From c45092a52cf4a953791d650a4c4449d3dfdda5c4 Mon Sep 17 00:00:00 2001 From: Robert Vokac Date: Mon, 22 Jul 2024 19:30:44 +0200 Subject: [PATCH] Refactoring II --- pom.xml | 2 +- .../org/nanoboot/youtubedlfrontend/Arg.java | 2 +- .../nanoboot/youtubedlfrontend/ArgType.java | 3 +- .../org/nanoboot/youtubedlfrontend/Main.java | 365 +++++------------- .../org/nanoboot/youtubedlfrontend/Utils.java | 5 +- .../youtubedlfrontend/YoutubeComment.java | 6 +- .../youtubedlfrontend/YoutubeVideo.java | 119 +++--- .../youtubedlfrontend/YoutubeVideoHtml.java | 178 +++++++++ .../YoutubedlFrontendException.java | 5 +- 9 files changed, 354 insertions(+), 331 deletions(-) create mode 100644 src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideoHtml.java diff --git a/pom.xml b/pom.xml index c7233d3..6365639 100644 --- a/pom.xml +++ b/pom.xml @@ -192,7 +192,7 @@ jackson-databind 2.17.1 - - - - - - """); - NumberFormat formatter = new DecimalFormat("#0.00"); - channels.forEach(c -> { - sb.append("

").append(c).append("

\n"); - sb.append("
").append(channelUrls.get(c)).append("
"); + 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)); + } + + 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; - sb.append("\n"); - youtubeVideos.stream().filter(v -> c.equals(v.getChannelName())).forEach(youtubeVideo -> { + oneChannelStringBuilder.append("
\n"); + youtubeVideos.stream().filter(v -> channel.equals(v.getChannelName())).forEach(youtubeVideo -> { iii++; if (internalStaticVariableVideoNumberPerRow == 0) { - sb.append(""); + oneChannelStringBuilder.append(""); } internalStaticVariableVideoNumberPerRow++; - sb.append("\n"); + oneChannelStringBuilder.append("
\n\n"); - sb.append("\n"); + oneChannelStringBuilder.append("\n"); String uploadDate = youtubeVideo.getUploadDate(); uploadDate = uploadDate.substring(0, 4) + "-" + uploadDate.substring(4, 6) + "-" + uploadDate.substring(6, 8); - sb.append("\n"); youtubeVideo.setNumber(iii); - sb.append("
").append(youtubeVideo.getTitle()).append("
").append(youtubeVideo.getTitle()).append("
").append(uploadDate).append(" •︎ ").append(youtubeVideo.getVideoDuration()) + oneChannelStringBuilder.append("
").append(uploadDate).append(" •︎ ").append(youtubeVideo.getVideoDuration()) .append(" •︎ ") .append("#").append(iii) .append("
\n"); if (internalStaticVariableVideoNumberPerRow == argsInstance.getInteger(ArgType.VIDEOS_PER_ROW).get()) { - sb.append(""); + oneChannelStringBuilder.append(""); internalStaticVariableVideoNumberPerRow = 0; } File videoHtmlFile = new File(videosDirectory, youtubeVideo.getId() + ".html"); if (!videoHtmlFile.exists() || argsInstance.getBoolean(ArgType.ALWAYS_GENERATE_HTML_FILES).get()) { { - StringBuilder videoHtml = new StringBuilder(""" - - - - - - """ - + youtubeVideo.getTitle() - + """ - - - - - """ - ); - String finalUrl = "https://www.youtube.com/watch?v=" + youtubeVideo.getId(); - - videoHtml.append("
\n
\n"); - videoHtml.append(""); - videoHtml.append(finalUrl).append("").append("
\n"); - String videoLocalUrl = ""; - try { - videoLocalUrl = "file:///" + archiveBoxRootDirectory.getAbsolutePath() + "/archive/" + youtubeVideo.getSnapshot() + "/media/" + URLEncoder.encode(youtubeVideo.getVideoFileName(), StandardCharsets.UTF_8.toString()).replace("+", "%20"); - } catch (UnsupportedEncodingException ex) { - throw new YoutubedlFrontendException(ex.getMessage()); - } - if (!youtubeVideo.getVideoFileName().endsWith(".mkv")) { - //try { - videoHtml.append("
- """); -// } catch (UnsupportedEncodingException ex) { -// throw new YoutubedlFrontendException(ex.getMessage()); -// } - } - else - { - videoHtml.append(""); - - videoHtml.append("
\n"); - } - videoHtml.append("").append(youtubeVideo.getTitle()).append(""); - videoHtml.append("
\n
\n"); - videoHtml.append("#").append(youtubeVideo.getNumber()).append("   "); - if (youtubeVideo.getPreviousVideoId() != null) { -// videoHtml.append(""); - videoHtml.append(" - } - videoHtml.append("Back"); - if (youtubeVideo.getPreviousVideoId() != null) { - //videoHtml.append(""); - videoHtml.append(""); - } - videoHtml.append("   "); - if (youtubeVideo.getNextVideoId() != null) { - //videoHtml.append(""); - videoHtml.append(""); - - } - videoHtml.append(" "); - videoHtml - .append("

