diff --git a/src/me/despawningbone/discordbot/command/info/Fandom.java b/src/me/despawningbone/discordbot/command/info/Fandom.java index 4f59d3b..930173d 100644 --- a/src/me/despawningbone/discordbot/command/info/Fandom.java +++ b/src/me/despawningbone/discordbot/command/info/Fandom.java @@ -1,153 +1,106 @@ package me.despawningbone.discordbot.command.info; import java.awt.Color; -import java.io.IOException; -import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.time.Instant; import java.util.Arrays; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONTokener; 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 Fandom extends Command { public Fandom() { this.desc = "Search across all the fan-made wikis!"; - this.alias = Arrays.asList("wikia"); + this.alias = Arrays.asList("wikia", "gamepedia"); //gamepedia is now fandom basically this.usage = ": [| index]"; this.examples = Arrays.asList("zelda: gate of time", "clockwork planet: ryuZU", "angel beats: kanade"); } @Override //query for details using future too? since i already have to make 2 queries, making 3 in parallel wont make it much slower; the only concern is rate limit //already doing sequential 3 queries, aint too slow so its fine public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) { channel.sendTyping().queue(); - //OffsetDateTime timesent = OffsetDateTime.now(); - - /*for(TextChannel c : channel.getGuild().getTextChannels()) { wtf is this - try { - System.out.println(c); - Message m = c.getMessageById("607977540690378753").complete(); - if(m != null) channel.sendMessage(m.toString()).queue(); - } catch(ErrorResponseException | InsufficientPermissionException e) { - e.printStackTrace(); - continue; - } - - }*/ if (args.length < 1) { return new CommandResult(CommandResultType.INVALIDARGS, "Invalid input, check help for more info."); } + try { - String[] init = String.join(" ", args).split(":"); + String[] init = String.join(" ", args).split(":", 2); if(init.length < 2) { return new CommandResult(CommandResultType.INVALIDARGS, "Please use a colon to seperate the wiki and the search query!"); } + + //get index String[] split = init[1].split(" \\| "); String sword = split[0]; int num = 0; if (split.length > 1) { try { num = Integer.parseInt(split[1]) - 1; if(num < 0) throw new NumberFormatException(); } catch (NumberFormatException e) { channel.sendMessage("Invalid index inputted. Defaulting to the first result...").queue(); num = 0; } } - JSONTokener result = null; - InputStream stream = null; + + //bruh the gamepedia merge killed a ton of the actual good UCP/nirvana API controller endpointss + //now i gotta use wack substitutions + + //search - since SearchApiController is now gone i gotta use the other ones String search = URLEncoder.encode(sword.trim(), "UTF-8"); HttpURLConnection url = null; String wiki = init[0].replaceAll("[^\\p{L}\\p{N} ]+", "").replaceAll(" ", "-").toLowerCase(); - //boolean old = false; - try { - /*url = (HttpURLConnection) new URL("https://" + wiki + ".fandom.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").openConnection(); - stream = url.getInputStream(); - if(url.getResponseCode() == 302) { //wikia is deprecated, for the few weeks of deprecation period only - old = true; - url = (HttpURLConnection) new URL("https://" + init[0].replaceAll("[^\\p{L}\\p{N} ]+", "").replaceAll(" ", "-").toLowerCase() + ".wikia.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").openConnection(); - stream = url.getInputStream(); - if(url.getResponseCode() == 302) { - channel.sendMessage("Unknown wiki name!").queue(); - return new CommandResult(CommandResultType.NORESULT); - } - }*/ - //i can use this instead of the above code since wikia redirects with 301 with no exceptions; when everything finishes moving, i might have to change it to fandom though - System.out.println("https://" + wiki + ".wikia.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14"); - url = (HttpURLConnection) new URL("https://" + wiki + ".wikia.com/api/v1/Search/List?query=" + search + "&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").openConnection(); - stream = url.getInputStream(); - if(url.getURL().toString().startsWith("https://community.fandom.com/")) { - return new CommandResult(CommandResultType.FAILURE, "Unknown wiki name!"); - } - } catch (IOException e) { - if(url.getResponseCode() == 404) { - return new CommandResult(CommandResultType.NORESULT, "it in the " + init[0] + " wiki"); - } - return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e)); + //the wikia domain is still in use; no need to swap to fandom.com for now + //alternative search endpoint (more of an autocomplete only but much faster): "https://" + wiki + ".wikia.com/wikia.php?controller=LinkSuggest&method=getLinkSuggestions&format=json&query=" + search + url = (HttpURLConnection) new URL("https://" + wiki + ".wikia.com/api.php?action=query&format=json&list=search&srsearch=" + search).openConnection(); + if(url.getResponseCode() == 404) { + return new CommandResult(CommandResultType.FAILURE, "Unknown wiki name!"); //404 means unknown wiki now } - JSONObject item; + + //get result + int id; try { - result = new JSONTokener(stream); - JSONArray main = new JSONObject(result).getJSONArray("items"); - item = main.getJSONObject(num); + JSONObject result = new JSONObject(new JSONTokener(url.getInputStream())); + id = result.getJSONObject("query").getJSONArray("search").getJSONObject(num).getInt("pageid"); } catch(JSONException e) { return new CommandResult(CommandResultType.NORESULT, "it in the " + init[0] + " wiki"); } - // System.out.println(i); - //JSONArray array = new JSONObject(new JSONTokener(new URL("https://" + wiki + (old ? ".wikia" : ".fandom") + ".com/api/v1/Articles/AsSimpleJson?id=" + item.getInt("id")).openStream())).getJSONArray("sections").getJSONObject(0).getJSONArray("content"); - JSONArray array = new JSONObject(new JSONTokener(new URL("https://" + wiki + ".wikia.com/api/v1/Articles/AsSimpleJson?id=" + item.getInt("id")).openStream())).getJSONArray("sections").getJSONObject(0).getJSONArray("content"); - String desc = ""; - for(int i = 0; i < array.length(); i++) { - desc = array.getJSONObject(i).getString("text"); - if(desc.contains("may refer to")) { - JSONArray list = array.getJSONObject(i + 1).getJSONArray("elements"); - for(int j = 0; j < list.length(); j++) { - desc += "\n- " + list.getJSONObject(j).getString("text"); - } - } - if(!desc.trim().replaceAll("(^\\h*)|(\\h*$)","").isEmpty()) { - break; - } - } - JSONObject details = new JSONObject(new JSONTokener(new URL("https://" + wiki + ".wikia.com/api/v1/Articles/Details?ids=" + item.getInt("id")).openStream())); - JSONObject info = details.getJSONObject("items").getJSONObject(String.valueOf(item.getInt("id"))); //TODO make async + + //fetch details about page; way worse formatting than AsSimpleJson but hey its gone what can i do + JSONObject details = new JSONObject(new JSONTokener(new URL("https://" + wiki + ".wikia.com/api/v1/Articles/Details?abstract=500&ids=" + id).openStream())); + JSONObject info = details.getJSONObject("items").getJSONObject(String.valueOf(id)); //TODO make async EmbedBuilder eb = new EmbedBuilder(); - eb.setTitle(info.getString("title"), item.getString("url")); + eb.setTitle(info.getString("title"), details.getString("basepath") + info.getString("url")); eb.setAuthor(StringUtils.capitalize(init[0]) + " wiki", details.getString("basepath")); - eb.setDescription(desc); + + //only use until the last full stop before table of content or end for slightly better formatting + //there might be false positives for table of content detection since its just checking 1 after full stop, but honestly rarely less details > commonly being ugly af + String desc = info.getString("abstract").replaceAll("^(?:(.*?\\.) ?1 .*|(.*\\.) .*?)$", "$1$2"); //greedy if table of content is present, else lazy to get the last + eb.setDescription(desc.matches(".*\\.$") ? desc : (desc + "...")); //if everything fails (aka last char aint a full stop) give it the good ol ... treatment if(info.has("comments")) eb.addField("Comments", String.valueOf(info.getInt("comments")), false); - if(!info.isNull("thumbnail")) eb.setThumbnail(info.getString("thumbnail")); + if(!info.isNull("thumbnail")) eb.setThumbnail(info.getString("thumbnail").substring(0, info.getString("thumbnail").indexOf("/revision/"))); //get full img by trimming revision path eb.setFooter("Last edited by " + info.getJSONObject("revision").getString("user"), null); eb.setTimestamp(Instant.ofEpochSecond(Long.parseLong(info.getJSONObject("revision").getString("timestamp")))); eb.setColor(new Color(0, 42, 50)); + channel.sendMessage(eb.build()).queue(); - /*MessageBuilder smsg = new MessageBuilder(); - smsg.append("**" + item.getString("title") + "**\n\n"); - smsg.append(desc + "\n"); - smsg.append("<" + item.getString("url") + ">"); - OffsetDateTime timeReceived = OffsetDateTime.now(); - long ms = Math.abs(timesent.until(timeReceived, ChronoUnit.MILLIS)); - smsg.append("\n" + ms + "ms"); - Message fmsg = smsg.build(); - channel.sendMessage(fmsg).queue();*/ return new CommandResult(CommandResultType.SUCCESS); //add searched result name? } catch (Exception e) { return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e)); } } }