Page MenuHomedesp's stash

EventListener.java
No OneTemporary

EventListener.java

package me.despawningbone.discordbot;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import me.despawningbone.discordbot.command.music.AudioTrackHandler;
import me.despawningbone.discordbot.command.music.GuildMusicManager;
import me.despawningbone.discordbot.command.music.Music;
import me.despawningbone.discordbot.utils.MiscUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildVoiceState;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.VoiceChannel;
import net.dv8tion.jda.api.entities.Message.Attachment;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent;
import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent;
import net.dv8tion.jda.api.events.user.UserActivityStartEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
public class EventListener extends ListenerAdapter {
public static Multimap<String, String> testAnimePicCache = ArrayListMultimap.create();
@Override
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
DiscordBot.mainJDA = event.getJDA(); // refresh it? //no need, everything's getJDA() is the same jda basis but audioplayer's still using it; need to migrate to store in guildmusicmanager
//String[] words = event.getMessage().getContentDisplay().split(" ");
User author = event.getAuthor();
TextChannel channel = event.getChannel();
Message msg = event.getMessage();
//checkAnimePics(event);
//DONE use log4j
//logging
if (!DiscordBot.logExcemptID.contains(author.getId())) {
String guildinfo = "[" + event.getGuild().getName() + " #" + channel.getName() + "]";
String payload = "[INFO] " + guildinfo + System.lineSeparator() + " " + msg + System.lineSeparator() + " Full msg: " + msg.getContentDisplay();
List<Attachment> att = event.getMessage().getAttachments();
if (!att.isEmpty()) {
payload += System.lineSeparator() + " Attachments:";
for (int i = 0; i < att.size(); i++) {
payload += System.lineSeparator() + " " + att.get(i).getUrl();
}
}
DiscordBot.logger.trace(payload); //TODO log embeds and add user id too?
}
/*if (String.join("", words).equalsIgnoreCase("!despacito")) {
channel.sendMessage("https://www.youtube.com/watch?v=W3GrSMYbkBE").queue();
return;
}*/
CommandResult result = null;
try (Connection con = DiscordBot.db.getConnection(); Statement s = con.createStatement()){
String prefix = MiscUtils.getPrefix(s, event.getGuild().getId());
if(msg.getContentDisplay().toLowerCase().startsWith(prefix.toLowerCase())) {
String msgStripped = msg.getContentDisplay().substring(prefix.length()).replaceAll("\\s\\s+", " "); //merges space
String[] args = msgStripped.split(" "); // base on command length?
Command cmd = DiscordBot.commands.get(args[0].toLowerCase());
cmd = cmd == null ? DiscordBot.aliases.get(args[0].toLowerCase()) : cmd;
if (cmd != null) {
ResultSet uRs = s.executeQuery("SELECT reports FROM users WHERE id = " + author.getId() + ";");
if(uRs.next()) { //checks null at the same time
if(uRs.getString(1).split("\n").length >= 5) {
channel.sendMessage("You are banned from using the bot.").queue();
DiscordBot.logger.info("[WARN] " + author.getName() + " (" + author.getId() + ") tried to execute " + msg.getContentDisplay() + " but was banned.");
return;
}
}
uRs.close();
long perm = MiscUtils.getActivePerms(s, channel, cmd);
//result = cmd.execute(channel, author, msg, args);
String perms = cmd.hasSubCommand() ? null : MiscUtils.getMissingPerms(perm, cmd.getRequiredBotUserLevel(), event.getMember(), channel); //pass it to the subcommand handler to handle instead
if(cmd.isDisabled()) perms = "DISABLED"; //override if disabled by code
if(perms == null || event.getAuthor().getId().equals(DiscordBot.OwnerID)) { //owner overrides perms for convenience
/*if(cmd.isDisabled(channel.getGuild().getId())) {
channel.sendMessage("This command is disabled!").queue();
result = new CommandResult(CommandResultType.FAILURE, "Disabled command");
} else {*/
cmd.executeAsync(channel, author, msg, Arrays.copyOfRange(args, 1, args.length), r -> { //catch all exceptions? //should have actually
DiscordBot.logger.info("[" + r.getResultType() + "] " + author.getName() + " (" + author.getId() + ") executed "
+ msg.getContentDisplay() + (r.getRemarks() == null ? "." : ". (" + r.getRemarks() + ")")); //logging has to be before sendMessage, or else if no permission it will just quit
if(r.getMessage() != null) channel.sendMessage(r.getMessage()).queue();
}); //dont know if async will screw anything up //wont, TODO log date and which server executed the command also?
return;
//}
} else if(perms.equals("DISABLED")) {
author.openPrivateChannel().queue(c -> //notify user whats wrong if possible
c.sendMessage("Sorry, but the command `" + msg.getContentDisplay() + "` is disabled in the channel `#" + channel.getName() + "`.").queue());
msg.addReaction("❎").queue();
result = new CommandResult(CommandResultType.DISABLED);
} else {
result = new CommandResult(CommandResultType.NOPERMS, perms);
channel.sendMessage(result.getMessage()).queue();
}
} else {
result = new CommandResult(CommandResultType.FAILURE, "Invalid command");
//do more stuff?
}
} else if(msg.getContentRaw().matches("<@!?" + DiscordBot.BotID + ">")) result = greet(channel, author, prefix);
} catch (SQLException e) {
result = new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
}
if(result != null) DiscordBot.logger.info("[" + result.getResultType() + "] " + author.getName() + " (" + author.getId() + ") executed "
+ msg.getContentDisplay() + (result.getRemarks() == null ? "." : ". (" + result.getRemarks() + ")"));
}
@SuppressWarnings("unused")
private void checkAnimePics(GuildMessageReceivedEvent event) {
//TESTING
CompletableFuture.runAsync(() -> {
User author = event.getAuthor();
TextChannel channel = event.getChannel();
Message msg = event.getMessage();
List<String> pics = new ArrayList<>();
if(channel.getId().equals("615396635383562272") && !DiscordBot.BotID.equals(author.getId())) {
for(Attachment att : msg.getAttachments()) {
if(att.isImage()) pics.add(att.getUrl());
}
/*if(msg.getContentDisplay().contains("http")) {
for(String s : msg.getContentDisplay().split("http")) {
try {
new URL("http" + s);
pics.add("http" + s);
} catch(MalformedURLException e) {
;
}
}
}*/
try {
Thread.sleep(1500);
msg = channel.retrieveMessageById(msg.getId()).complete();
} catch (InterruptedException e2) {
e2.printStackTrace();
}
for(MessageEmbed em : msg.getEmbeds()) {
//System.out.println(em.toJSONObject());
if(em.getThumbnail() != null) {
System.out.println("thumb");
if(em.getSiteProvider() != null && em.getSiteProvider().getName().equals("pixiv")) { //pixiv doesnt show whole pic in embed
pics.add(em.getUrl());
} else {
pics.add(em.getThumbnail().getUrl());
}
} else if(em.getImage() != null && !author.isBot()) {
System.out.println("img");
pics.add(em.getImage().getUrl());
} else {
System.out.println("url");
pics.add(em.getUrl());
}
}
//System.out.println(pics);
//System.out.println(testAnimePicCache);
for(String pic : pics) { //handle first since these mustnt be the same urls, therefore cache saucenao sauce instead
String origPic = pic;
if(!testAnimePicCache.containsValue(pic)) {
Element saucenao;
try {
saucenao = Jsoup.connect("https://saucenao.com/search.php?url=" + pic).get().body();
Element result = saucenao.selectFirst(".resulttable");
try { //normal pixiv/deviantart handling
if(result.parent().attr("class").equals("result hidden")) throw new NullPointerException();
Element source = result.selectFirst("strong:contains(ID:)").nextElementSibling();
pic = source.attr("href"); //will not run if the cache has the value || if the link specified aint a pic
} catch (NullPointerException e1) { //weird saucenao card formatting (eg episode info), or no result; we dont handle these
;
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("next" + testAnimePicCache);
if(testAnimePicCache.containsValue(pic)) {
try {
Multimap<String, String> temp = ArrayListMultimap.create();
System.out.println("temp");
Message m = channel.retrieveMessageById(Multimaps.invertFrom(testAnimePicCache, temp).get(pic).toArray(new String[1])[0]).complete();
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("Repost detected!");
eb.setDescription("[This image](" + origPic + ")" + (origPic.equals(pic) ? "" : "([source](" + pic + "))") + " is a repost of [this message](" + m.getJumpUrl() + ") by `" + m.getAuthor().getName() + "#" + m.getAuthor().getDiscriminator() + "` at **" + m.getTimeCreated().format(DateTimeFormatter.RFC_1123_DATE_TIME) + "**.\n");
eb.setThumbnail(origPic);
channel.sendMessage(eb.build()).queue();
continue;
} catch(NullPointerException e) { //if the message is deleted
e.printStackTrace();
}
} else {
System.out.println("put");
testAnimePicCache.put(msg.getId(), pic);
}
}
}
}).whenComplete((r, t) -> {if(t != null) t.printStackTrace();});
}
private Properties greetEasterEggs = new Properties();
{
try(FileInputStream in = new FileInputStream(new File(System.getProperty("user.dir") + File.separator + "eastereggs.properties"))){
greetEasterEggs.load(in);
} catch (IOException e) {
e.printStackTrace();
}
}
private CommandResult greet(TextChannel channel, User author, String prefix) {
MessageBuilder smsg = new MessageBuilder();
String nick = channel.getGuild().getMemberById(author.getId()).getNickname();
if (nick != null) {
smsg.append("Yo " + nick + "!\n");
} else {
smsg.append("Yo " + author.getName() + "!\n");
}
String easterEgg = greetEasterEggs.getProperty(author.getId());
if(easterEgg != null) {
smsg.append(easterEgg.replace("\\n", "\n") + "\n");
}
EmbedBuilder eb = new EmbedBuilder();
eb.setColor(0x051153); //TODO version info based on git commits
eb.appendDescription("This bot is running **despbot v1.5.0**, Shard `" + DiscordBot.mainJDA.getShardInfo().getShardString() + "`. ([invite me!](https://discordapp.com/oauth2/authorize?&client_id=" + DiscordBot.BotID + "&scope=bot&permissions=0))\n");
eb.appendDescription("Connected guilds: `" + DiscordBot.mainJDA.getGuildCache().size() + (DiscordBot.mainJDA.getShardManager() == null ? "" : "/" + DiscordBot.mainJDA.getShardManager().getShards().stream().mapToLong(jda -> jda.getGuildCache().size()).sum()) + "`; ");
eb.appendDescription("Total members (cached): `" + DiscordBot.mainJDA.getUserCache().size() + (DiscordBot.mainJDA.getShardManager() == null ? "" : "/" + DiscordBot.mainJDA.getShardManager().getShards().stream().mapToLong(jda -> jda.getUserCache().size()).sum()) + "`\n");
eb.appendDescription("DM `" + DiscordBot.mainJDA.getUserById(DiscordBot.OwnerID).getAsTag() + "` if you have any questions!\n");
eb.appendDescription("To get a list of commands, do `" + prefix + "help`.");
smsg.setEmbed(eb.build());
Message fmsg = smsg.build();
channel.sendMessage(fmsg).queue();
return new CommandResult(CommandResultType.SUCCESS, null);
}
@Override
public void onGuildMessageUpdate(GuildMessageUpdateEvent event) {
//System.out.println("edit"); //debug
Message msg = event.getMessage();
User author = event.getAuthor();
TextChannel channel = event.getChannel();
if (!DiscordBot.logExcemptID.contains(author.getId())) {
String guildinfo = "[" + event.getGuild().getName() + " #" + channel.getName() + "]";
DiscordBot.logger.trace("[EDIT] " + guildinfo + System.lineSeparator() + " " + msg + System.lineSeparator() + " Full edited msg: " + msg.getContentDisplay());
}
}
@Override
public void onUserActivityStart(UserActivityStartEvent event) { //store presence for checking osu pp
Activity osu = event.getNewActivity();
if (osu != null && osu.getName().equals("osu!") && osu.isRich() //if need to include other games and details, just remove this if clause and change sGame below
&& osu.asRichPresence().getDetails() != null) {
String toolTip = osu.asRichPresence().getLargeImage().getText();
//DiscordBot.guildMemberPresence.put(event.getUser().getId(), game); //so that game update to nothing wont be logged
/*System.out.println(event.getGuild().getName());
System.out.println(event.getUser().getName());
System.out.println(game.getName());
System.out.println(game.getUrl());
System.out.println(game.getType());
System.out.println(game.isRich() ? game.asRichPresence().getDetails() : "no rich");
System.out.println(game.isRich() ? game.asRichPresence().getState() : "no rich");*/
//OffsetDateTime timesent = OffsetDateTime.now();
//System.out.println(toolTip);
String sGame = (toolTip.lastIndexOf(" (") != -1 ? toolTip.substring(0, toolTip.lastIndexOf(" (")) : toolTip) + "||" + osu.asRichPresence().getDetails();
//sGame = sGame.replaceAll("'", "''");
/*OffsetDateTime timeReceived = OffsetDateTime.now();
long ms = Math.abs(timesent.until(timeReceived, ChronoUnit.MILLIS));
System.out.println("Time taken: " + ms + "ms");*/
try (Connection con = DiscordBot.db.getConnection()) { //DONE do i need to close the statement?
PreparedStatement s = con.prepareStatement("INSERT INTO users(id, game) VALUES (" + event.getUser().getId() + ", ?) ON CONFLICT(id) DO UPDATE SET game = ? WHERE game <> ?;" ); //prevent blank updates
s.setString(1, sGame); s.setString(2, sGame); s.setString(3, sGame);
s.execute();
//con.createStatement().execute("INSERT INTO users(id, game) VALUES (" + event.getUser().getId() + ", '" + sGame + "') ON CONFLICT(id) DO UPDATE SET game = '" + sGame + "' WHERE game <> '" + sGame + "';" ); //prevent blank updates
} catch (SQLException e) { //FIXED if i make this not osu only, be aware of SQL injections through sGame (probably being paranoid tho)
e.printStackTrace();
}
/*timeReceived = OffsetDateTime.now();
ms = Math.abs(timesent.until(timeReceived, ChronoUnit.MILLIS));
System.out.println("Time taken: " + ms + "ms");*/
}
}
//TODO only update when not paused?
//TODO update on member deafen?
private void waitActivity(Guild guild) {
AudioTrackHandler ap = ((Music) DiscordBot.commands.get("music")).getAudioTrackHandler();
ap.getGuildMusicManager(guild).player.setPaused(true);
ap.getGuildMusicManager(guild).clearQueueCleanup = ap.ex.schedule(() -> {
ap.stopAndClearQueue(guild);
DiscordBot.lastMusicCmd.get(guild.getId()).sendMessage("The queue has been cleared.").queue();
ap.getGuildMusicManager(guild).clearQueueCleanup = null;
}, 1, TimeUnit.MINUTES);
}
private String updateActivity(Guild guild, VoiceChannel vc) {
AudioTrackHandler ap = ((Music) DiscordBot.commands.get("music")).getAudioTrackHandler();
GuildMusicManager mm = ap.getGuildMusicManager(guild);
if(mm.clearQueueCleanup != null) {
mm.player.setPaused(false);
mm.clearQueueCleanup.cancel(true);
mm.clearQueueCleanup = null;
}
String type = mm.scheduler.loop; //mm cannot be null
if (type != null
&& vc.getMembers().size() > 2
&& vc.getMembers().contains(guild.getMemberById(DiscordBot.OwnerID))) {
ap.toggleLoopQueue(guild, type);
return type;
}
return null;
}
@Override
public void onGuildVoiceLeave(GuildVoiceLeaveEvent event) { // theoretically i dont need to check if lastMusicCmd has the entry or not, as it must have one to trigger this
GuildVoiceState vs = event.getGuild().getMemberById(DiscordBot.BotID).getVoiceState();
if(!event.getMember().getUser().getId().equals(DiscordBot.BotID)) {
if (vs.inVoiceChannel()) {
if (vs.getChannel().equals(event.getChannelLeft())
&& event.getChannelLeft().getMembers().size() < 2) {
TextChannel channel = DiscordBot.lastMusicCmd.get(event.getGuild().getId());
channel.sendMessage(
"All users have left the music channel, the player is now paused.\nThe queue will be cleared in 1 minute if there is no activity.")
.queue();
waitActivity(event.getGuild());
}
}
} else { //got kicked
AudioTrackHandler ap = ((Music) DiscordBot.commands.get("music")).getAudioTrackHandler();
if(ap != null) { //if not destroyed
ap.stopAndClearQueue(event.getGuild()); //can double fire on normal end; shouldnt be too big of a problem
}
}
}
@Override
public void onGuildVoiceMove(GuildVoiceMoveEvent event) { // theoretically i dont need to check if lastMusicCmd has the entry or not, as it must have one to trigger this
GuildVoiceState vs = event.getGuild().getMemberById(DiscordBot.BotID).getVoiceState();
if (vs.inVoiceChannel()) {
String id = event.getGuild().getId();
TextChannel channel = DiscordBot.lastMusicCmd.get(id);
if (!event.getMember().getUser().getId().equals(DiscordBot.BotID)) {
if (vs.getChannel().equals(event.getChannelLeft())) {
if (!event.getMember().getUser().getId().equals(DiscordBot.BotID)
&& event.getChannelLeft().getMembers().size() < 2) {
channel.sendMessage(
"All users have left the music channel, the player is now paused.\nThe queue will be cleared in 1 minute if there is no activity.")
.queue();
waitActivity(event.getGuild());
}
} else if (vs.getChannel().equals(event.getChannelJoined())) {
String type = updateActivity(event.getGuild(), event.getChannelJoined());
if(type != null) channel.sendMessage((type.equals("loop") ? "Looping" : "Autoplay") + " mode disabled due to new users joining the music channel.").queue();
}
} else { //moved bot to empty channel
if(event.getChannelJoined().getMembers().size() < 2) {
channel.sendMessage(
"The bot has been moved to an empty channel, the player is now paused.\nThe queue will be cleared in 1 minute if there is no activity.")
.queue();
waitActivity(event.getGuild());
} else { //moved bot to channel with ppl
event.getGuild().getAudioManager().openAudioConnection(event.getChannelJoined()); //seems to need explicit reconnect on bot move, it gets stuck on attempting to reconnect otherwise; probably would be fixed soon but hot patch for now
String type = updateActivity(event.getGuild(), event.getChannelJoined());
if(type != null) channel.sendMessage((type.equals("loop") ? "Looping" : "Autoplay") + " mode disabled due to new users joining the music channel.").queue();
}
}
}
}
@Override
public void onGuildVoiceJoin(GuildVoiceJoinEvent event) {
GuildVoiceState vs = event.getGuild().getMemberById(DiscordBot.BotID).getVoiceState();
String id = event.getGuild().getId();
TextChannel channel = DiscordBot.lastMusicCmd.get(id);
if(channel != null) {
if (vs.inVoiceChannel() && !event.getMember().getUser().getId().equals(DiscordBot.BotID)) {
if (vs.getChannel().equals(event.getChannelJoined())) {
String type = updateActivity(event.getGuild(), event.getChannelJoined());
if(type != null) channel.sendMessage((type.equals("loop") ? "Looping" : "Autoplay") + " mode disabled due to new users joining the music channel.").queue();
}
}
}
}
}

File Metadata

Mime Type
text/x-java
Expires
Mon, Jul 7, 4:40 AM (1 d, 9 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
79/65/053f84d5547569168524a9cfe7ad

Event Timeline