diff --git a/build.gradle b/build.gradle index 125d2aa..9566bf7 100644 --- a/build.gradle +++ b/build.gradle @@ -71,6 +71,8 @@ dependencies { compile 'com.google.api-client:google-api-client:1.23.0' compile 'com.google.apis:google-api-services-youtube:v3-rev192-1.23.0' + compile group: 'org.jsoup', name: 'jsoup', version: '1.12.1' + testCompile('org.springframework.boot:spring-boot-starter-test') testCompile('com.jayway.jsonpath:json-path') diff --git a/src/main/java/net/Broken/Commands/YtSearch.java b/src/main/java/net/Broken/Commands/YtSearch.java index 2eb9961..e88aea7 100644 --- a/src/main/java/net/Broken/Commands/YtSearch.java +++ b/src/main/java/net/Broken/Commands/YtSearch.java @@ -6,6 +6,7 @@ import net.Broken.MainBot; import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.MessageTimeOut; import net.Broken.audio.Youtube.SearchResult; +import net.Broken.audio.Youtube.YoutubeSearchRework; import net.Broken.audio.Youtube.YoutubeTools; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Message; @@ -16,6 +17,7 @@ import org.apache.logging.log4j.Logger; import java.io.IOException; import java.util.ArrayList; +import java.util.List; public class YtSearch implements Commande { @@ -23,22 +25,24 @@ public class YtSearch implements Commande { @Override public void action(String[] args, MessageReceivedEvent event) { - YoutubeTools youtubeT = YoutubeTools.getInstance(); - if(args.length < 1){ + YoutubeSearchRework youtubeSearch = YoutubeSearchRework.getInstance(); + if (args.length < 1) { logger.info("YtSearch: Missing args, user: " + event.getAuthor().getName()); Message message = event.getChannel().sendMessage(EmbedMessageUtils.buildStandar(EmbedMessageUtils.getError("Missing search query!"))).complete(); new MessageTimeOut(MainBot.messageTimeOut, message, event.getMessage()).start(); - }else { + } else { try { - ArrayList result = youtubeT.search(args[0], 5, false); - for(SearchResult item : result){ + + StringBuilder builder = new StringBuilder(); + for (String arg : args) { + builder.append(arg); + } + List result = youtubeSearch.searchVideo(builder.toString(), 5, false); + for (SearchResult item : result) { event.getChannel().sendMessage(EmbedMessageUtils.searchResult(item)).queue(); } - } catch (GoogleJsonResponseException e) { - logger.error("There was a service error: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage()); - event.getChannel().sendMessage(EmbedMessageUtils.getInternalError()).queue(); } catch (IOException t) { logger.catching(t); event.getChannel().sendMessage(EmbedMessageUtils.getInternalError()).queue(); diff --git a/src/main/java/net/Broken/RestApi/MusicWebAPIController.java b/src/main/java/net/Broken/RestApi/MusicWebAPIController.java index db88068..0bdfcfd 100644 --- a/src/main/java/net/Broken/RestApi/MusicWebAPIController.java +++ b/src/main/java/net/Broken/RestApi/MusicWebAPIController.java @@ -13,6 +13,7 @@ import net.Broken.Tools.UserManager.UserUtils; import net.Broken.audio.AudioM; import net.Broken.audio.GetVoiceChanels; import net.Broken.audio.Youtube.SearchResult; +import net.Broken.audio.Youtube.YoutubeSearchRework; import net.Broken.audio.Youtube.YoutubeTools; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.VoiceChannel; @@ -206,8 +207,10 @@ public class MusicWebAPIController { if(token != null && !token.isEmpty()) { try { UserEntity user = userUtils.getUserWithApiToken(userRepository, token); - YoutubeTools youtubeTools = YoutubeTools.getInstance(); - ArrayList result = youtubeTools.search(query, 25, playlist); +// YoutubeTools youtubeTools = YoutubeTools.getInstance(); +// ArrayList result = youtubeTools.search(query, 25, playlist); + YoutubeSearchRework youtubeSearch = YoutubeSearchRework.getInstance(); + List result = youtubeSearch.searchVideo(query, 25, playlist); return new ResponseEntity<>(result, HttpStatus.OK); }catch (UnknownTokenException e){ diff --git a/src/main/java/net/Broken/Tools/EmbedMessageUtils.java b/src/main/java/net/Broken/Tools/EmbedMessageUtils.java index a87ba1d..23a504a 100644 --- a/src/main/java/net/Broken/Tools/EmbedMessageUtils.java +++ b/src/main/java/net/Broken/Tools/EmbedMessageUtils.java @@ -113,7 +113,7 @@ public class EmbedMessageUtils { .setColor(Color.CYAN) .setTitle(result.title) .setImage(result.imageUrl) - .addField("Duration: ", YoutubeTools.getInstance().ytTimeToString(result.duration), false) + .addField("Duration: ", result.duration, false) .addField("URL:","https://www.youtube.com/watch?v="+result.id,false) .addField("Chanel:", result.channelTittle, false); return buildStandar(builder); diff --git a/src/main/java/net/Broken/audio/Youtube/SearchResult.java b/src/main/java/net/Broken/audio/Youtube/SearchResult.java index 7aa75aa..5ee4664 100644 --- a/src/main/java/net/Broken/audio/Youtube/SearchResult.java +++ b/src/main/java/net/Broken/audio/Youtube/SearchResult.java @@ -23,4 +23,15 @@ public class SearchResult { imageUrl = result.getSnippet().getThumbnails().getDefault().getUrl(); this.duration = duration; } + + public SearchResult(String id, String title, String description, String publishedAt, String channelId, String channelTittle, String imageUrl, String duration) { + this.id = id; + this.title = title; + this.description = description; + this.publishedAt = publishedAt; + this.channelId = channelId; + this.channelTittle = channelTittle; + this.imageUrl = imageUrl; + this.duration = duration; + } } diff --git a/src/main/java/net/Broken/audio/Youtube/YoutubeSearchRework.java b/src/main/java/net/Broken/audio/Youtube/YoutubeSearchRework.java new file mode 100644 index 0000000..e2925c3 --- /dev/null +++ b/src/main/java/net/Broken/audio/Youtube/YoutubeSearchRework.java @@ -0,0 +1,107 @@ +package net.Broken.audio.Youtube; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +public class YoutubeSearchRework { + + private Logger logger = LogManager.getLogger(); + + private static YoutubeSearchRework INSTANCE; + + public static YoutubeSearchRework getInstance() { + if (INSTANCE == null) { + INSTANCE = new YoutubeSearchRework(); + } + return INSTANCE; + } + + + public List searchVideo(String search, int maxResult, boolean playlist) throws IOException { + search = URLEncoder.encode(search, StandardCharsets.UTF_8.toString()); + String url = "https://www.youtube.com/results?search_query=" + search + "&sp="+ (playlist ? "EgIQAw%3D%3D" :"EgIQAQ%3D%3D"); + Document doc = getYoutubeSearchDocument(url); + return extractVideoInfo(doc, maxResult, playlist); + } + + + private Document getYoutubeSearchDocument(String URL) throws IOException { + + return Jsoup.connect(URL).userAgent("Googlebot/2.1 (+http://www.googlebot.com/bot.html)").header("Accept-Language", "en-US").get(); + + + } + + // video = EgIQAQ== + private List extractVideoInfo(Document doc, int maxResult, boolean playlist) { + Elements videosDivs = doc.select(".yt-lockup"); + List results = new ArrayList<>(); + int i = 0; + for (Element videoDiv : videosDivs) { + if(i >= maxResult) + break; + Element titleDiv = videoDiv.selectFirst(".yt-uix-tile-link"); + String id; + if(!playlist) + id = titleDiv.attributes().get("href").replace("/watch?v=", ""); + else{ + String listUrl = titleDiv.attributes().get("href"); + int listIndex = listUrl.indexOf("list="); + id = listUrl.substring(listIndex).replace("list=", ""); + + } + + String title = titleDiv.text(); + Elements metas = videoDiv.selectFirst(".yt-lockup-meta-info").getElementsByTag("li"); + String view = ""; + String date = ""; + if(!playlist){ + for (Element metaElem : metas) { + + if (metaElem.text().contains("view")) { + view = metaElem.text(); + } else { + date = metaElem.text(); + } + } + } + + + Element chanelTag = videoDiv.selectFirst(".yt-lockup-byline").getElementsByTag("a").get(0); + String channelTittle = chanelTag.text(); + String channelId = chanelTag.attributes().get("href").replace("/channel/", ""); + + String imageUrl; + String duration; + if(!playlist){ + duration = videoDiv.selectFirst(".video-time").text(); + imageUrl = "https://i.ytimg.com/vi/" + id + "/hqdefault.jpg"; + } + + else{ + String listUrl = titleDiv.attributes().get("href"); + int listIndex = listUrl.indexOf("&list="); + listUrl = listUrl.substring(0, listIndex).replace("/watch?v=", ""); + imageUrl = "https://i.ytimg.com/vi/" + listUrl + "/hqdefault.jpg"; + duration = videoDiv.selectFirst(".formatted-video-count-label").text(); + } + + + results.add(new SearchResult(id, title, "", date, channelId, channelTittle, imageUrl, duration)); + i++; + + + } + return results; + } +} diff --git a/src/main/resources/static/js/music.js b/src/main/resources/static/js/music.js index 6e2eb1b..f719f50 100644 --- a/src/main/resources/static/js/music.js +++ b/src/main/resources/static/js/music.js @@ -446,7 +446,7 @@ function search() { "
  • " + " \"\"" + " " + item["title"] + "" + - "

    " + item["channelTittle"] + " ║ " + item["publishedAt"].substr(0, item["publishedAt"].indexOf('T')) + "
    " + ytTimeToTime(item["duration"]) + + "

    " + item["channelTittle"] + " ║ " + item["publishedAt"] + "
    " + item["duration"] + "

    " + " add_circle_outline" + " " +