diff --git a/.gitignore b/.gitignore index 6d4941d..71d2f22 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,9 @@ target/ # Gradle .gradle -gradle \ No newline at end of file +gradle + +# eclipse +.settings/ +.classpath +.project \ No newline at end of file diff --git a/README.md b/README.md index f40153b..1dcd23e 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,29 @@ dependencies { } ``` +### Maven + +*Step 1 :* Add jitpack repository to your pom.xml file + +``` + + + jitpack.io + https://jitpack.io + + +``` + +*Step 2:* Add the dependency + +``` + + com.github.sapher + youtubedl-java + 1.+ + +``` + ## Make request ```java diff --git a/pom.xml b/pom.xml index 58c79ee..4b54264 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.sapher youtubedl - 1.1 + 1.3-print-info jar YoutubeDL wrapper diff --git a/src/main/java/com/sapher/youtubedl/YoutubeDL.java b/src/main/java/com/sapher/youtubedl/YoutubeDL.java index 6cb26ec..00925be 100644 --- a/src/main/java/com/sapher/youtubedl/YoutubeDL.java +++ b/src/main/java/com/sapher/youtubedl/YoutubeDL.java @@ -140,9 +140,10 @@ public static VideoInfo getVideoInfo(String url) throws YoutubeDLException { // Parse result ObjectMapper objectMapper = new ObjectMapper(); VideoInfo videoInfo; - + try { videoInfo = objectMapper.readValue(response.getOut(), VideoInfo.class); + System.out.println("videoInfo="+videoInfo.toString()); } catch (IOException e) { throw new YoutubeDLException("Unable to parse video information: " + e.getMessage()); } diff --git a/src/main/java/com/sapher/youtubedl/YoutubeDLProxychains.java b/src/main/java/com/sapher/youtubedl/YoutubeDLProxychains.java new file mode 100644 index 0000000..4344795 --- /dev/null +++ b/src/main/java/com/sapher/youtubedl/YoutubeDLProxychains.java @@ -0,0 +1,133 @@ +package com.sapher.youtubedl; + +import java.io.IOException; +import java.util.List; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.sapher.youtubedl.mapper.VideoFormat; +import com.sapher.youtubedl.mapper.VideoInfo; +import com.sapher.youtubedl.mapper.VideoThumbnail; + +/** + * @author memento + * This class is child class from YoutubeDL that allows to use youtube-dl behind a Tor "Proxychains" software to avoid BAN for example. + * + * Test class: YoutubeDLProxychainsTest + * + * Before using this class, be sure you have installed proxychains on your machine + * If you're using debian/ubuntu, install this powerful tool by typing this in your terminal : + * > sudo apt-get install proxychains tor obfsproxy + * + * (Other linux distributions : https://www.linuxsecrets.com/3372-install-setup-proxychains-on-linux ) + * + * Normally, to use youtube-dl behind proxychains, you'd execute (example) : + * > proxychains youtube-dl https://www.youtube.com/watch?v=nMfPqeZjc2c + * + * pros : you stay anonymous and you avoid being ban + * cons : the queries take longer + * + */ +public class YoutubeDLProxychains extends YoutubeDL{ + + /** + * Execute youtube-dl request + * @param request request object + * @return response object + * @throws YoutubeDLException + */ + public static YoutubeDLResponse execute(YoutubeDLRequest request) throws YoutubeDLException { + //We use proxychains, here + setExecutablePath("proxychains youtube-dl"); + return execute(request, null); + } + + /** + * Retrieve all information available on a video + * @param url Video url + * @return Video info + * @throws YoutubeDLException + */ + public static VideoInfo getVideoInfo(String url) throws YoutubeDLException { + //We use proxychains, here + setExecutablePath("proxychains youtube-dl"); + + // Build request + YoutubeDLRequest request = new YoutubeDLRequest(url); + request.setOption("dump-json"); + request.setOption("no-playlist"); + YoutubeDLResponse response = execute(request); + + // Parse result + ObjectMapper objectMapper = new ObjectMapper(); + VideoInfo videoInfo; + + //Proxychains : remove proxychains header ex: "ProxyChains-3.1 (http://proxychains.sf.net)\n" + String output = response.getOut(); + output = output.substring(output.indexOf("{")); + + try { + videoInfo = objectMapper.readValue(output, VideoInfo.class); + System.out.println("videoInfo="+videoInfo.toString()); + } catch (IOException e) { + throw new YoutubeDLException("Unable to parse video information: " + e.getMessage()); + } + + return videoInfo; + } + + /** + * List formats + * @param url Video url + * @return list of formats + * @throws YoutubeDLException + */ + public static List getFormats(String url) throws YoutubeDLException { + //We use proxychains, here + setExecutablePath("proxychains youtube-dl"); + + VideoInfo info = getVideoInfo(url); + return info.formats; + } + + /** + * List thumbnails + * @param url Video url + * @return list of thumbnail + * @throws YoutubeDLException + */ + public static List getThumbnails(String url) throws YoutubeDLException { + //We use proxychains, here + setExecutablePath("proxychains youtube-dl"); + + VideoInfo info = getVideoInfo(url); + return info.thumbnails; + } + + /** + * List categories + * @param url Video url + * @return list of category + * @throws YoutubeDLException + */ + public static List getCategories(String url) throws YoutubeDLException { + //We use proxychains, here + setExecutablePath("proxychains youtube-dl"); + + VideoInfo info = getVideoInfo(url); + return info.categories; + } + + /** + * List tags + * @param url Video url + * @return list of tag + * @throws YoutubeDLException + */ + public static List getTags(String url) throws YoutubeDLException { + //We use proxychains, here + setExecutablePath("proxychains youtube-dl"); + + VideoInfo info = getVideoInfo(url); + return info.tags; + } +} diff --git a/src/main/java/com/sapher/youtubedl/mapper/VideoInfo.java b/src/main/java/com/sapher/youtubedl/mapper/VideoInfo.java index ddbdf8d..0495804 100644 --- a/src/main/java/com/sapher/youtubedl/mapper/VideoInfo.java +++ b/src/main/java/com/sapher/youtubedl/mapper/VideoInfo.java @@ -19,10 +19,63 @@ public class VideoInfo { public String description; public String thumbnail; public String license; + + @JsonProperty("view_count") + public String viewCount; + @JsonProperty("like_count") + public String likeCount; + @JsonProperty("dislike_count") + public String dislikeCount; + @JsonProperty("repost_count") + public String repostCount; + @JsonProperty("average_rating") + public String averageRating; + @JsonProperty("uploader_id") public String uploaderId; public String uploader; + + @JsonProperty("channel_url") + public String channelUrl; + + @JsonProperty("channel_id") + public String channelId; + + @JsonProperty("uploader_url") + public String uploaderUrl; + + public String track; + public String playlist; + @JsonProperty("playlist_index") + public String playlistIndex; + @JsonProperty("episode_number") + public String episodeNumber; + @JsonProperty("season_number") + public String seasonNumber; + + @JsonProperty("is_live") + public String isLive; + public String series; + + @JsonProperty("release_date") + public String releaseDate; + @JsonProperty("release_year") + public String releaseYear; + + + @JsonProperty("scan_date") + public String scanDate; + + public String creator; + public String artist; + @JsonProperty("alt_title") + public String altTitle; + @JsonProperty("extractor_key") + public String extractorKey; + public String chapters; + public String album; + @JsonProperty("player_url") public String playerUrl; @@ -44,4 +97,69 @@ public class VideoInfo { public ArrayList formats; public ArrayList thumbnails; //public ArrayList subtitles; + + //some useful getters + public String getViewCount() { + return viewCount; + } + public String getLikeCount() { + return likeCount; + } + public String getDislikeCount() { + return dislikeCount; + } + public String getRepostCount() { + return repostCount; + } + public String getAverageRating() { + return averageRating; + } + public String getId() { + return id; + } + public String getFulltitle() { + return fulltitle; + } + public String getTitle() { + return title; + } + public String getUploadDate() { + return uploadDate; + } + public int getDuration() { + return duration; + } + public String getDescription() { + return description; + } + public String getThumbnail() { + return thumbnail; + } + public String getUploaderId() { + return uploaderId; + } + public String getUploader() { + return uploader; + } + @Override + public String toString() { + return "VideoInfo [id=" + id + "\n, fulltitle=" + fulltitle + "\n, title=" + title + "\n, uploadDate=" + uploadDate + + "\n, displayId=" + displayId + "\n, duration=" + duration + "\n, description=" + description + + "\n, thumbnail=" + thumbnail + "\n, license=" + license + "\n, viewCount=" + viewCount + "\n, likeCount=" + + likeCount + "\n, dislikeCount=" + dislikeCount + "\n, repostCount=" + repostCount + "\n, averageRating=" + + averageRating + "\n, uploaderId=" + uploaderId + "\n, uploader=" + uploader + "\n, channelUrl=" + channelUrl + + "\n, channelId=" + channelId + "\n, uploaderUrl=" + uploaderUrl + "\n, track=" + track + "\n, playlist=" + + playlist + "\n, playlistIndex=" + playlistIndex + "\n, episodeNumber=" + episodeNumber + "\n, seasonNumber=" + + seasonNumber + "\n, isLive=" + isLive + "\n, series=" + series + "\n, releaseDate=" + releaseDate + + "\n, releaseYear=" + releaseYear + "\n, scanDate=" + scanDate + "\n, creator=" + creator + "\n, artist=" + + artist + "\n, altTitle=" + altTitle + "\n, extractorKey=" + extractorKey + "\n, chapters=" + chapters + + "\n, album=" + album + "\n, playerUrl=" + playerUrl + "\n, webpageUrl=" + webpageUrl + + "\n, webpageUrlBasename=" + webpageUrlBasename + "\n, resolution=" + resolution + "\n, width=" + width + + "\n, height=" + height + "\n, format=" + format + "\n, ext=" + ext + "\n, httpHeader=" + httpHeader + + "\n, categories=" + categories + "\n, tags=" + tags + "\n, formats=" + formats + "\n, thumbnails=" + + thumbnails + "]"; + } + + + } diff --git a/src/test/java/com/sapher/youtubedl/YoutubeDLProxychainsTest.java b/src/test/java/com/sapher/youtubedl/YoutubeDLProxychainsTest.java new file mode 100644 index 0000000..9af2ace --- /dev/null +++ b/src/test/java/com/sapher/youtubedl/YoutubeDLProxychainsTest.java @@ -0,0 +1,155 @@ +package com.sapher.youtubedl; + +import com.sapher.youtubedl.mapper.VideoFormat; +import com.sapher.youtubedl.mapper.VideoInfo; +import com.sapher.youtubedl.mapper.VideoThumbnail; +import com.sapher.youtubedl.YoutubeDLProxychains; +import org.junit.Test; +import org.junit.Assert; + +import java.util.List; + +public class YoutubeDLProxychainsTest{ + + private final static String DIRECTORY = System.getProperty("java.io.tmpdir"); + //private final static String VIDEO_URL = "https://www.youtube.com/watch?v=nMfPqeZjc2c"; + private final static String VIDEO_URL = "https://www.youtube.com/watch?v=x3hGMgd2X14"; + private final static String NONE_EXISTENT_VIDEO_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcZ"; + + /**@Test + public void testUsingOwnExecutablePath() throws YoutubeDLException { + YoutubeDLProxychains.setExecutablePath("/usr/bin/youtube-dl"); + Assert.assertNotNull(YoutubeDLProxychains.getVersion()); + }**/ + + @Test + public void testGetVersion() throws YoutubeDLException { + Assert.assertNotNull(YoutubeDLProxychains.getVersion()); + } + + @Test + public void testElapsedTime() throws YoutubeDLException { + + long startTime = System.nanoTime(); + + YoutubeDLRequest request = new YoutubeDLRequest(); + request.setOption("version"); + YoutubeDLResponse response = YoutubeDLProxychains.execute(request); + + int elapsedTime = (int) (System.nanoTime() - startTime); + + Assert.assertTrue(elapsedTime > response.getElapsedTime()); + } + + + @Test + public void testSimulateDownload() throws YoutubeDLException { + + YoutubeDLRequest request = new YoutubeDLRequest(); + request.setUrl(VIDEO_URL); + request.setOption("simulate"); + + YoutubeDLResponse response = YoutubeDLProxychains.execute(request); + System.out.println(response.getCommand()); + Assert.assertEquals("proxychains youtube-dl " + VIDEO_URL + " --simulate", response.getCommand()); + } + + @Test + public void testDirectory() throws YoutubeDLException { + + YoutubeDLRequest request = new YoutubeDLRequest(VIDEO_URL, DIRECTORY); + request.setOption("simulate"); + + YoutubeDLResponse response = YoutubeDLProxychains.execute(request); + + Assert.assertEquals(DIRECTORY, response.getDirectory()); + } + + @Test + public void testGetVideoInfo() throws YoutubeDLException { + VideoInfo videoInfo = YoutubeDLProxychains.getVideoInfo(VIDEO_URL); + Assert.assertNotNull(videoInfo); + } + + @Test + public void testGetVideoInfoInDetails() throws YoutubeDLException { + VideoInfo videoInfo = YoutubeDLProxychains.getVideoInfo(VIDEO_URL); + Assert.assertNotNull(videoInfo); + //Let's check we can access key elements from video info + Assert.assertNotNull(videoInfo.getId()); + Assert.assertNotNull(videoInfo.getTitle()); + Assert.assertNotNull(videoInfo.getFulltitle()); + Assert.assertNotNull(videoInfo.getDescription()); + Assert.assertNotNull(videoInfo.getThumbnail()); + Assert.assertNotNull(videoInfo.getUploaderId()); + Assert.assertNotNull(videoInfo.getUploader()); + Assert.assertNotNull(videoInfo.getUploadDate()); + Assert.assertNotNull(videoInfo.getDuration()); + Assert.assertNotNull(videoInfo.getViewCount()); + Assert.assertNotNull(videoInfo.getLikeCount()); + Assert.assertNotNull(videoInfo.getDislikeCount()); + Assert.assertNotNull(videoInfo.getAverageRating()); + //Let's print the whole object + System.out.println("videoInfo:"+videoInfo.toString()); + + + } + + @Test + public void testGetVideoInfoInDetailsWithProxychains() throws YoutubeDLException { + VideoInfo videoInfo = YoutubeDLProxychains.getVideoInfo(VIDEO_URL); + Assert.assertNotNull(videoInfo); + //Let's check we can access key elements from video info + Assert.assertNotNull(videoInfo.getId()); + Assert.assertNotNull(videoInfo.getTitle()); + Assert.assertNotNull(videoInfo.getFulltitle()); + Assert.assertNotNull(videoInfo.getDescription()); + Assert.assertNotNull(videoInfo.getThumbnail()); + Assert.assertNotNull(videoInfo.getUploaderId()); + Assert.assertNotNull(videoInfo.getUploader()); + Assert.assertNotNull(videoInfo.getUploadDate()); + Assert.assertNotNull(videoInfo.getDuration()); + Assert.assertNotNull(videoInfo.getViewCount()); + Assert.assertNotNull(videoInfo.getLikeCount()); + Assert.assertNotNull(videoInfo.getDislikeCount()); + Assert.assertNotNull(videoInfo.getAverageRating()); + //Let's print the whole object + System.out.println("videoInfo:"+videoInfo.toString()); + + + } + + @Test + public void testGetFormats() throws YoutubeDLException { + List formats = YoutubeDLProxychains.getFormats(VIDEO_URL); + System.out.println("formats : "+formats); + Assert.assertNotNull(formats); + Assert.assertTrue(formats.size() > 0); + } + + @Test + public void testGetThumbnails() throws YoutubeDLException { + List thumbnails = YoutubeDLProxychains.getThumbnails(VIDEO_URL); + Assert.assertNotNull(thumbnails); + Assert.assertTrue(thumbnails.size() > 0); + } + + @Test + public void testGetTags() throws YoutubeDLException { + List tags = YoutubeDLProxychains.getTags(VIDEO_URL); + Assert.assertNotNull(tags); + Assert.assertTrue(tags.size() > 0); + } + + @Test + public void testGetCategories() throws YoutubeDLException { + List categories = YoutubeDLProxychains.getCategories(VIDEO_URL); + Assert.assertNotNull(categories); + Assert.assertTrue(categories.size() > 0); + } + + @Test(expected = YoutubeDLException.class) + public void testFailGetNonExistentVideoInfo() throws YoutubeDLException { + YoutubeDLProxychains.getVideoInfo(NONE_EXISTENT_VIDEO_URL); + } +} \ No newline at end of file diff --git a/src/test/java/com/sapher/youtubedl/YoutubeDLTest.java b/src/test/java/com/sapher/youtubedl/YoutubeDLTest.java index ca8d5e7..3033139 100644 --- a/src/test/java/com/sapher/youtubedl/YoutubeDLTest.java +++ b/src/test/java/com/sapher/youtubedl/YoutubeDLTest.java @@ -68,6 +68,30 @@ public void testGetVideoInfo() throws YoutubeDLException { VideoInfo videoInfo = YoutubeDL.getVideoInfo(VIDEO_URL); Assert.assertNotNull(videoInfo); } + + @Test + public void testGetVideoInfoInDetails() throws YoutubeDLException { + VideoInfo videoInfo = YoutubeDL.getVideoInfo(VIDEO_URL); + Assert.assertNotNull(videoInfo); + //Let's check we can access key elements from video info + Assert.assertNotNull(videoInfo.getId()); + Assert.assertNotNull(videoInfo.getTitle()); + Assert.assertNotNull(videoInfo.getFulltitle()); + Assert.assertNotNull(videoInfo.getDescription()); + Assert.assertNotNull(videoInfo.getThumbnail()); + Assert.assertNotNull(videoInfo.getUploaderId()); + Assert.assertNotNull(videoInfo.getUploader()); + Assert.assertNotNull(videoInfo.getUploadDate()); + Assert.assertNotNull(videoInfo.getDuration()); + Assert.assertNotNull(videoInfo.getViewCount()); + Assert.assertNotNull(videoInfo.getLikeCount()); + Assert.assertNotNull(videoInfo.getDislikeCount()); + Assert.assertNotNull(videoInfo.getAverageRating()); + //Let's print the whole object + System.out.println("videoInfo:"+videoInfo.toString()); + + + } @Test public void testGetFormats() throws YoutubeDLException {