diff --git a/src/main/java/net/tylermurphy/ken/command/Responder.java b/src/main/java/net/tylermurphy/ken/command/Responder.java index d7bdc15..343b06a 100644 --- a/src/main/java/net/tylermurphy/ken/command/Responder.java +++ b/src/main/java/net/tylermurphy/ken/command/Responder.java @@ -31,6 +31,7 @@ import net.tylermurphy.ken.command.music.*; import net.tylermurphy.ken.command.music.Queue; import net.tylermurphy.ken.command.nsfw.*; import net.tylermurphy.ken.command.selfrole.*; +import net.tylermurphy.ken.command.social.Sticker; import java.awt.*; import java.lang.reflect.Method; @@ -94,6 +95,7 @@ public class Responder extends ListenerAdapter { new UnMute(), new SetJoining(), new History(), + new Sticker() }; Arrays.stream(objects).forEach(register::register); } @@ -142,9 +144,9 @@ public class Responder extends ListenerAdapter { // Invoke Method and Respond to User try { - event.deferReply().queue(); Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); Response response = (Response)temp; + event.deferReply(response.isError()).queue(); reply(response, event.getHook()); } catch (Exception e) { EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() @@ -238,9 +240,9 @@ public class Responder extends ListenerAdapter { // Invoke Method and Respond to User try { - event.deferReply().queue(); Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); Response response = (Response) temp; + event.deferReply(response.isError()).queue(); reply(response, event.getHook()); } catch (Exception e) { EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() @@ -308,6 +310,7 @@ public class Responder extends ListenerAdapter { case CHANNEL -> args.add(option.getAsChannel()); case ROLE -> args.add(option.getAsRole()); case MENTIONABLE -> args.add(option.getAsMentionable()); + case ATTACHMENT -> args.add(option.getAsAttachment()); default -> { } } diff --git a/src/main/java/net/tylermurphy/ken/command/main/Help.java b/src/main/java/net/tylermurphy/ken/command/main/Help.java index 3746ffc..80daa3c 100644 --- a/src/main/java/net/tylermurphy/ken/command/main/Help.java +++ b/src/main/java/net/tylermurphy/ken/command/main/Help.java @@ -89,6 +89,13 @@ public class Help { .appendDescription("**/money** Check how much moneys you have\n") .appendDescription("**/roulette ** Gamble on roulette\n") .appendDescription("**/slots ** Gamble on slots\n"), + Ken.getInstance().getDefaultEmbed() + .setAuthor("Command List") + .setTitle(":desktop: **Social Commands**") + .appendDescription("**/sticker ** Post a sticker\n") + .appendDescription("**/addsticker ** Add a sticker\n") + .appendDescription("**/deletesticker ** Delete a sticker\n") + .appendDescription("**/liststickers** List all server stickers\n"), Ken.getInstance().getDefaultEmbed() .setAuthor("Command List") .setTitle(":man_detective: **Self Roles**") diff --git a/src/main/java/net/tylermurphy/ken/command/social/Sticker.java b/src/main/java/net/tylermurphy/ken/command/social/Sticker.java new file mode 100644 index 0000000..9fc5c52 --- /dev/null +++ b/src/main/java/net/tylermurphy/ken/command/social/Sticker.java @@ -0,0 +1,88 @@ +package net.tylermurphy.ken.command.social; + +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.internal.utils.tuple.Pair; +import net.tylermurphy.ken.Ken; +import net.tylermurphy.ken.command.Response; +import net.tylermurphy.ken.command.annotation.Command; +import net.tylermurphy.ken.command.annotation.Option; +import net.tylermurphy.ken.command.annotation.Requirement; + +import java.util.List; + +public class Sticker { + + @Command(name="sticker", description="Post a sticker set in a server") + @Option(name="name", description="Name of the sticker", type=OptionType.STRING, required=true) + public Response sticker(Member sender, Guild guild, List args) { + String name = (String) args.get(0); + Pair imageData = Ken.getInstance().getDatabase().getStickerTable().getImage(guild.getIdLong(), name.toLowerCase()); + if(imageData == null) { + return Response.error(String.format("Sticker %s does not exists on this server", name)); + } + byte[] image = imageData.getLeft(); + return Response.success(String.format("%s posted sticker %s", sender.getEffectiveName(), name)).setFile(image, imageData.getRight()); + } + + @Command(name="addsticker", description="Add a sticker to the server") + @Option(name="name", description="Name of the sticker", type=OptionType.STRING, required=true) + @Option(name="sticker", description="Image or gif file", type=OptionType.ATTACHMENT, required=true) + @Requirement(Permission.MANAGE_SERVER) + public Response addSticker(GuildMessageChannel channel, Guild guild, List args) { + String name = (String) args.get(0); + Message.Attachment sticker = (Message.Attachment) args.get(1); + if(!sticker.isImage()) { + return Response.error("Attachment must be a valid discord image"); + } + if(sticker.getSize() > 5 * 1024 * 1024) { + return Response.error("Attachment must be 5MB or less"); + } + sticker.getProxy().download().whenComplete((s, error) -> { + if(error != null) { + channel.sendMessage(":x: Failed to retrieve uploaded image").queue(); + return; + } + boolean result = Ken.getInstance().getDatabase().getStickerTable().setImage(guild.getIdLong(), name.toLowerCase(), s, sticker.getFileName()); + if(result) { + channel.sendMessage(String.format(":white_check_mark: Successfully uploaded image with name " + name)).queue(); + } else { + channel.sendMessage(":x: Failed to upload image to database").queue(); + } + }); + return Response.success(":wrench: Attempting to upload image"); + } + + @Command(name="deletesticker", description="Delete a sticker set in a server") + @Option(name="name", description="Name of the sticker", type=OptionType.STRING, required=true) + @Requirement(Permission.MANAGE_SERVER) + public Response deleteSticker(Member sender, Guild guild, List args) { + String name = (String) args.get(0); + boolean result = Ken.getInstance().getDatabase().getStickerTable().deleteImage(guild.getIdLong(), name.toLowerCase()); + if(result) { + return Response.success(String.format(":white_check_mark: Sticker %s has been deleted", name)); + } else { + return Response.error(String.format("Sticker %s does not exists on this server", name)); + } + } + + @Command(name="liststickers", description="List stickers set in this server") + public Response listStickers(Guild guild) { + List names = Ken.getInstance().getDatabase().getStickerTable().getImages(guild.getIdLong()); + if(names.size() > 1) { + String response = "The stickers in this server are: ``"; + for(String name : names) { + response = response + name +", "; + } + response = response.substring(0, response.length()-2) + "``"; + return Response.success(response); + } else { + return Response.error("There are no stickers in this server"); + } + } + +} diff --git a/src/main/java/net/tylermurphy/ken/database/Database.java b/src/main/java/net/tylermurphy/ken/database/Database.java index 77a7a51..88833a8 100644 --- a/src/main/java/net/tylermurphy/ken/database/Database.java +++ b/src/main/java/net/tylermurphy/ken/database/Database.java @@ -16,6 +16,7 @@ public class Database { private final ModerationTable moderationTable; private final UserTable userTable; private final GuildSettingsTable guildSettingsTable; + private final StickerTable stickerTable; public Database(){ if(Ken.getInstance().getConfig().getBoolean("database.sqlite")) { @@ -28,6 +29,7 @@ public class Database { moderationTable = new ModerationTable(this); userTable = new UserTable(this); guildSettingsTable = new GuildSettingsTable(this); + stickerTable = new StickerTable(this); } public SelfRoleTable getSelfRoleData(){ @@ -44,6 +46,8 @@ public class Database { public GuildSettingsTable getGuildSettingsTable() { return guildSettingsTable; } + public StickerTable getStickerTable() { return stickerTable; } + protected Connection connect() throws SQLException { return connection.connect(); } diff --git a/src/main/java/net/tylermurphy/ken/database/StickerTable.java b/src/main/java/net/tylermurphy/ken/database/StickerTable.java new file mode 100644 index 0000000..bc46cfc --- /dev/null +++ b/src/main/java/net/tylermurphy/ken/database/StickerTable.java @@ -0,0 +1,95 @@ +package net.tylermurphy.ken.database; + +import net.dv8tion.jda.internal.utils.tuple.Pair; +import net.tylermurphy.ken.Ken; + +import java.io.IOException; +import java.io.InputStream; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +public class StickerTable { + + private final Database database; + + public StickerTable(Database database){ + + String sql = """ + CREATE TABLE IF NOT EXISTS sticker_data ( + guild_id BIGINT NOT NULL, + name VARCHAR(16) NOT NULL, + image BLOB NOT NULL, + filename VARCHAR(50) NOT NULL, + PRIMARY KEY (guild_id,name) + );"""; + + try(Connection connection = database.connect(); Statement statement = connection.createStatement()) { + statement.executeUpdate(sql); + } catch (SQLException e) { + Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage()); + } + + this.database = database; + } + + public Pair getImage(long guildId, String name){ + String sql = "SELECT * FROM sticker_data WHERE guild_id=? AND name=?"; + try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, guildId); + statement.setString(2, name); + ResultSet rs = statement.executeQuery(); + if(rs.next()) { + return Pair.of(rs.getBytes("image"), rs.getString("filename")); + } else { + return null; + } + } catch (SQLException e) { + Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage()); + return null; + } + } + + public List getImages(long guildId){ + String sql = "SELECT * FROM sticker_data WHERE guild_id=?"; + try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, guildId); + ResultSet rs = statement.executeQuery(); + List names = new ArrayList<>(); + while(rs.next()) { + names.add(rs.getString("name")); + } + return names; + } catch (SQLException e) { + Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage()); + return null; + } + } + + public boolean setImage(long guildId, String name, InputStream image, String filename) { + String sql = "REPLACE INTO sticker_data (guild_id, name, image, filename) VALUES(?,?,?,?)"; + try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, guildId); + statement.setString(2, name); + statement.setBytes(3, image.readAllBytes()); + statement.setString(4, filename); + return statement.executeUpdate() != 0; + } catch (SQLException | IOException e) { + e.printStackTrace(); + Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage()); + return false; + } + } + + public boolean deleteImage(long guildId, String name) { + String sql = "DELETE FROM sticker_data WHERE guild_id=? AND name=?"; + try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { + statement.setLong(1, guildId); + statement.setString(2, name); + return statement.executeUpdate() != 0; + } catch (SQLException e) { + Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage()); + return false; + } + } +}