Page MenuHomedesp's stash

No OneTemporary

diff --git a/src/me/despawningbone/discordbot/command/anime/Sauce.java b/src/me/despawningbone/discordbot/command/anime/Sauce.java
index 3ce28ff..95035f4 100644
--- a/src/me/despawningbone/discordbot/command/anime/Sauce.java
+++ b/src/me/despawningbone/discordbot/command/anime/Sauce.java
@@ -1,168 +1,169 @@
package me.despawningbone.discordbot.command.anime;
import java.awt.Color;
import java.io.IOException;
+import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
public class Sauce extends Command{
public Sauce() {
this.desc = "Get the source of an anime pic!";
this.usage = "[-d] [imgurl]";
this.alias = Arrays.asList("source", "saucenao", "iqdb");
this.remarks = Arrays.asList("The URL should be a direct link to an image.", "You can also upload an image as an attachment while calling this command instead of using a url.",
" * Specify the `-d` parameter to do a depth search!", " * It is useful for cropped images and edited images, but makes the search much longer.");
}
@Override
public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) { //allow people to not input url to check sauce of the most recent image like u/2dgt3d?
List<String> amend = new ArrayList<String>(Arrays.asList(args));
int temp = amend.indexOf("-d");
if(temp != -1) amend.subList(temp, temp + 1).clear();
String url = null;
try {
if(amend.size() < 1) {
if(msg.getAttachments().size() > 0) url = msg.getAttachments().get(0).getUrl();
else throw new MalformedURLException();
} else {
url = amend.get(0).trim();
new URL(url);
}
} catch(MalformedURLException e) {
return new CommandResult(CommandResultType.FAILURE, "Please enter a valid URL!");
}
System.out.println(url);
try {
channel.sendTyping().queueAfter(20, TimeUnit.MILLISECONDS);
if(temp != -1) {
channel.sendMessage("Performing depth search for the picture... (this can take up to 20 seconds)").queue();
String[] urls = yandexSearch(url);
System.out.println(Arrays.asList(urls));
url = urls[2] == null ? urls[0] : urls[1] + ";" + urls[2];
//sync
//List<EmbedBuilder> collect = Arrays.asList(tempSearchSauce(urls[0]),tempSearchSauce(urls[1]));
//async
CompletableFuture<EmbedBuilder> first = CompletableFuture.supplyAsync(() -> {try {return tempSearchSauce(urls[0]);} catch (IOException e){e.printStackTrace(); return null;}});
CompletableFuture<EmbedBuilder> ratio = CompletableFuture.supplyAsync(() -> {try {return tempSearchSauce(urls[1]);} catch (IOException e){e.printStackTrace(); return null;}});
List<EmbedBuilder> collect = CompletableFuture.allOf(first, ratio)
.thenApply(future -> Arrays.asList(first.join(), ratio.join()))
.whenComplete((s, t) -> {if(!(ratio.join() != null && first.join() != null) && t != null) throw new CompletionException(t.getCause());}).get();
channel.sendMessage(collect.stream().filter(e -> e != null).sorted((a, b) -> urls[2] == null ? -1 : Double.compare(Double.parseDouble(b.build().getFooter().getText().replaceAll(".*?([.0-9]*%).*", "$1").replace("%", "")), Double.parseDouble(a.build().getFooter().getText().replaceAll(".*?([.0-9]*%).*", "$1").replace("%", "")))).findFirst().get().build()).queue();
} else {
EmbedBuilder eb = tempSearchSauce(url);
channel.sendMessage(eb.build()).queue();
}
} catch (IOException | InterruptedException | ExecutionException e) {
Throwable t = e instanceof ExecutionException ? e.getCause() : e;
return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(t));
} catch (NullPointerException | NoSuchElementException e) {
if(e instanceof NoSuchElementException) {
EmbedBuilder eb = new EmbedBuilder();
String[] urls = url.split(";");
eb.setThumbnail(urls[0]);
eb.setTitle("Possibly related image", urls[0]);
eb.setDescription("Maybe [this](" + urls[urls.length > 1 ? 1 : 0] + ") will help in your search for the delicious marinara?");
channel.sendMessage(eb.build()).queueAfter(20, TimeUnit.MILLISECONDS);
}
return new CommandResult(CommandResultType.NORESULT);
}
return new CommandResult(CommandResultType.SUCCESS);
}
private String[] yandexSearch(String url) throws IOException {
Element yandex = Jsoup.connect("https://yandex.com/images/search?url=" + URLEncoder.encode(url, "UTF-8") + "&rpt=imageview").get().body();
String[] size = new String[]{yandex.selectFirst(".CbirPreview-Placeholder").attr("width"), yandex.selectFirst(".CbirPreview-Placeholder").attr("height")};
//double ratio = Double.parseDouble(size[0]) / Double.parseDouble(size[1]) >= 1 ? 16.0/9 : 9/16.0;
double ratio = Double.parseDouble(size[0]) / Double.parseDouble(size[1]);
- System.out.println(yandex.select(".other-sites__thumb"));
- System.out.println(size[0] + " " + size[1] + " " + ratio);
+ //System.out.println(yandex.select(".other-sites__thumb"));
+ //System.out.println(size[0] + " " + size[1] + " " + ratio);
String other, site = null, similar = URLDecoder.decode(yandex.select(".cbir-similar__thumb .cbir-similar__image").get(yandex.select(".cbir-other-sizes__item").size() > 0 ? 1 : 0).parent().attr("href").split("img_url=")[1].split("&")[0], "UTF-8");
if(yandex.select(".cbir-other-sizes__list").size() > 0) { //TODO merge the sort algorithms?
/*other = yandex.select(".cbir-other-sizes__list").first().select("a").stream().sorted((a, b) -> { //selects largest possible section of the other sizes
String[] aA = a.select(".cbir-other-sizes__resolution").first().text().split("×"), bA = b.select(".cbir-other-sizes__resolution").first().text().split("×");
return Double.compare(Math.abs(Double.parseDouble(aA[0]) / Double.parseDouble(aA[1]) - ratio), Math.abs(Double.parseDouble(bA[0]) / Double.parseDouble(bA[1]) - ratio));
}).findFirst().get().attr("href");*/
other = yandex.select(".cbir-other-sizes__list a").first().attr("href"); //sorting with ratio seems to perform bad for most crops so dont sort anymore
} else {
yandex.select(".other-sites__item").stream().limit(12).sorted((a, b) -> {
String[] aA = a.select(".other-sites__meta").first().text().split("×"), bA = b.select(".other-sites__meta").first().text().split("×");
System.out.println(Math.abs(Double.parseDouble(aA[0]) / Double.parseDouble(aA[1]) - ratio) + ", " + Math.abs(Double.parseDouble(bA[0]) / Double.parseDouble(bA[1]) - ratio));
return Double.compare(Math.abs(Double.parseDouble(aA[0]) / Double.parseDouble(aA[1]) - ratio), Math.abs(Double.parseDouble(bA[0]) / Double.parseDouble(bA[1]) - ratio));}).forEach(s -> System.out.println(s));
Element eSite = yandex.select(".other-sites__item").stream().limit(12).sorted((a, b) -> {
String[] aA = a.select(".other-sites__meta").first().text().split("×"), bA = b.select(".other-sites__meta").first().text().split("×");
return Double.compare(Math.abs(Double.parseDouble(aA[0]) / Double.parseDouble(aA[1]) - ratio), Math.abs(Double.parseDouble(bA[0]) / Double.parseDouble(bA[1]) - ratio));}).findFirst().get();
other = eSite.select(".other-sites__preview-link").first().attr("href");
- site = Jsoup.connect(eSite.select(".other-sites__snippet-site-link").first().attr("href")).get().html().split(";URL='")[1].split("'")[0];
+ site = eSite.select(".other-sites__snippet-site-link").first().attr("href");
}
return new String[]{similar, other, site};
//gets second image coz usually the first one is just a sharper identical image, then get the largest image that has the image inside or select an image closest to 16:9 for anime checking //closest to given ratio now, anime checking usually cant be done with depth search anyways since not every scene is screen capped online
}
private EmbedBuilder tempSearchSauce(String url) throws IOException {
EmbedBuilder eb = new EmbedBuilder();
eb.setColor(new Color(29, 29, 29));
try { //search iqdb first for the tags; results usually more organized and formatted
Element iqdb = Jsoup.connect("https://iqdb.org/?url=" + url + "&service[]=1&service[]=2&service[]=3&service[]=4&service[]=5&service[]=11&service[]=13").get().body(); //services excluding eshuushuu since it has no tags and will fallback to saucenao anyways
if(iqdb.select(".err").size() > 0 && iqdb.select(".err").html().contains("HTTP")) throw new IOException(iqdb.selectFirst(".err").ownText().split("\\.")[0]);
Elements tb = iqdb.select("th:contains(Best match)").get(0).parent().siblingElements();
Element img = tb.get(0).selectFirst("img");
eb.setThumbnail("https://iqdb.org/" + img.attr("src"));
eb.setTitle("Source: " + tb.get(1).selectFirst("td").ownText(), (img.parent().attr("href").contains("http") ? "" : "https:") + img.parent().attr("href"));
String tags = img.attr("alt").split("Tags:")[1];
eb.setDescription(tags.contains(",") ? tags.replaceAll(",", "\n") : tags.replaceAll(" ", "\n").replaceAll("\\_", " "));
eb.setFooter(tb.get(2).select("td").eachText().get(0) + " | " + tb.get(3).select("td").text(), null);
- } catch (IndexOutOfBoundsException | SocketTimeoutException e) { //fallback to saucenao, usually pixiv source instead of image boards
+ } catch (IndexOutOfBoundsException | SocketTimeoutException | ConnectException e) { //fallback to saucenao, usually pixiv source instead of image boards
try {
Element saucenao = Jsoup.connect("https://saucenao.com/search.php?url=" + url).get().body();
Element result = saucenao.selectFirst(".resulttable");
if(result == null) return null;
if(result.parent().attr("class").equals("result hidden")) return null;
eb.setThumbnail((result.selectFirst("img").attr("src").contains("http") ? "" : "https:") + result.selectFirst("img").attr("src").replaceAll(" ", "%20"));
try { //normal pixiv/deviantart handling
Element source = result.selectFirst("strong:contains(ID:)").nextElementSibling();
eb.setAuthor(result.select(".resulttitle strong").text());
eb.setTitle("Source: " + source.previousElementSibling().text().replaceAll("ID:", "#") + source.text(), source.attr("href"));
Element member = result.select(".linkify").get(2);
eb.setDescription("Author: [" + member.text() + "](" + member.attr("href") + ")");
} catch (NullPointerException e1) { //weird saucenao card formatting (eg episode info)
result.select("br").after("\\n");
String[] title = result.selectFirst(".resulttitle") == null ? new String[]{"No title"} : result.selectFirst(".resulttitle").wholeText().replaceAll("\\\\n", "\n").split("\n", 2); //there can be no titles, like 4chan sources
eb.setTitle(title[0], result.selectFirst(".resultmiscinfo a") == null ? null : result.selectFirst(".resultmiscinfo a").attr("href"));
if(title.length > 1) eb.appendDescription(title[1] + "\n");
eb.appendDescription(result.selectFirst(".resultcontentcolumn").wholeText().replaceAll("\\\\n", "\n"));
}
eb.setFooter(result.select(".resultsimilarityinfo").text() + " Similarity", null);
} catch (IndexOutOfBoundsException e1) {
return null;
}
}
return eb;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jul 5, 4:28 AM (5 h, 35 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
0d/63/20144f094791f98300bdf1d0bf5c

Event Timeline