Download "); - - videoHtml.append(formatter.format(((double) youtubeVideo.getVideoFileSizeInBytes()) / 1024d / 1024d)).append(" MB "); - if (youtubeVideo.getVideoFileName().endsWith(".mkv")) { - - String v = youtubeVideo.getVideoFileName().replaceAll(" ", "\\\\ "); - v = v.replace("(", "\\("); - v = v.replace(")", "\\)"); - var vWebm = v.substring(0, v.length() - 3) + "webm"; - - videoHtml.append("
"); - - } else { - - - videoHtml.append("
"); - } - videoHtml.append("Directory").append("
"); - videoHtml.append("
\n
\n"); - - videoHtml.append("
\n"); - videoHtml.append("
");
-                        videoHtml.append(youtubeVideo.getDescription().isBlank() ? "No description" : youtubeVideo.getDescription());
-                        videoHtml.append("
"); - videoHtml.append("

Comments

"); - youtubeVideo.getComments().forEach(co -> { - -// private String id, parentId, text, author; -// private int timestamp; - videoHtml.append("
"); - videoHtml.append("

").append(co.getAuthor()).append("

"); - - videoHtml.append("") - .append(Utils.DATE_FORMAT.format(new Date(co.getTimestamp() * 1000))).append("
\n"); - videoHtml.append("").append(co.getId()).append(" ") - .append(co.getParentId()).append("
\n"); - videoHtml.append("
").append(co.getText()).append("
"); - videoHtml.append("
"); - }); - -// private String id; -// -// private String title; -// private String videoFileName = ""; -// private long videoFileSizeInBytes = 0; -// private String videoFileSha512HashSum = ""; -// private String videoDuration = ""; -// private String channelName; -// private String channelUrl; -// private String channelId; -// private String uploadDate; -// private String description; -// private String thumbnail; -// private List comments = new ArrayList<>(); - videoHtml.append(""); - String singleVideo = videoHtml.toString(); - //singleVideo.replace("
\n", "
\n\n"); + String singleVideo = new YoutubeVideoHtml(youtubeVideo, archiveBoxRootDirectory, archiveBoxArchiveDirectory).toString(); Utils.writeTextToFile(singleVideo, videoHtmlFile); } } }); if (internalStaticVariableVideoNumberPerRow < argsInstance.getInteger(ArgType.VIDEOS_PER_ROW).get()) { - sb.append(""); + oneChannelStringBuilder.append(""); } - sb.append("\n"); - sb.append("
"); + oneChannelStringBuilder.append("\n"); + oneChannelStringBuilder.append("
"); + } + oneChannelStringBuilder.append(""); }); - sb.append(""" - - - - - """); - Utils.writeTextToFile(sb.toString(), videosHtmlFile); - - System.out.println("[Warning] Snapshots without videos:"); - YoutubeVideo.missingYoutubeVideos.forEach(s -> System.out.println(s)); + oneChannelStringBuilder.append(""" + + + """); + return oneChannelStringBuilder; } + + } diff --git a/src/main/java/org/nanoboot/youtubedlfrontend/Utils.java b/src/main/java/org/nanoboot/youtubedlfrontend/Utils.java index b8ec709..3bbf2bc 100644 --- a/src/main/java/org/nanoboot/youtubedlfrontend/Utils.java +++ b/src/main/java/org/nanoboot/youtubedlfrontend/Utils.java @@ -24,7 +24,6 @@ import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; @@ -35,6 +34,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.*; import javax.imageio.ImageIO; @@ -48,6 +49,7 @@ public class Utils { private static final String UNDERSCORE = "_"; public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + public static final NumberFormat TWO_DECIMAL_POINTS_FORMATTER = new DecimalFormat("#0.00"); private Utils() { //Not meant to be instantiated. } @@ -187,6 +189,7 @@ public class Utils { throw new YoutubedlFrontendException("Could not create boolean from String: " + s); } } + public static byte[] resizeImage(InputStream inputStream, int width, int height, String formatName) throws IOException { BufferedImage sourceImage = ImageIO.read(inputStream); Image thumbnail = sourceImage.getScaledInstance(width, height, Image.SCALE_SMOOTH); diff --git a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeComment.java b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeComment.java index 6fbdee9..4be30b3 100644 --- a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeComment.java +++ b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeComment.java @@ -43,13 +43,15 @@ public class YoutubeComment implements Comparable { author = jsonObject.getString("author"); timestamp = jsonObject.getInt("timestamp"); } + public static List sort(List list) { - + List root = getChildren(list, "root"); Collections.sort(root); return list; //return sort(list, new ArrayList<>(), "root"); } + private static List getChildren(List all, String parentId) { final List children = all.stream().filter(c -> c.getParentId().equals(parentId)).sorted().toList(); List result = new ArrayList<>(); @@ -59,7 +61,7 @@ public class YoutubeComment implements Comparable { }); return result; } - + @Override public int compareTo(YoutubeComment o) { //if(this.timestamp != o.timestamp) { diff --git a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideo.java b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideo.java index 29bca69..0266293 100644 --- a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideo.java +++ b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideo.java @@ -20,6 +20,7 @@ import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Properties; @@ -63,7 +64,7 @@ public class YoutubeVideo implements Comparable { public YoutubeVideo(File mediaDirectory, boolean argAlwaysGenerateMetadata, String argVideo) throws InterruptedException, IOException { File metadataFile = new File(mediaDirectory, "metadata"); - if (argAlwaysGenerateMetadata && metadataFile.exists()) { + if (!argAlwaysGenerateMetadata && metadataFile.exists()) { YoutubeVideo yv = new YoutubeVideo(); //new ObjectMapper().readValue(Utils.readTextFromFile(metadataFile), YoutubeVideo.class); @@ -131,7 +132,7 @@ public class YoutubeVideo implements Comparable { continue; } else { int width = o.getInt("width"); - if (width < (((double)Main.THUMBNAIL_WIDTH) * 0.8d)) { + if (width < (((double) Main.THUMBNAIL_WIDTH) * 0.8d)) { continue; } miniThumbnail = o.getString("url"); @@ -147,7 +148,6 @@ public class YoutubeVideo implements Comparable { // new File(mediaDirectory, "mini-thumbnail.jpg").delete(); // new File(mediaDirectory, "thumbnail.webp").delete(); // new File(mediaDirectory, "mini-thumbnail.webp").delete(); - if (thumbnail != null) { if (!thumbnailFile.exists()) { try (BufferedInputStream in = new BufferedInputStream(new URL(thumbnail).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(thumbnailFile.getAbsolutePath())) { @@ -171,35 +171,7 @@ public class YoutubeVideo implements Comparable { System.out.println(e.getMessage()); } } -// for (String s : ImageIO.getReaderFormatNames()) { -// System.out.println(s); -// } - //if(!miniThumbnailFile.exists()) { -//String miniThumbnailFileAbsolutePath = miniThumbnailFile.getAbsolutePath(); -// String formatName = miniThumbnailFileAbsolutePath.substring(miniThumbnailFileAbsolutePath -// .lastIndexOf(".") + 1); -// BufferedImage inputImage = ImageIO.read(thumbnailFile); -// if(inputImage == null) { -// -// } -// int thumbnailWidth = inputImage.getWidth(); -// int thumbnailHeight = inputImage.getHeight(); -// double heightWidthRatio = ((double) thumbnailHeight) / ((double) thumbnailWidth); -// int miniThumbnailWidth = Main.THUMBNAIL_WIDTH; -// int miniThumbnailHeight = (int) (heightWidthRatio * ((double) Main.THUMBNAIL_WIDTH)); -// -// BufferedImage outputImage = new BufferedImage(miniThumbnailWidth, -// miniThumbnailHeight, inputImage.getType()); -// -// Graphics2D g2d = outputImage.createGraphics(); -// g2d.drawImage(inputImage, 0, 0, miniThumbnailWidth, miniThumbnailHeight, null); -// g2d.dispose(); -// -// -// -// ImageIO.write(outputImage, formatName, new File(miniThumbnailFileAbsolutePath)); - //} } // Optional descriptionFile = files.stream().filter(f -> f.getName().endsWith(".description")).findFirst(); @@ -211,14 +183,9 @@ public class YoutubeVideo implements Comparable { .filter(f -> (f.getName().endsWith("." + ext)) || (f.getName().endsWith(".mp4")) - || (f.getName().endsWith(".mkv"))|| (f.getName().endsWith(".webm")) + || (f.getName().endsWith(".mkv")) || (f.getName().endsWith(".webm")) ) - // .filter( - // f -> !f.getName().endsWith(".description") - // && !f.getName().endsWith(".json") - // && !f.getName().equals("metadata") - // && !f.getName().endsWith(thumbnail) - // ) + .findFirst(); snapshot = mediaDirectory.getParentFile().getName(); @@ -303,23 +270,24 @@ public class YoutubeVideo implements Comparable { public String getMiniThumbnailFormat() { return getExtensionFromUrl(miniThumbnail); } + private String getExtensionFromUrl(String url) { - String result = url.substring(url + String result = url.substring(url .lastIndexOf(".") + 1); int questionMarkIndex = 0; - for(int i = 0;i 0) { + if (questionMarkIndex > 0) { result = result.substring(0, questionMarkIndex); } return result; - + } /** @@ -359,4 +327,69 @@ public class YoutubeVideo implements Comparable { } } + public static List loadYoutubeVideos(File archiveBoxArchiveDirectory, Args argsInstance) throws IOException, InterruptedException { + int i = 0; + List youtubeVideos = new ArrayList<>(); + for (File snapshotDirectory : archiveBoxArchiveDirectory.listFiles()) { + //if(i> 40)break;//only for tests + File mediaDirectory = new File(snapshotDirectory, "media"); + if (!mediaDirectory.exists()) { + //nothing to do + continue; + } + YoutubeVideo youtubeVideo = new YoutubeVideo(mediaDirectory, argsInstance.getBoolean(ArgType.ALWAYS_GENERATE_METADATA).get(), argsInstance.getString(ArgType.VIDEO).orElse("")); + if (argsInstance.getString(ArgType.VIDEO).isPresent() && !argsInstance.getString(ArgType.VIDEO).equals(youtubeVideo.getId())) { + continue; + } + if (argsInstance.getString(ArgType.CHANNEL).isPresent() && !argsInstance.getString(ArgType.CHANNEL).equals(youtubeVideo.getChannelId())) { + continue; + } + + i++; + System.out.println("\n\nFound video #" + i); + + for (File f : new File(archiveBoxArchiveDirectory + "/" + youtubeVideo.getSnapshot() + "/media/" + youtubeVideo.getVideoFileName()).getParentFile().listFiles()) { + if (f.getName().endsWith(".webm")) { + //mkv file was manually converted to webm + youtubeVideo.setVideoFileName(f.getName()); + break; + } + + } + System.out.println("id = " + youtubeVideo.getId()); + System.out.println("snapshot = " + youtubeVideo.getSnapshot()); + System.out.println("title = " + youtubeVideo.getTitle()); + System.out.println("videoFileName = " + youtubeVideo.getVideoFileName()); + System.out.println("videoFileSizeInBytes = " + youtubeVideo.getVideoFileSizeInBytes()); + System.out.println("videoFileSha512HashSum = " + youtubeVideo.getVideoFileSha512HashSum()); + System.out.println("videoDuration = " + youtubeVideo.getVideoDuration()); + System.out.println("channelName = " + youtubeVideo.getChannelName()); + System.out.println("channelUrl = " + youtubeVideo.getChannelUrl()); + System.out.println("uploadDate = " + youtubeVideo.getUploadDate()); + System.out.println("description = " + youtubeVideo.getDescription()); + System.out.println("thumbnail = " + youtubeVideo.getThumbnail()); + System.out.println("miniThumbnail = " + youtubeVideo.getMiniThumbnail()); + System.out.println("comments = " + youtubeVideo.getComments()); + youtubeVideos.add(youtubeVideo); + } + Collections.sort(youtubeVideos); + YoutubeVideo previousVideo = null; + YoutubeVideo nextVideo = null; + YoutubeVideo currentVideo = null; + for (int j = 0; j < youtubeVideos.size(); j++) { + previousVideo = currentVideo; + currentVideo = youtubeVideos.get(j); + if (j < (youtubeVideos.size() - 1)) { + nextVideo = youtubeVideos.get(j + 1); + } + if (previousVideo != null) { + currentVideo.setPreviousVideoId(previousVideo.getId()); + } + if (nextVideo != null) { + currentVideo.setNextVideoId(nextVideo.getId()); + } + } + return youtubeVideos; + } + } diff --git a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideoHtml.java b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideoHtml.java new file mode 100644 index 0000000..52548be --- /dev/null +++ b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubeVideoHtml.java @@ -0,0 +1,178 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// 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.File; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.text.NumberFormat; +import java.util.Date; +import lombok.Getter; + +/** + * + * @author robertvokac + */ +public class YoutubeVideoHtml { + + @Getter + private String singleVideo; + + public YoutubeVideoHtml(YoutubeVideo youtubeVideo, File archiveBoxRootDirectory, File archiveBoxArchiveDirectory) { + + StringBuilder videoHtml = new StringBuilder(""" + + + + + + """ + + youtubeVideo.getTitle() + + """ + + + + + """ + ); + String finalUrl = "https://www.youtube.com/watch?v=" + youtubeVideo.getId(); + videoHtml.append("
\n
\n"); + videoHtml.append(""); + videoHtml.append(finalUrl).append("").append("
\n"); + String videoLocalUrl = ""; + try { + videoLocalUrl = "file:///" + archiveBoxRootDirectory.getAbsolutePath() + "/archive/" + youtubeVideo.getSnapshot() + "/media/" + URLEncoder.encode(youtubeVideo.getVideoFileName(), StandardCharsets.UTF_8.toString()).replace("+", "%20"); + } catch (UnsupportedEncodingException ex) { + throw new YoutubedlFrontendException(ex.getMessage()); + } + if (!youtubeVideo.getVideoFileName().endsWith(".mkv")) { + //try { + videoHtml.append("
+ """); +// } catch (UnsupportedEncodingException ex) { +// throw new YoutubedlFrontendException(ex.getMessage()); +// } + } else { + videoHtml.append(""); + + videoHtml.append("
\n"); + } + videoHtml.append("").append(youtubeVideo.getTitle()).append(""); + videoHtml.append("
\n
\n"); + videoHtml.append("#").append(youtubeVideo.getNumber()).append("   "); + if (youtubeVideo.getPreviousVideoId() != null) { +// videoHtml.append(""); +videoHtml.append(" + } + videoHtml.append("Back"); + if (youtubeVideo.getPreviousVideoId() != null) { + //videoHtml.append(""); + videoHtml.append(""); + } + videoHtml.append("   "); + if (youtubeVideo.getNextVideoId() != null) { + //videoHtml.append(""); + videoHtml.append(""); + + } + videoHtml.append(" "); + videoHtml + .append("

