summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/net/tylermurphy/ken/Ken.java2
-rw-r--r--src/main/java/net/tylermurphy/ken/command/Responder.java19
-rw-r--r--src/main/java/net/tylermurphy/ken/command/moderation/Ban.java9
-rw-r--r--src/main/java/net/tylermurphy/ken/command/moderation/History.java72
-rw-r--r--src/main/java/net/tylermurphy/ken/command/moderation/Kick.java85
-rw-r--r--src/main/java/net/tylermurphy/ken/command/moderation/TempBan.java13
-rw-r--r--src/main/java/net/tylermurphy/ken/command/moderation/UnBan.java11
-rw-r--r--src/main/java/net/tylermurphy/ken/database/Database.java4
-rw-r--r--src/main/java/net/tylermurphy/ken/database/UserTable.java61
9 files changed, 260 insertions, 16 deletions
diff --git a/src/main/java/net/tylermurphy/ken/Ken.java b/src/main/java/net/tylermurphy/ken/Ken.java
index b9b6cba..a69ddc2 100644
--- a/src/main/java/net/tylermurphy/ken/Ken.java
+++ b/src/main/java/net/tylermurphy/ken/Ken.java
@@ -99,6 +99,8 @@ public class Ken {
public Role getRoleById(long id) { return api.getRoleById(id); }
+ public User getUserByName(String username, String discriminator) { return api.getUserByTag(username, discriminator); }
+
public EmbedBuilder getDefaultEmbed() {
EmbedBuilder builder = new EmbedBuilder();
builder.setColor(new Color(
diff --git a/src/main/java/net/tylermurphy/ken/command/Responder.java b/src/main/java/net/tylermurphy/ken/command/Responder.java
index bd4e0e1..45ebeab 100644
--- a/src/main/java/net/tylermurphy/ken/command/Responder.java
+++ b/src/main/java/net/tylermurphy/ken/command/Responder.java
@@ -17,6 +17,7 @@ import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.LayoutComponent;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.interactions.components.selections.SelectMenu;
+import net.dv8tion.jda.api.requests.restaction.WebhookMessageCreateAction;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import net.dv8tion.jda.api.utils.FileUpload;
import net.tylermurphy.ken.Ken;
@@ -144,9 +145,10 @@ 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;
- reply(response, event);
+ reply(response, event.getHook());
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
@@ -191,9 +193,9 @@ public class Responder extends ListenerAdapter {
// Invoke Method and Respond to User
try {
+ event.deferEdit().queue();
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
Response response = (Response) temp;
- event.deferEdit().queue();
edit(response, event.getHook());
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
@@ -239,9 +241,10 @@ 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;
- reply(response, event);
+ reply(response, event.getHook());
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
@@ -252,18 +255,18 @@ public class Responder extends ListenerAdapter {
}
- private void reply(Response response, IReplyCallback event){
+ private void reply(Response response, InteractionHook hook){
if(response.isError()) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setDescription(response.getMessage());
- event.replyEmbeds(builder.build()).setEphemeral(true).queue();
+ hook.sendMessageEmbeds(builder.build()).setEphemeral(true).queue();
} else {
- ReplyCallbackAction message;
+ WebhookMessageCreateAction<Message> message;
if(response.hasEmbed()) {
- message = event.replyEmbeds(response.getEmbeds());
+ message = hook.sendMessageEmbeds(response.getEmbeds());
} else {
- message = event.reply(response.getMessage());
+ message = hook.sendMessage(response.getMessage());
}
if(response.hasButtons()) message = message.addActionRow(response.getButtons());
if(response.hasSelectMenu()) message = message.addActionRow(response.getSelectMenu());
diff --git a/src/main/java/net/tylermurphy/ken/command/moderation/Ban.java b/src/main/java/net/tylermurphy/ken/command/moderation/Ban.java
index 95ee7e7..2cf7350 100644
--- a/src/main/java/net/tylermurphy/ken/command/moderation/Ban.java
+++ b/src/main/java/net/tylermurphy/ken/command/moderation/Ban.java
@@ -27,7 +27,7 @@ public class Ban {
@Command(name="ban", description="Perm ban a user and delete all messages in past 24h")
@Option(name="member", description="Member to ban", type=OptionType.USER, required=true)
@Option(name="reason", description="Reason to ban", type=OptionType.STRING, required=true)
- @Option(name="deletemessages", description="Delete messages from past 24h", type=OptionType.BOOLEAN, required=true)
+ @Option(name="delete_messages", description="Delete messages from past 24h", type=OptionType.BOOLEAN, required=true)
@Requirement(Permission.BAN_MEMBERS)
public Response execute(Member sender, List<Object> args, Guild guild){
Member target = (Member) args.get(0);
@@ -45,6 +45,9 @@ public class Ban {
if(!Checks.getRolePermission(self, low)){
return Response.error("I need a higher role than the target");
}
+ if(guild.getOwner() == target){
+ return Response.error("You cannot to this to the server owner");
+ }
try {
guild.retrieveBan(target).complete();
@@ -67,6 +70,8 @@ public class Ban {
table.setData(guild.getIdLong(), target.getUser().getIdLong(), json.toString());
+ Ken.getInstance().getDatabase().getUserTable().setData(target.getIdLong(), target.getUser().getName(), Integer.parseInt(target.getUser().getDiscriminator()));
+
PrivateChannel channel = target.getUser().openPrivateChannel().complete();
if(channel != null){
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
@@ -79,7 +84,7 @@ public class Ban {
}
guild.ban(target,purge ? 1 : 0,reason).queue();
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
- .appendDescription(String.format("Permanently banned %s for %s", target.getEffectiveName(), reason));
+ .appendDescription(String.format("Permanently banned %s for %s", target, reason));
return Response.success(builder.build());
}
diff --git a/src/main/java/net/tylermurphy/ken/command/moderation/History.java b/src/main/java/net/tylermurphy/ken/command/moderation/History.java
index cc598f9..f3408bd 100644
--- a/src/main/java/net/tylermurphy/ken/command/moderation/History.java
+++ b/src/main/java/net/tylermurphy/ken/command/moderation/History.java
@@ -1,4 +1,76 @@
package net.tylermurphy.ken.command.moderation;
+import net.dv8tion.jda.api.EmbedBuilder;
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.entities.*;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+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 net.tylermurphy.ken.database.ModerationTable;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
public class History {
+
+ @Command(name="history", description="Get moderation history of a user")
+ @Option(name="username", description="The username of the target not including after the #", type= OptionType.STRING, required=true)
+ @Option(name="discriminator", description="Last for digits after #", type=OptionType.INTEGER, required=true)
+ @Requirement(Permission.BAN_MEMBERS)
+ public Response execute(List<Object> args, Guild guild){
+ String username = (String) args.get(0);
+ String discriminator = String.valueOf(args.get(1));
+
+ if(discriminator.length() != 4) {
+ return Response.error("Invalid discriminator");
+ }
+
+ long target = Ken.getInstance().getDatabase().getUserTable().getData(username, (int)args.get(1));
+
+ if(target == 0L) {
+ return Response.error("Unable to find this user");
+ }
+
+ ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
+ String data = table.getData(guild.getIdLong(), target);
+ JSONObject json = table.updateData(data);
+
+ JSONObject status = json.getJSONObject("status");
+ JSONArray history = json.getJSONArray("history");
+
+ StringBuilder historyString = new StringBuilder();
+ history.forEach(audit -> historyString.append(parseStatus((JSONObject) audit)));
+
+ EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
+ .setAuthor("Moderation History")
+ .addField("Status", parseStatus(status), false)
+ .addField("History", historyString.toString(), false);
+
+ return Response.success(builder.build());
+ }
+
+ private String parseStatus(JSONObject status){
+ String type = status.getString("type");
+ String reason = "Reason: " + status.getString("reason");
+ if(type.equals("None")) return "User currently has no moderation actions against them";
+ String name = switch (type){
+ case "ban" -> "Banned";
+ case "temp-ban" -> "Temp banned";
+ case "unban" -> "Unbanned";
+ case "kick" -> "Kicked";
+ default -> throw new RuntimeException("Unknown value: " + type);
+ };
+ SimpleDateFormat format = new SimpleDateFormat("MMM d, y ha zz");
+ String date = status.has("until") ?
+ "Until: " + format.format(new Date(status.getLong("until"))) :
+ "Date: " + format.format(new Date(status.getLong("date")));
+ return "**" + name + "**\n" + reason + "\n" + date + "\n";
+ }
+
}
diff --git a/src/main/java/net/tylermurphy/ken/command/moderation/Kick.java b/src/main/java/net/tylermurphy/ken/command/moderation/Kick.java
index aad0de1..39a0a7f 100644
--- a/src/main/java/net/tylermurphy/ken/command/moderation/Kick.java
+++ b/src/main/java/net/tylermurphy/ken/command/moderation/Kick.java
@@ -1,4 +1,89 @@
package net.tylermurphy.ken.command.moderation;
+import net.dv8tion.jda.api.EmbedBuilder;
+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.PrivateChannel;
+import net.dv8tion.jda.api.entities.Role;
+import net.dv8tion.jda.api.exceptions.ErrorResponseException;
+import net.dv8tion.jda.api.interactions.commands.OptionType;
+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 net.tylermurphy.ken.database.ModerationTable;
+import net.tylermurphy.ken.util.Checks;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.awt.*;
+import java.util.Date;
+import java.util.List;
+
public class Kick {
+
+ @Command(name="kick", description="Kick a user")
+ @Option(name="member", description="Member to kick", type= OptionType.USER, required=true)
+ @Option(name="reason", description="Reason to kick", type=OptionType.STRING, required=true)
+ @Requirement(Permission.BAN_MEMBERS)
+ public Response execute(Member sender, List<Object> args, Guild guild){
+ Member target = (Member) args.get(0);
+ String reason = (String) args.get(1);
+ if(target == sender){
+ return Response.error("You are not allowed to do this to yourself");
+ }
+ Role low = Checks.getHighestRole(target);
+ Role high = Checks.getHighestRole(sender);
+ if(!Checks.getRolePermission(high, low)){
+ return Response.error("You need a higher role than the target");
+ }
+ Role self = Checks.getHighestRole(guild.getSelfMember());
+ if(!Checks.getRolePermission(self, low)){
+ return Response.error("I need a higher role than the target");
+ }
+ if(guild.getOwner() == target){
+ return Response.error("You cannot to this to the server owner");
+ }
+
+ try {
+ guild.retrieveBan(target).complete();
+ return Response.error("User is currently banned and cannot be kicked");
+ } catch (ErrorResponseException ignored) {}
+
+ ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
+ String data = table.getData(guild.getIdLong(), target.getUser().getIdLong());
+ JSONObject json = table.updateData(data);
+
+ JSONObject status = json.getJSONObject("status");
+ status.put("type", "None");
+ status.put("reason", "");
+ status.put("until", 0L);
+ json.put("status", status);
+
+ JSONArray history = json.getJSONArray("history");
+ history.put(new JSONObject().put("type", "kick").put("reason", reason).put("date",new Date().getTime()));
+ json.put("history", history);
+
+ table.setData(guild.getIdLong(), target.getUser().getIdLong(), json.toString());
+
+ Ken.getInstance().getDatabase().getUserTable().setData(target.getIdLong(), target.getUser().getName(), Integer.parseInt(target.getUser().getDiscriminator()));
+
+ PrivateChannel channel = target.getUser().openPrivateChannel().complete();
+ if(channel != null){
+ EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
+ .setColor(Color.red)
+ .setTitle("**Kicked**")
+ .appendDescription("You have been kicked from "+guild.getName()+"\n")
+ .appendDescription("`By:` " + sender.getEffectiveName()+"\n")
+ .appendDescription("`Reason:` " + reason);
+ channel.sendMessageEmbeds(builder.build()).queue();
+ }
+ guild.kick(target, reason).queue();
+ EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
+ .appendDescription(String.format("Kicked %s for %s", target, reason));
+ return Response.success(builder.build());
+ }
+
}
diff --git a/src/main/java/net/tylermurphy/ken/command/moderation/TempBan.java b/src/main/java/net/tylermurphy/ken/command/moderation/TempBan.java
index 62696ad..f56b9ac 100644
--- a/src/main/java/net/tylermurphy/ken/command/moderation/TempBan.java
+++ b/src/main/java/net/tylermurphy/ken/command/moderation/TempBan.java
@@ -31,7 +31,7 @@ public class TempBan {
@Option(name="days", description="Days for temp ban", type= OptionType.INTEGER, required=true)
@Option(name="hours", description="Hours for temp ban", type= OptionType.INTEGER, required=true)
@Option(name="reason", description="Reason to temp-ban", type=OptionType.STRING, required=true)
- @Option(name="deletemessages", description="Delete messages from past 24h", type=OptionType.BOOLEAN, required=true)
+ @Option(name="delete_messages", description="Delete messages from past 24h", type=OptionType.BOOLEAN, required=true)
@Requirement(Permission.BAN_MEMBERS)
public Response execute(Member sender, List<Object> args, Guild guild){
Member target = (Member) args.get(0);
@@ -51,6 +51,9 @@ public class TempBan {
if(!Checks.getRolePermission(self, low)){
return Response.error("I need a higher role than the target");
}
+ if(guild.getOwner() == target){
+ return Response.error("You cannot to this to the server owner");
+ }
if(hours < 0){
return Response.error("Hours must be 0 or greater");
}
@@ -70,7 +73,7 @@ public class TempBan {
cal.setTime(new Date());
cal.add(Calendar.DATE, days);
cal.add(Calendar.HOUR, hours);
- SimpleDateFormat format = new SimpleDateFormat("L d, y ha zz");
+ SimpleDateFormat format = new SimpleDateFormat("MMM d, y ha zz");
String date = format.format(cal.getTime());
ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
@@ -89,6 +92,8 @@ public class TempBan {
table.setData(guild.getIdLong(), target.getUser().getIdLong(), json.toString());
+ Ken.getInstance().getDatabase().getUserTable().setData(target.getIdLong(), target.getUser().getName(), Integer.parseInt(target.getUser().getDiscriminator()));
+
PrivateChannel channel = target.getUser().openPrivateChannel().complete();
if(channel != null){
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
@@ -96,13 +101,13 @@ public class TempBan {
.setTitle("**Temp Banned**")
.appendDescription("You have been temporarily banned from "+guild.getName()+"\n")
.appendDescription("`By:` " + sender.getEffectiveName()+"\n")
- .appendDescription("`Reason:` " + reason)
+ .appendDescription("`Reason:` " + reason+"\n")
.appendDescription("`Until:` " + date);
channel.sendMessageEmbeds(builder.build()).queue();
}
guild.ban(target,purge ? 1 : 0,reason).queue();
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
- .appendDescription(String.format("Temporarily banned %s for %s until %s", target.getEffectiveName(), reason, date));
+ .appendDescription(String.format("Temporarily banned %s for %s until %s", target, reason, date));
return Response.success(builder.build());
}
diff --git a/src/main/java/net/tylermurphy/ken/command/moderation/UnBan.java b/src/main/java/net/tylermurphy/ken/command/moderation/UnBan.java
index b259002..2e5831a 100644
--- a/src/main/java/net/tylermurphy/ken/command/moderation/UnBan.java
+++ b/src/main/java/net/tylermurphy/ken/command/moderation/UnBan.java
@@ -21,13 +21,18 @@ import java.util.List;
public class UnBan {
@Command(name="unban", description="Unban a user")
- @Option(name="username", description="Username", type= OptionType.STRING, required=true)
- @Option(name="discriminator", description="Discriminator", type=OptionType.INTEGER, required=true)
+ @Option(name="username", description="The username of the target not including after the #", type= OptionType.STRING, required=true)
+ @Option(name="discriminator", description="Last for digits after #", type=OptionType.INTEGER, required=true)
@Option(name="reason", description="Reason to unban", type=OptionType.STRING, required=true)
@Requirement(Permission.BAN_MEMBERS)
public Response execute(Member sender, Guild guild, List<Object> args){
String username = (String) args.get(0);
String discriminator = String.valueOf(args.get(1));
+
+ if(discriminator.length() != 4) {
+ return Response.error("Invalid discriminator");
+ }
+
String reason = (String) args.get(2);
User target = null;
@@ -69,6 +74,8 @@ public class UnBan {
table.setData(guild.getIdLong(), target.getIdLong(), json.toString());
+ Ken.getInstance().getDatabase().getUserTable().setData(target.getIdLong(), target.getName(), Integer.parseInt(target.getDiscriminator()));
+
PrivateChannel channel = target.openPrivateChannel().complete();
if(channel != null){
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
diff --git a/src/main/java/net/tylermurphy/ken/database/Database.java b/src/main/java/net/tylermurphy/ken/database/Database.java
index 2c46c68..7e9c183 100644
--- a/src/main/java/net/tylermurphy/ken/database/Database.java
+++ b/src/main/java/net/tylermurphy/ken/database/Database.java
@@ -14,6 +14,7 @@ public class Database {
private final SelfRoleTable selfRoleTable;
private final EconomyTable economyTable;
private final ModerationTable moderationTable;
+ private final UserTable userTable;
public Database(){
if(Ken.getInstance().getConfig().getBoolean("database.sqlite")) {
@@ -24,6 +25,7 @@ public class Database {
selfRoleTable = new SelfRoleTable(this);
economyTable = new EconomyTable(this);
moderationTable = new ModerationTable(this);
+ userTable = new UserTable(this);
}
public SelfRoleTable getSelfRoleData(){
@@ -36,6 +38,8 @@ public class Database {
public ModerationTable getModerationTable() { return moderationTable; }
+ public UserTable getUserTable() { return userTable; }
+
protected Connection connect() throws SQLException {
return connection.connect();
}
diff --git a/src/main/java/net/tylermurphy/ken/database/UserTable.java b/src/main/java/net/tylermurphy/ken/database/UserTable.java
new file mode 100644
index 0000000..0125eac
--- /dev/null
+++ b/src/main/java/net/tylermurphy/ken/database/UserTable.java
@@ -0,0 +1,61 @@
+package net.tylermurphy.ken.database;
+
+import net.dv8tion.jda.api.entities.User;
+import net.tylermurphy.ken.Ken;
+import org.json.JSONObject;
+
+import java.sql.*;
+
+public class UserTable {
+
+ private final Database database;
+
+ public UserTable(Database database){
+
+ String sql = """
+ CREATE TABLE IF NOT EXISTS user_data (
+ user_id BIGINT NOT NULL,
+ username VARCHAR(64) NOT NULL,
+ discriminator INT NOT NULL,
+ PRIMARY KEY (user_id)
+ );""";
+
+ 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 long getData(String username, int discriminator){
+ User cache = Ken.getInstance().getUserByName(username, String.valueOf(discriminator));
+ if(cache != null) return cache.getIdLong();
+ String sql = "SELECT * FROM user_data WHERE username=? AND discriminator=?";
+ try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setString(1, username);
+ statement.setInt(2, discriminator);
+ ResultSet rs = statement.executeQuery();
+ if(rs.next()) return rs.getLong("user_id");
+ else return 0L;
+ } catch (SQLException e) {
+ Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
+ return 0L;
+ }
+ }
+
+ public boolean setData(long userId, String username, int discriminator) {
+ String sql = "INSERT OR REPLACE INTO user_data (user_id, username, discriminator) VALUES(?,?,?)";
+ try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
+ statement.setLong(1, userId);
+ statement.setString(2, username);
+ statement.setInt(3, discriminator);
+ return statement.executeUpdate() != 0;
+ } catch (SQLException e) {
+ Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
+ return false;
+ }
+ }
+
+}