diff --git a/.classpath b/.classpath index 91ec221..e147ff5 100644 --- a/.classpath +++ b/.classpath @@ -1,9 +1,14 @@ - - - - + + + + + + + + + diff --git a/src/pkg/deepCurse/nopalmo/command/GuildCommand.java b/src/pkg/deepCurse/nopalmo/command/GuildCommand.java new file mode 100644 index 0000000..b163baf --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/command/GuildCommand.java @@ -0,0 +1,42 @@ +package pkg.deepCurse.nopalmo.command; + +import java.util.List; + +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import pkg.deepCurse.nopalmo.manager.GuildCommandManager; + +public abstract class GuildCommand { + + public abstract void run(List args, GuildMessageReceivedEvent guildMessage, GuildCommandManager commandManager) throws Exception; + + public abstract String[] getCommandCalls(); + + public String getCommandName() { + return getCommandCalls()[0]; + } + + public boolean isHidden() { + return false; + } + + public boolean isNSFW() { + return false; + } + + public Permission[] getRequiredPermissions() { + return null; + } + + public boolean isPremium() { // im probably never gonna use this, but ill leave it in for those who want to + // see how i would implement it + return false; + } + + public abstract HelpPage getHelpPage(); + + public enum HelpPage { + General, DEV, EGG, Moderation, Fun, Info + } + +} diff --git a/src/pkg/deepCurse/nopalmo/command/guildCommand/Ping.java b/src/pkg/deepCurse/nopalmo/command/guildCommand/Ping.java new file mode 100644 index 0000000..f59a26a --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/command/guildCommand/Ping.java @@ -0,0 +1,29 @@ +package pkg.deepCurse.nopalmo.command.guildCommand; + +import java.util.List; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import pkg.deepCurse.nopalmo.command.GuildCommand; +import pkg.deepCurse.nopalmo.database.DatabaseTools; +import pkg.deepCurse.nopalmo.manager.GuildCommandManager; + +public class Ping extends GuildCommand { + + @Override + public void run(List args, GuildMessageReceivedEvent guildMessage, GuildCommandManager commandManager) + throws Exception { + + DatabaseTools.Tools.Guild.Prefix.createPrefix(guildMessage.getGuild().getIdLong(), args.get(0)); + + } + + @Override + public String[] getCommandCalls() { + return new String[] {"ping"}; + } + + @Override + public HelpPage getHelpPage() { + return HelpPage.Info; + } +} diff --git a/src/pkg/deepCurse/nopalmo/core/Boot.java b/src/pkg/deepCurse/nopalmo/core/Boot.java index eec22c8..634cea1 100644 --- a/src/pkg/deepCurse/nopalmo/core/Boot.java +++ b/src/pkg/deepCurse/nopalmo/core/Boot.java @@ -1,16 +1,36 @@ package pkg.deepCurse.nopalmo.core; +import javax.security.auth.login.LoginException; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.requests.GatewayIntent; +import net.dv8tion.jda.api.utils.ChunkingFilter; +import net.dv8tion.jda.api.utils.MemberCachePolicy; +import pkg.deepCurse.nopalmo.listener.GuildMessageReceivedListener; import pkg.deepCurse.simpleLoggingGarbage.core.Log; public class Boot { + public static JDA bot; + public static void main(String[] args) { Log.boot("Booting. . ."); long preBootTime = System.currentTimeMillis(); - - - + + try { + bot = JDABuilder.createDefault(args[0]).setChunkingFilter(ChunkingFilter.NONE) + .setMemberCachePolicy(MemberCachePolicy.NONE).enableIntents(GatewayIntent.GUILD_MEMBERS) + .setActivity(Activity.watching("Loading users...")).setIdle(true) + .addEventListeners(new GuildMessageReceivedListener()).build().awaitReady(); + } catch (LoginException e) { + Log.crash(e); + } catch (InterruptedException e) { + e.printStackTrace(); + } + long bootTime = System.currentTimeMillis() - preBootTime; } diff --git a/src/pkg/deepCurse/nopalmo/database/DatabaseTools.java b/src/pkg/deepCurse/nopalmo/database/DatabaseTools.java new file mode 100644 index 0000000..7173180 --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/database/DatabaseTools.java @@ -0,0 +1,324 @@ +package pkg.deepCurse.nopalmo.database; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.annotation.Nonnull; + +import org.jetbrains.annotations.Nullable; + +import pkg.deepCurse.simpleLoggingGarbage.core.Log; + +public class DatabaseTools { + + private static Connection connection; + + public DatabaseTools(String password) { + connection = createConnection(password); + } + + public static Connection createConnection(String password) { + String driver = "com.mysql.cj.jdbc.Driver"; + String url = "jdbc:mysql://localhost/nopalmo"; + String username = "u1d"; + try { + Class.forName(driver); + } catch (ClassNotFoundException e) { + Log.crash(e); + } + + try { + return DriverManager.getConnection(url, username, password); + } catch (SQLException e) { + sqlTranslate("Generate connection", e); + } + return null; + } + + private static void sqlTranslate(String action, int errorCode) { + switch (errorCode) { + case 1062: + System.err.println("Failed to execute; errorCode=1062; Duplicate ID; On action " + action); + break; + default: + System.err.println("Failed to execute; errorCode=" + errorCode + "; Unknown code; On action " + action); + break; + } + } + + @Deprecated + private static void sqlTranslate(String action, SQLException e) { + sqlTranslate(action, e.getErrorCode()); + } + + private static void sqlTranslate(PreparedStatement pstmt, SQLException e) { + sqlTranslate(pstmt.toString(), e.getErrorCode()); + } + + private static void checkUpdateCounts(PreparedStatement pstmt, int[] updateCounts) { + checkUpdateCounts(pstmt.toString(), updateCounts); + } + + @Deprecated + public static void checkUpdateCounts(String action, int[] updateCounts) { + for (int i = 0; i < updateCounts.length; i++) { + if (updateCounts[i] >= 0) { + System.out.println("Successfully executed; updateCount=" + updateCounts[i] + "; On action " + action); + } else if (updateCounts[i] == Statement.SUCCESS_NO_INFO) { + System.out.println("Successfully executed; updateCount=Statement.SUCCESS_NO_INFO; On action " + action); + } else if (updateCounts[i] == Statement.EXECUTE_FAILED) { + System.out.println("Failed to execute; updateCount=Statement.EXECUTE_FAILED; On action " + action); + } + } + } + + public class Tools { + + public class Guild { + + public class Prefix { + + @Nullable + public static String getPrefix(@Nonnull long guildID) { + Statement st = null; + ResultSet rs = null; + String query = "select * from guilds where guildid = " + guildID; + try { + st = connection.createStatement(); + rs = st.executeQuery(query); + if (rs.next()) { + return rs.getString("prefix"); + } else { + // throw new SQLException(null, null, 33); // we need a real catcher here + System.err.println( + "Failed to execute; errorCode=NO_ROW_FOUND; No row found; On action " + query); + return null; + } + + } catch (SQLException e) { + sqlTranslate(query, e.getErrorCode()); + // System.out.println("eeeeee"); + return null; + } finally { + try { + if (rs != null) + rs.close(); + } catch (Exception e) { + } + + try { + if (st != null) + st.close(); + } catch (Exception e) { + } + + // try { if (conn != null) conn.close(); } catch (Exception e) {}; + } + // return null; + } + + public static void createPrefix(@Nonnull long guildID, @Nullable String prefix) + throws IllegalArgumentException { + + if (prefix == null || prefix.isEmpty()) { + // throw new IllegalArgumentException("Input cannot be empty"); + prefix = ";"; + } + + PreparedStatement pstmt = null; + + String query = "insert into guilds(guildid, prefix) values(?, ?);"; + try { + pstmt = connection.prepareStatement(query); + + pstmt.setLong(1, guildID); + pstmt.setString(2, prefix); + pstmt.addBatch(); + + int[] updateCounts = pstmt.executeBatch(); + checkUpdateCounts(pstmt, updateCounts); + pstmt.close(); + connection.commit(); + } catch (SQLException e) { + sqlTranslate(pstmt, e); + + for (int i : new int[] { 1062 }) { + if (i == e.getErrorCode()) { + setPrefix(connection, guildID, prefix); + break; + } + } + + try { + connection.rollback(); + } catch (Exception e2) { + e.printStackTrace(); + } + + } + } + + public static void setPrefix(Connection conn, long guildID, String prefix) + throws IllegalArgumentException { + + if (prefix.isEmpty()) { + throw new IllegalArgumentException("Input cannot be empty"); + } + + PreparedStatement pstmt = null; + + String query = "update guilds set prefix = ? where guildid = ?;"; + try { + pstmt = conn.prepareStatement(query); + + pstmt.setLong(2, guildID); + pstmt.setString(1, prefix); + pstmt.addBatch(); + + int[] updateCounts = pstmt.executeBatch(); + checkUpdateCounts(pstmt, updateCounts); + pstmt.close(); + conn.commit(); + } catch (SQLException e) { + sqlTranslate(pstmt, e); + try { + conn.rollback(); + } catch (Exception e2) { + e.printStackTrace(); + } + + } + } + } + } + + public class Developers { + + public static boolean canPowerOffBot(long userID) { + Statement st = null; + ResultSet rs = null; + String query = "select * from developers where userid = " + userID; + try { + st = connection.createStatement(); + rs = st.executeQuery(query); + if (rs.next()) { + return rs.getBoolean("canpoweroffbot"); + } else { + // throw new SQLException(null, null, 33); // we need a real catcher here + System.err + .println("Failed to execute; errorCode=NO_ROW_FOUND; No row found; On action " + query); + return false; + } + + } catch (SQLException e) { + sqlTranslate(query, e.getErrorCode()); + // System.out.println("eeeeee"); + return false; + } finally { + try { + if (rs != null) + rs.close(); + } catch (Exception e) { + } + + try { + if (st != null) + st.close(); + } catch (Exception e) { + } + + // try { if (conn != null) conn.close(); } catch (Exception e) {}; + } + // return null; + } + + } + + public class Global { + + public static String getPrefix() { + Statement st = null; + ResultSet rs = null; + String query = "select * from global where id = 'prefix'"; + try { + st = connection.createStatement(); + rs = st.executeQuery(query); + if (rs.next()) { + return rs.getString("val"); + } else { + // throw new SQLException(null, null, 33); // we need a real catcher here + System.err + .println("Failed to execute; errorCode=NO_ROW_FOUND; No row found; On action " + query); + return null; + } + + } catch (SQLException e) { + sqlTranslate(query, e.getErrorCode()); + // System.out.println("eeeeee"); + return null; + } finally { + try { + if (rs != null) + rs.close(); + } catch (Exception e) { + } + + try { + if (st != null) + st.close(); + } catch (Exception e) { + } + + // try { if (conn != null) conn.close(); } catch (Exception e) {}; + } + // return null; + } + } + +// public class Reaction { // started off as a good idea but it sucks +// public static String getReaction(long reactionID) { +// Statement st = null; +// ResultSet rs = null; +// String query = "select * from reactions where id = '"+reactionID+"'"; +// try { +// st = connection.createStatement(); +// rs = st.executeQuery(query); +// if (rs.next()) { +// return rs.getString("val"); +// } else { +// // throw new SQLException(null, null, 33); // we need a real catcher here +// System.err +// .println("Failed to execute; errorCode=NO_ROW_FOUND; No row found; On action " + query); +// return null; +// } +// +// } catch (SQLException e) { +// sqlTranslate(query, e.getErrorCode()); +// // System.out.println("eeeeee"); +// return null; +// } finally { +// try { +// if (rs != null) +// rs.close(); +// } catch (Exception e) { +// } +// +// try { +// if (st != null) +// st.close(); +// } catch (Exception e) { +// } +// +// // try { if (conn != null) conn.close(); } catch (Exception e) {}; +// } +// // return null; +// } +// } + + } + +} diff --git a/src/pkg/deepCurse/nopalmo/global/Reactions.java b/src/pkg/deepCurse/nopalmo/global/Reactions.java new file mode 100644 index 0000000..857359b --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/global/Reactions.java @@ -0,0 +1,21 @@ +package pkg.deepCurse.nopalmo.global; + +import java.util.HashMap; + +public class Reactions { + + private static HashMap reactionMap = new HashMap(); + + public static void init() { + reactionMap.put("galaxyThumb", 801657838358495232L); + } + + public static String getReaction(String id) { + return ":"+id+":"+reactionMap.get(id); + } + + public static String getEmote(String id) { + return "<:"+id+":"+reactionMap.get(id)+">"; + } + +} diff --git a/src/pkg/deepCurse/nopalmo/global/Tools.java b/src/pkg/deepCurse/nopalmo/global/Tools.java new file mode 100644 index 0000000..977cce7 --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/global/Tools.java @@ -0,0 +1,7 @@ +package pkg.deepCurse.nopalmo.global; + +import net.dv8tion.jda.api.entities.Member; + +public class Tools { + +} diff --git a/src/pkg/deepCurse/nopalmo/listener/GuildMessageReceivedListener.java b/src/pkg/deepCurse/nopalmo/listener/GuildMessageReceivedListener.java new file mode 100644 index 0000000..db3ccd9 --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/listener/GuildMessageReceivedListener.java @@ -0,0 +1,63 @@ +package pkg.deepCurse.nopalmo.listener; + +import javax.annotation.Nonnull; + +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.events.ReadyEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import pkg.deepCurse.nopalmo.database.DatabaseTools; +import pkg.deepCurse.nopalmo.database.DatabaseTools.Tools.Global; +import pkg.deepCurse.nopalmo.global.Reactions; +import pkg.deepCurse.nopalmo.manager.GuildCommandManager; + +public class GuildMessageReceivedListener extends ListenerAdapter { + + public static GuildCommandManager m = new GuildCommandManager(); + + @Override + public void onReady(@Nonnull ReadyEvent event) { + System.out.println("GuildMessageReceivedListener is now ready\n" + event.getGuildAvailableCount() + "/" + + event.getGuildTotalCount() + " : " + event.getGuildUnavailableCount() + " <" + + event.getResponseNumber() + ">"); + } + + @Override + public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) { + Message message = event.getMessage(); + String messageRaw = message.getContentRaw(); + String[] prefixArray = new String[] { DatabaseTools.Tools.Guild.Prefix.getPrefix(event.getGuild().getIdLong()), + "<@!" + event.getJDA().getSelfUser().getIdLong() + ">" }; + + boolean shouldReturn = true; + for (String i : prefixArray) { + if (messageRaw.startsWith(i)) { + shouldReturn = false; + } + } + + if (messageRaw.contentEquals(Global.getPrefix() + Global.getPrefix()) + && DatabaseTools.Tools.Developers.canPowerOffBot(event.getAuthor().getIdLong())) { + message.addReaction(Reactions.getReaction("galaxyThumb")).queue(); + + System.out.println("Shutting down; id " + event.getAuthor().getIdLong() + " used"); + + // pause thread as last resort + + event.getJDA().shutdown(); + System.exit(0); + } + + // TODO add pre manager commands + + if (shouldReturn) { + return; + } + + if (!event.getAuthor().isBot()) { + m.startCommand(event); + } + + } + +} diff --git a/src/pkg/deepCurse/nopalmo/manager/GuildCommandManager.java b/src/pkg/deepCurse/nopalmo/manager/GuildCommandManager.java new file mode 100644 index 0000000..4b82f9f --- /dev/null +++ b/src/pkg/deepCurse/nopalmo/manager/GuildCommandManager.java @@ -0,0 +1,64 @@ +package pkg.deepCurse.nopalmo.manager; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.regex.Pattern; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import pkg.deepCurse.nopalmo.command.GuildCommand; +import pkg.deepCurse.nopalmo.command.guildCommand.Ping; +import pkg.deepCurse.nopalmo.database.DatabaseTools.Tools.Global; + +public class GuildCommandManager { + + private final Map guildCommandMap = new HashMap<>(); + Executor executor = null; + + public GuildCommandManager() { + init(); + executor = Executors.newSingleThreadExecutor(); + } + + public void init() { + addCommand(new Ping()); + } + + private void addCommand(GuildCommand c) { + if (!guildCommandMap.containsKey(c.getCommandName())) { + guildCommandMap.put(c.getCommandName(), c); + } else { + guildCommandMap.remove(c.getCommandName()); + guildCommandMap.put(c.getCommandName(), c); + } + } + + public Collection getguildCommandMap() { + return guildCommandMap.values(); + } + + public GuildCommand getCommand(String commandName) { + if (commandName != null) { + return guildCommandMap.get(commandName); + } + return null; + } + + public void startCommand(GuildMessageReceivedEvent guildMessage) { + + final String message = guildMessage.getMessage().getContentRaw(); + + final String[] split = message.replaceFirst("(?i)" + Pattern.quote(Global.getPrefix()), "").split("\\s+"); + final String command = split[0].toLowerCase(); + + executor.execute(() -> { + long commandStartTime = System.currentTimeMillis(); + + + }); + + } + +} diff --git a/src/pkg/deepCurse/simpleLoggingGarbage/core/Log.java b/src/pkg/deepCurse/simpleLoggingGarbage/core/Log.java index e64f46c..f7224d0 100644 --- a/src/pkg/deepCurse/simpleLoggingGarbage/core/Log.java +++ b/src/pkg/deepCurse/simpleLoggingGarbage/core/Log.java @@ -1,5 +1,7 @@ package pkg.deepCurse.simpleLoggingGarbage.core; +import javax.security.auth.login.LoginException; + /** * this class exists for the sole reason of im lazy, as far as i know, this is * really bad practice and i will replace it at some point, or at least upgrade @@ -22,4 +24,6 @@ public class Log { } } //@formatter:on + public static void crash(Exception e) { + } }