Download "); + videoHtml.append(Utils.TWO_DECIMAL_POINTS_FORMATTER.format(((double) youtubeVideo.getVideoFileSizeInBytes()) / 1024d / 1024d)).append(" MB "); + if (youtubeVideo.getVideoFileName().endsWith(".mkv")) { + + String v = youtubeVideo.getVideoFileName().replaceAll(" ", "\\\\ "); + v = v.replace("(", "\\("); + v = v.replace(")", "\\)"); + var vWebm = v.substring(0, v.length() - 3) + "webm"; + + videoHtml.append("
"); + + } else { + + videoHtml.append("
"); + } + videoHtml.append("Directory").append("
"); + videoHtml.append("
\n
\n"); + videoHtml.append("
\n"); + videoHtml.append("
");
+        videoHtml.append(youtubeVideo.getDescription().isBlank() ? "No description" : youtubeVideo.getDescription());
+        videoHtml.append("
"); + videoHtml.append("

Comments

"); + youtubeVideo.getComments().forEach(co -> { + +// private String id, parentId, text, author; +// private int timestamp; +videoHtml.append("
"); +videoHtml.append("

").append(co.getAuthor()).append("

"); + +videoHtml.append("") + .append(Utils.DATE_FORMAT.format(new Date(co.getTimestamp() * 1000))).append("
\n"); +videoHtml.append("").append(co.getId()).append(" ") + .append(co.getParentId()).append("
\n"); +videoHtml.append("
").append(co.getText()).append("
"); +videoHtml.append("
"); + }); + videoHtml.append(""); + singleVideo = videoHtml.toString(); + + } + @Override + public String toString() { + return this.singleVideo; + } + +} diff --git a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubedlFrontendException.java b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubedlFrontendException.java index 8ce1629..ccc2ce4 100644 --- a/src/main/java/org/nanoboot/youtubedlfrontend/YoutubedlFrontendException.java +++ b/src/main/java/org/nanoboot/youtubedlfrontend/YoutubedlFrontendException.java @@ -16,7 +16,6 @@ // 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; /** @@ -32,5 +31,5 @@ public class YoutubedlFrontendException extends RuntimeException { public YoutubedlFrontendException(String msg, Exception e) { super(msg, e); } - -} \ No newline at end of file + +}