Page MenuHomedesp's stash

No OneTemporary

diff --git a/.gitignore b/.gitignore
index 13f2d81..eb331cc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,9 @@
bin/
target/
logs/
.metadata/
tokens.properties
+eastereggs.properties
testAnimePicCache.bin
data.db
hs_err_pid*.log
diff --git a/src/me/despawningbone/discordbot/DiscordBot.java b/src/me/despawningbone/discordbot/DiscordBot.java
index 513354f..a37ec66 100644
--- a/src/me/despawningbone/discordbot/DiscordBot.java
+++ b/src/me/despawningbone/discordbot/DiscordBot.java
@@ -1,286 +1,290 @@
package me.despawningbone.discordbot;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import javax.security.auth.login.LoginException;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.PropertyConfigurator;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import me.despawningbone.discordbot.command.Command;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.requests.GatewayIntent;
public class DiscordBot {
// TODO move to appropriate locations
//public static List<String> BannedID = new ArrayList<String>(); //DONE store in DB
public static List<String> ModID = new ArrayList<String>();
public static List<String> logExcemptID = new ArrayList<String>();
//TODO synchronize below or change to concurrent //but why? its thread safe since its read only
public static HashMap<String, Command> commands = new HashMap<String, Command>();
public static HashMap<String, Command> aliases = new HashMap<String, Command>(); //TODO temporary solution
public static TreeMap<String, List<Command>> catCmds = new TreeMap<String, List<Command>>(); //order base on categories?
public static ConcurrentHashMap<String, TextChannel> lastMusicCmd = new ConcurrentHashMap<String, TextChannel>(); //TODO store in guild configs //nah its fine
//public static HashMap<String, Game> guildMemberPresence = new HashMap<String, Game>();
public static final String prefix = "!desp "; //DONE allow guild change prefix?
public static JDA mainJDA = null;
- public static final String BotID = "311086271642599424";
- public static final String OwnerID = "237881229876133888";
+ public static String BotID;
+ public static String OwnerID;
public static Properties tokens = new Properties();
static final Logger logger = LoggerFactory.getLogger(DiscordBot.class); //package private
public static HikariDataSource db;
/*public static FirefoxDriver driver;*/
// DONE SQLite integration; check if program termination will screw up the connection
// TODO SHARDING
// DONE on shutdown alert those playing music or await? //alerted
public static void main(String[] args) {
// initiate Selenium
/*System.setProperty("webdriver.gecko.driver",
System.getProperty("user.dir") + File.separator + "geckodriver.exe");
FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);
driver = new FirefoxDriver(options);*/
PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.properties");
try(FileInputStream in = new FileInputStream(new File(System.getProperty("user.dir") + File.separator + "tokens.properties"))){
tokens.load(in);
} catch (IOException e) {
e.printStackTrace();
return;
}
initCmds();
initDB();
// login
try {
JDA jda = JDABuilder.create(tokens.getProperty("bot"), GatewayIntent.getIntents(GatewayIntent.ALL_INTENTS))
//.setAudioSendFactory(new NativeAudioSendFactory()) //segfaults frequently somehow, disabling
.addEventListeners(new me.despawningbone.discordbot.EventListener()).build();
jda.getPresence().setActivity(Activity.watching("Ping me for info!"));
// for user bots, see
// https://discordapp.com/developers/docs/topics/gateway#update-status
// and
// https://gist.github.com/MrPowerGamerBR/b8acccb9951b0d78a5115024e3ee0d03
+
+ //find owner id from bot owner
+ BotID = jda.getSelfUser().getId();
+ OwnerID = jda.retrieveApplicationInfo().complete().getOwner().getId();
} catch (LoginException e) {
e.printStackTrace();
return;
}
// initiate logs //handled by log4j?
File directory = new File(System.getProperty("user.dir") + File.separator + "logs" + File.separator);
if (!directory.exists()) {
directory.mkdir();
}
//initiate test anime pics cache for repost check
/*try {
FileInputStream in = new FileInputStream(System.getProperty("user.dir") + File.separator + "testAnimePicCache.bin");
ObjectInputStream ois = new ObjectInputStream(in);
EventListener.testAnimePicCache = (Multimap<String, String>) ois.readObject();
ois.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> { //no need to be a global variable since i dont need to access it
try {
FileOutputStream out = new FileOutputStream(System.getProperty("user.dir") + File.separator + "testAnimePicCache.bin");
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(EventListener.testAnimePicCache);
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}, 1, 5, TimeUnit.MINUTES);*/
// DEPRECATED //or is it? make unmodifiable instead
for(String id : tokens.getProperty("botmod").split(",")) {
ModID.add(id);
}
ModID.add(OwnerID);
logExcemptID.add(BotID);
}
private static void initDB() { //init guild settings when do !desp settings for the first time? //dont really need coz im doing upsert for all values anyways
HikariConfig dbConf = new HikariConfig();
dbConf.setJdbcUrl("jdbc:sqlite:data.db");
dbConf.setIdleTimeout(45000);
dbConf.setMaxLifetime(60000);
dbConf.setMaximumPoolSize(10);
//dbConf.setMaximumPoolSize(25); //for deployment in server
db = new HikariDataSource(dbConf);
try (Connection con = db.getConnection()){
Statement s = con.createStatement();
s.execute("CREATE TABLE IF NOT EXISTS settings"
+ "(id INTEGER PRIMARY KEY," //performance problem using text; integer can handle long anyways
+ "prefix TEXT DEFAULT '!desp ',"
+ "premium INTEGER DEFAULT 0,"
+ "mchannel TEXT," //allow people to set this manually? By default, use last music cmd place
+ "locale TEXT DEFAULT 'EN'," //or int? //user specific or guild specific, or user override guild?
+ "shortcuts TEXT," //use another method?
+ "votepct INTEGER DEFAULT 50,"
+ "looplimit INTEGER DEFAULT 1,"
+ "volume INTEGER DEFAULT 100," //premium?, is default actually 100?
+ "helpdm INTEGER DEFAULT 0);"); //send help to dm or not, excluding cmd help(?)
//add logexempt?
PreparedStatement pragma = con.prepareStatement("SELECT name FROM pragma_table_info('perms_' || ?);"); //NOTE: sqlite does not support changing default values, beware when adding new commands
for(Entry<String, List<Command>> entry : catCmds.entrySet()) {
pragma.setString(1, entry.getKey().toLowerCase());
ResultSet rs = pragma.executeQuery();
boolean isEmpty = true;
HashMap<String, EnumSet<Permission>> nodes = new HashMap<>();
Stack<Command> tree = new Stack<>();
for(Command cmd : entry.getValue()) tree.push(cmd); //populate stack coz there is no root node
while(!tree.empty()) {
Command cmd = tree.pop();
String name = cmd.getName();
for(Command iterate = cmd.getParent(); iterate != null; iterate = iterate.getParent()) {
name = iterate.getName() + "." + name;
}
nodes.put(name, cmd.getDefaultPerms());
for(String sub : cmd.getSubCommandNames()) {
tree.push(cmd.getSubCommand(sub));
}
}
while(rs.next()) {
isEmpty = false;
nodes.remove(rs.getString("name")); //remove already added node names
}
if(isEmpty) {
String create = "CREATE TABLE perms_" + entry.getKey().toLowerCase() + " (id INTEGER PRIMARY KEY, _GLOBAL_ TEXT DEFAULT '0\n', "; //perms for a category are always default no restraints
StringJoiner join = new StringJoiner(", ");
for(Entry<String, EnumSet<Permission>> node : nodes.entrySet()) {
join.add("\"" + node.getKey() + "\" TEXT DEFAULT '" + ((0L << 32) | (Permission.getRaw(node.getValue()) & 0xffffffffL)) + "\n'"); //initialize with no permission deny override, permissions allow //needs to be text so that channel overrides delimiter can be stored
}
create += join.toString() + ");";
s.execute(create);
//DONE? create table
} else {
if(!nodes.isEmpty()) { //which means there is new subCmd/cmd
for(Entry<String, EnumSet<Permission>> node : nodes.entrySet()) {
s.execute("ALTER TABLE perms_" + entry.getKey().toLowerCase() + " ADD COLUMN \"" + node.getKey() + "\" TEXT DEFAULT '" + ((0L << 32) | (Permission.getRaw(node.getValue()) & 0xffffffffL)) + "\n';"); //not able to prep statement coz its column name
s.close();
}
}
}
}
pragma.close();
//DONE TEST generate the nodes, retrieve default from fields? //what about additional commands added, use ALTER TABLE ADD COLUMN DEFAULT? I dont need to sort it according to category at all, i am not and will not be bulk printing permissions anywhere //actually i might be coz of list edited perms
//fit subnodes into sub tables, split by category so its more balanced (category as table name)?
//fields are gonna be sth like <channelid>:<perm>|<perm> etc?
//DONE store the permissions with long merged; <32bit = deny, >32bit = allow
s.execute("CREATE TABLE IF NOT EXISTS users"
+ "(id INTEGER PRIMARY KEY,"
+ "reports TEXT DEFAULT '',"
+ "game TEXT);"); //disposable, i can change it anytime
//add botmod field? if so, i can deprecate the hard coded list, but it would require querying to this table on perm checks //i need to query it to check if the user is banned anyways //subcmd need to query again, so i didnt do it; besides the modlist is gonna be too small to be significant anyways
//add user specific locale? might be confusing
s.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
private static void initCmds() {
Reflections reflections = new Reflections("me.despawningbone.discordbot.command");
Set<Class<? extends Command>> classes = reflections.getSubTypesOf(Command.class);
for (Class<? extends Command> s : classes) {
try {
if (Modifier.isAbstract(s.getModifiers())) {
continue;
}
String pkName = s.getPackage().getName();
String cat = StringUtils.capitalize(pkName.substring(pkName.lastIndexOf(".") + 1));
//if(cat.equals("Osu")) cat = "osu!";
Command c = s.getConstructor().newInstance(); //DONE use constructor to put name and cat instead
if (c.isDisabled()) {
continue;
}
try { //init name and cat
Field nameF = Command.class.getDeclaredField("name");
nameF.setAccessible(true);
if(nameF.get(c) == null) nameF.set(c, s.getSimpleName().toLowerCase()); //allow overrides
Field catF = Command.class.getDeclaredField("cat");
catF.setAccessible(true);
catF.set(c, cat);
} catch (NoSuchFieldException e) { //should never throw
e.printStackTrace();
}
// check disable whole command category?
List<Command> cmds = catCmds.get(cat);
if(cmds == null) {
cmds = new ArrayList<Command>(Arrays.asList(c));
} else {
cmds.add(c);
}
catCmds.put(cat, cmds);
// set command category?
commands.put(c.getName(), c);
List<String> l = c.getAliases();
if(l != null) {
for(int i = 0; i < l.size(); i++) {
aliases.put(l.get(i), c);
}
}
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
for(Entry<String, List<Command>> entry : catCmds.entrySet()) {
Collections.sort(entry.getValue(), (a, b) -> a.getName().compareTo(b.getName()));
}
}
}
diff --git a/src/me/despawningbone/discordbot/EventListener.java b/src/me/despawningbone/discordbot/EventListener.java
index 88e9434..96b5091 100644
--- a/src/me/despawningbone/discordbot/EventListener.java
+++ b/src/me/despawningbone/discordbot/EventListener.java
@@ -1,441 +1,416 @@
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(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") || cmd.isDisabled()) {
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");
}
- if (author.getId().equals("237881229876133888")) { // easter eggs
- smsg.append("How art thou, my creator?");
- }
- if (author.getId().equals("179824176847257600")) {
- smsg.append("Still stalking as usual, huh? :smirk:");
- smsg.append("\n\"go fix your potatoes\" - pugger");
- }
- if (author.getId().equals("165403578133905408")) {
- smsg.append(
- "You're probably still dead :D (your status), either that or you are playing with your doodle :P");
- }
- if (author.getId().equals("187714189672841216")) {
- smsg.append("Hello, fearsome coder named Morgan :wink:");
- }
- if (author.getId().equals("201768560345743360")) {
- smsg.append("Still need help to save you from the school? :D");
- }
- if (author.getId().equals("257660112703979521")) {
- smsg.append("I like how you only uses me for `!desp roll 1`. :P");
- }
- if (author.getId().equals("272712701988569090")) {
- smsg.append("This guy is generous :smile:");
- }
- if (author.getId().equals("203861130995695616")) {
- smsg.append("He asked my owner to change it so here it is :smile:");
- }
- if (author.getId().equals("206038522971422721")) {
- smsg.append("Appearently he loves !desp idiot :face_palm:");
- }
- if (author.getId().equals("218377806994866176")) {
- smsg.append("Your potatoes seems better than Dank's :smirk:");
- }
- if (author.getId().equals("139316803582033920")) {
- smsg.append("That ironic name tho :stuck_out_tongue:");
- }
- if (author.getId().equals("237058431272484864")) {
- smsg.append(":b:oi");
- }
- if (author.getId().equals("338258756762730496")) {
- smsg.append("**a e s t h e t i c**");
+ 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=311086271642599424&scope=bot&permissions=0))\n");
+ 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 `despawningbone#4078` if you have any questions!\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();
}
}
}
}
}
diff --git a/src/me/despawningbone/discordbot/command/admin/UserReport.java b/src/me/despawningbone/discordbot/command/admin/UserReport.java
index d36f349..f9f846c 100644
--- a/src/me/despawningbone/discordbot/command/admin/UserReport.java
+++ b/src/me/despawningbone/discordbot/command/admin/UserReport.java
@@ -1,183 +1,183 @@
package me.despawningbone.discordbot.command.admin;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.exception.ExceptionUtils;
import me.despawningbone.discordbot.DiscordBot;
import me.despawningbone.discordbot.command.Command;
import me.despawningbone.discordbot.command.CommandResult;
import me.despawningbone.discordbot.command.CommandResult.CommandResultType;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
public class UserReport extends Command {
public UserReport() {
this.alias = Arrays.asList("ureport");
this.desc = "Report a user if they are abusing the bot!";
this.usage = "<userID/username>";
this.remarks = Arrays.asList("Note: 5 global reports will result in a ban from the bot.");
- this.examples = Arrays.asList(DiscordBot.OwnerID, "despawningbone");
+ this.examples = Arrays.asList("311086271642599424", "despawningbone");
}
@Override
public CommandResult execute(TextChannel channel, User author, Message msg, String[] args) {
if (args.length < 1) {
return new CommandResult(CommandResultType.INVALIDARGS, "Please specify which user you want to report.");
} else {
String SID = null;
boolean success = true;
String pname = String.join(" ", args);
long ID = 0;
try {
ID = Long.parseLong(pname);
} catch (NumberFormatException e) {
success = false;
// System.out.println(pname); //debug
List<Member> pm = channel.getGuild().getMembersByEffectiveName(pname, true);
if (pm.size() <= 0) {
return new CommandResult(CommandResultType.FAILURE, "There is no such user.");
} else if (pm.size() > 1) {
return new CommandResult(CommandResultType.FAILURE, "Theres more than 1 user with the same name. Please use !desp ID to get the ID of the user you want to report.");
} else {
SID = pm.get(0).getUser().getId();
ID = Long.parseLong(SID);
}
}
if (success == true) {
SID = Long.toString(ID);
}
if (author.getId().equals(SID)) {
return new CommandResult(CommandResultType.FAILURE, "You cannot report yourself you dumbo :stuck_out_tongue:");
} else if (DiscordBot.ModID.contains(SID) || SID.equals(DiscordBot.BotID)) {
return new CommandResult(CommandResultType.FAILURE, "That user cannot be reported.");
}
try (Connection con = DiscordBot.db.getConnection(); Statement s = con.createStatement()) {
String reports = "";
ResultSet uRs = s.executeQuery("SELECT reports FROM users WHERE id = " + SID + ";");
if(uRs.next()) {
reports = uRs.getString(1);
if(reports.contains(author.getId())) {
return new CommandResult(CommandResultType.FAILURE, "You cannot report a user more than once."); //make it so that its toggling the reports instead?
} else if(reports.split("\n").length < 5){
reports += author.getId() + "\n";
} else {
return new CommandResult(CommandResultType.FAILURE, "The user has already been banned!");
}
} else {
reports = author.getId() + "\n";
}
PreparedStatement set = con.prepareStatement("INSERT INTO users(id, reports) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET reports = ?" );
set.setString(1, SID);
set.setString(2, reports); set.setString(3, reports);
int update = set.executeUpdate();
if(update != 0) {
int times = reports.split("\n").length;
channel.sendMessage("You have successfully reported <@!" + ID + ">.\nThe user has been reported for "
+ times + "/5 times.\n").queue();
if(times >= 5) {
channel.sendMessage("The user <@!" + ID + "> is now banned from using the bot.").queue();
}
return new CommandResult(CommandResultType.SUCCESS);
} else {
throw new IllegalArgumentException("This should never happen");
}
} catch (SQLException e) {
return new CommandResult(CommandResultType.ERROR, ExceptionUtils.getStackTrace(e));
}
/*for (int i = 0; i < DiscordBot.reportedlist.size(); i++) {
String[] randrp = DiscordBot.reportedlist.get(i).split(" ");
if (randrp[0].contains(author.getId()) && randrp[1].contains(SID)) {
return new CommandResult(CommandResultType.FAILURE, "You cannot report a user more than once.");
}
}
boolean banned = false;
boolean contains = false;
for (int i = 0; i < DiscordBot.playerreportlist.size(); i++) {
if (DiscordBot.playerreportlist.get(i).contains(SID)) {
contains = true;
}
}
if (contains == false) {
DiscordBot.playerreportlist.add(SID + " " + "1");
times = 1;
FileWriter fileWriter = null;
BufferedWriter bufferedWriter;
try {
fileWriter = new FileWriter(DiscordBot.pfile, true);
} catch (IOException e1) {
e1.printStackTrace();
}
try {
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(SID + " " + "1" + "\r\n");
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
// System.out.println("Got record");//debug
for (int i = 0; i < DiscordBot.playerreportlist.size(); i++) {
String[] pandt = DiscordBot.playerreportlist.get(i).split(" ");
if (pandt[0].contains(SID)) {
times = Long.parseLong(pandt[1]);
// System.out.println(times); //debug
if (times < 5) {
times = times + (long) 1;
// System.out.println(times); //debug
if (times == 5) {
DiscordBot.BannedID.add(Long.toString(ID));
banned = true;
}
DiscordBot.playerreportlist.set(i, SID + " " + Long.toString(times));
Path fp = Paths.get(System.getProperty("user.dir"), "PlayerReports.txt");
try {
List<String> fileContent = new ArrayList<>(
Files.readAllLines(fp, StandardCharsets.UTF_8));
for (int f = 0; f < fileContent.size(); f++) {
if (fileContent.get(f).startsWith(SID)) {
fileContent.set(f, SID + " " + Long.toString(times));
break;
}
}
Files.write(fp, fileContent, StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
break;
} else {
if (!DiscordBot.BannedID.contains(String.valueOf(ID))) {
DiscordBot.BannedID.add(Long.toString(ID));
}
return new CommandResult(CommandResultType.FAILURE, "The user <@!" + ID
+ "> had enough reports therefore he is banned from using this bot.");
}
}
}
}
DiscordBot.reportedlist.add(author.getId() + " " + SID);
channel.sendMessage("You have successfully reported <@!" + ID + ">.\nThe user has been reported for "
+ times + "/5 times.\n").queue();
String addinfo = null;
if (banned == true) {
channel.sendMessage("The user <@!" + ID + "> is now banned from using the bot.").queue();
addinfo = channel.getGuild().getMemberById(SID).getEffectiveName() + " (" + SID
+ ") is banned from the bot.";
}
return new CommandResult(CommandResultType.SUCCESS, addinfo);*/
}
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, May 8, 8:16 AM (12 h, 25 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
3b/61/1a1898ffee84b04a0e2c11815dcc

Event Timeline