/////////////////////////////////////////////////////////////////////////////////////////////// // youtubedl-frontend: Tool generating html pages for Archive Box. // Copyright (C) 2024 the original author or authors. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; version 2 // of the License only. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. /////////////////////////////////////////////////////////////////////////////////////////////// package org.nanoboot.youtubedlfrontend; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import static org.nanoboot.youtubedlfrontend.Args.TWO_DASHES; /** * @author Robert Vokac * @since 0.0.0 */ public class Main { private static int iii = 0; private static int internalStaticVariableVideoNumberPerRow = 0; public static int THUMBNAIL_WIDTH = 250; public static void main(String[] args) throws IOException, InterruptedException { System.out.println("youtubedlfrontend - HTML generator\n"); if (args.length < 1) { //System.err.println("At least one argument is expected, but the count of arguments is: " + args.length + "."); String argsS = "/rv/blupi/archivebox --video_ 7qKUtn76q30 --always-generate-metadata 0" + " --always-generate-html-files 0 --videos-per-row 4 --thumbnail-links-to-youtube 0" + " --thumbnail-as-base64 0" + " --channel_ UCqBpgfXap7cZOYkAC34u8Lg "; args = argsS.split(" "); //System.exit(1); } Args argsInstance = new Args(args); System.out.println(argsInstance.toString()); String workingDirectory = args.length > 0 && !args[0].startsWith(TWO_DASHES) ? args[0] : new File(".").getAbsolutePath(); File archiveBoxRootDirectory = new File(workingDirectory); File archiveBoxArchiveDirectory = new File(archiveBoxRootDirectory, "archive"); List youtubeVideos = YoutubeVideo.loadYoutubeVideos(archiveBoxArchiveDirectory, argsInstance); Map channelUrls = new HashMap<>(); List channels = new ArrayList<>(); youtubeVideos.stream().forEach(c -> { final String channelName_ = c.getChannelName(); if (channelName_ != null && !channelUrls.containsKey(c.getChannelName())) { channelUrls.put(channelName_, c.getChannelUrl()); channels.add(channelName_); } }); Collections.sort(channels, (String o1, String o2) -> o1.toLowerCase().compareTo(o2.toLowerCase())); File videosHtmlFile = new File(archiveBoxRootDirectory, "videos.html"); File videosDirectory = new File(archiveBoxRootDirectory, "videos"); File channelsDirectory = new File(archiveBoxRootDirectory, "channels"); if (!videosDirectory.exists()) { videosDirectory.mkdir(); } if (!channelsDirectory.exists()) { channelsDirectory.mkdir(); } channels.stream().forEach(c -> { StringBuilder oneChannelStringBuilder = createChannelHtml(c, channels, argsInstance, channelUrls, youtubeVideos, archiveBoxRootDirectory, videosDirectory, archiveBoxArchiveDirectory); Utils.writeTextToFile(oneChannelStringBuilder.toString(), new File(channelsDirectory, channelUrls.get(c).split("/channel/")[1] + ".html")); }); StringBuilder oneChannelStringBuilder = createChannelHtml(null, channels, argsInstance, channelUrls, youtubeVideos, archiveBoxRootDirectory, videosDirectory, archiveBoxArchiveDirectory); Utils.writeTextToFile(oneChannelStringBuilder.toString(), videosHtmlFile); System.out.println("[Warning] Snapshots without videos:"); YoutubeVideo.missingYoutubeVideos.forEach(s -> System.out.println(s)); System.out.println("Total duration: " + ((int)((((double)YoutubeVideo.totalDurationInMilliseconds) / 1000d / 60d / 60d))) + " hours"); youtubeVideos.sort(new Comparator() { @Override public int compare(YoutubeVideo o1, YoutubeVideo o2) { return Long.valueOf(o1.getVideoDurationInMilliseconds()).compareTo(o2.getVideoDurationInMilliseconds()); } }); youtubeVideos.forEach(y-> {System.out.println(y.getVideoDurationInMinutes() + " = minutes \t" + "https://youtube.com/watch?v=" + y.getId() + "\t" + y.getTitle());}); System.out.println("\n\n\n\n"); youtubeVideos.sort(new Comparator() { @Override public int compare(YoutubeVideo o1, YoutubeVideo o2) { return Long.valueOf(o1.getVideoFileSizeInBytes()).compareTo(o2.getVideoFileSizeInBytes()); } }); youtubeVideos.forEach(y-> {System.out.println(y.getVideoFileSizeInMegaBytes()+ " MB \t" + "https://youtube.com/watch?v=" + y.getId() + "\t" + y.getTitle());}); } private static StringBuilder createChannelHtml(String wantedChannelName, List channels, Args argsInstance, Map channelUrls, List youtubeVideos, File archiveBoxRootDirectory, File videosDirectory, File archiveBoxArchiveDirectory) { StringBuilder oneChannelStringBuilder = new StringBuilder(); oneChannelStringBuilder.append(""" Youtube videos """); channels.stream().filter(c -> wantedChannelName == null ? true : c.equals(wantedChannelName)).forEach(channel -> { oneChannelStringBuilder.append("

").append(channel).append("

\n"); oneChannelStringBuilder.append("
"); oneChannelStringBuilder.append("").append("Videos").append(""); oneChannelStringBuilder.append("   ( ").append(channelUrls.get(channel)).append(" )"); if(wantedChannelName != null) { oneChannelStringBuilder.append("
"); iii = 0; internalStaticVariableVideoNumberPerRow = 0; oneChannelStringBuilder.append("\n"); youtubeVideos.stream().filter(v -> channel.equals(v.getChannelName())).forEach(youtubeVideo -> { iii++; if (internalStaticVariableVideoNumberPerRow == 0) { oneChannelStringBuilder.append(""); } internalStaticVariableVideoNumberPerRow++; oneChannelStringBuilder.append("\n"); if (internalStaticVariableVideoNumberPerRow == argsInstance.getInteger(ArgType.VIDEOS_PER_ROW).get()) { oneChannelStringBuilder.append(""); internalStaticVariableVideoNumberPerRow = 0; } File videoHtmlFile = new File(videosDirectory, youtubeVideo.getId() + ".html"); if (!videoHtmlFile.exists() || argsInstance.getBoolean(ArgType.ALWAYS_GENERATE_HTML_FILES).get()) { { String singleVideo = new YoutubeVideoHtml(youtubeVideo, archiveBoxRootDirectory, archiveBoxArchiveDirectory).toString(); Utils.writeTextToFile(singleVideo, videoHtmlFile); } } }); if (internalStaticVariableVideoNumberPerRow < argsInstance.getInteger(ArgType.VIDEOS_PER_ROW).get()) { oneChannelStringBuilder.append(""); } oneChannelStringBuilder.append("
\n\n"); oneChannelStringBuilder.append("\n"); String uploadDate = youtubeVideo.getUploadDate(); uploadDate = uploadDate.substring(0, 4) + "-" + uploadDate.substring(4, 6) + "-" + uploadDate.substring(6, 8); oneChannelStringBuilder.append("\n"); youtubeVideo.setNumber(iii); oneChannelStringBuilder.append("
").append(youtubeVideo.getTitle()).append("
").append(uploadDate).append(" •︎ ").append(youtubeVideo.getVideoDuration()) .append(" •︎ ") .append("#").append(iii) .append("
\n"); oneChannelStringBuilder.append("
"); } oneChannelStringBuilder.append("
"); }); oneChannelStringBuilder.append(""" """); return oneChannelStringBuilder; } }