This commit is contained in:
Tyler Murphy 2022-09-01 00:15:36 -04:00
parent 5a50f81abb
commit 2bb0dcd0e2
14 changed files with 410 additions and 47 deletions

View file

@ -7,6 +7,7 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity; import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
@ -16,6 +17,7 @@ import net.tylermurphy.ken.command.Responder;
import net.tylermurphy.ken.database.Database; import net.tylermurphy.ken.database.Database;
import net.tylermurphy.ken.music.PlayerManager; import net.tylermurphy.ken.music.PlayerManager;
import net.tylermurphy.ken.util.ImageFetcher; import net.tylermurphy.ken.util.ImageFetcher;
import net.tylermurphy.ken.util.ModerationChecker;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -67,6 +69,7 @@ public class Ken {
log.error(e.getMessage()); log.error(e.getMessage());
throw new RuntimeException("Unable to connect with YouTube API"); throw new RuntimeException("Unable to connect with YouTube API");
} }
new ModerationChecker().start();
} }
public static Ken getInstance(){ public static Ken getInstance(){
@ -101,6 +104,10 @@ public class Ken {
public User getUserByName(String username, String discriminator) { return api.getUserByTag(username, discriminator); } public User getUserByName(String username, String discriminator) { return api.getUserByTag(username, discriminator); }
public Guild getGuildById(long id) { return api.getGuildById(id); }
public User getUserById(long id) { return api.getUserById(id); }
public EmbedBuilder getDefaultEmbed() { public EmbedBuilder getDefaultEmbed() {
EmbedBuilder builder = new EmbedBuilder(); EmbedBuilder builder = new EmbedBuilder();
builder.setColor(new Color( builder.setColor(new Color(

View file

@ -151,7 +151,6 @@ public class Responder extends ListenerAdapter {
.setTitle(":x: **Error**") .setTitle(":x: **Error**")
.setDescription(e.getCause() != null ? e.getCause().getMessage() : e.getMessage()); .setDescription(e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
event.getHook().sendMessageEmbeds(builder.build()).setEphemeral(true).queue(); event.getHook().sendMessageEmbeds(builder.build()).setEphemeral(true).queue();
e.printStackTrace();
} }
} }
@ -246,7 +245,7 @@ public class Responder extends ListenerAdapter {
.setColor(Color.RED) .setColor(Color.RED)
.setTitle(":x: **Error**") .setTitle(":x: **Error**")
.setDescription(e.getCause().getMessage()); .setDescription(e.getCause().getMessage());
event.getHook().editOriginalEmbeds(builder.build()).queue(); event.getHook().sendMessageEmbeds(builder.build()).queue();
} }
} }
@ -319,8 +318,16 @@ public class Responder extends ListenerAdapter {
boolean setValue = false; boolean setValue = false;
String value = Ken.getInstance().getDatabase().getGuildSettingsTable().getData(event.getGuild().getIdLong(), "closeServer"); String value = Ken.getInstance().getDatabase().getGuildSettingsTable().getData(event.getGuild().getIdLong(), "closeServer");
if(value != null) setValue = Boolean.parseBoolean(value); if(value != null) setValue = Boolean.parseBoolean(value);
if(!setValue){ if(setValue){
try {
event.getGuild().kick(user, "Server is currently closed").queue(); event.getGuild().kick(user, "Server is currently closed").queue();
user.openPrivateChannel().queue(privateChannel -> {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription("Kicked from "+event.getGuild().getName() + " because the server is currently closed");
privateChannel.sendMessageEmbeds(builder.build()).queue();
});
} catch (Exception ignored){}
} }
} }

View file

@ -44,12 +44,14 @@ public class Help {
), ),
Ken.getInstance().getDefaultEmbed() Ken.getInstance().getDefaultEmbed()
.setAuthor("Command List") .setAuthor("Command List")
.setTitle(":tools: **Admin Commands**") .setTitle(":tools: **Moderation Commands**")
.appendDescription("**/purge <amount>** Purges an amount of messages from a channel\n") .appendDescription("**/purge <amount>** Purges an amount of messages from a channel\n")
.appendDescription("**/kick <user> <reason>** Kick a user from the server\n") .appendDescription("**/kick <user> <reason>** Kick a user from the server\n")
.appendDescription("**/tempban <user> <days> <hours> <reason> <delete>** Temp ban a user from the server\n") .appendDescription("**/tempban <user> <time> <reason> <delete>** Temp ban a user from the server\n")
.appendDescription("**/ban <user> <reason> <delete>** Bans a user from the server\n") .appendDescription("**/ban <user> <reason> <delete>** Bans a user from the server\n")
.appendDescription("**/unban <username> <discriminator>** Unbans a user from the server\n") .appendDescription("**/unban <username> <discriminator>** Unbans a user from the server\n")
.appendDescription("**/mute <user> <time> <reason>** Mutes a user in the server\n")
.appendDescription("**/unmute <user> <reason>** Un mutes a user in the server\n")
.appendDescription("**/history <username> <discriminator>** Gets users moderation history\n") .appendDescription("**/history <username> <discriminator>** Gets users moderation history\n")
.appendDescription("**/setjoining <toggle>** Disable joining to the server\n"), .appendDescription("**/setjoining <toggle>** Disable joining to the server\n"),
Ken.getInstance().getDefaultEmbed() Ken.getInstance().getDefaultEmbed()

View file

@ -58,6 +58,16 @@ public class Ban {
String data = table.getData(guild.getIdLong(), target.getUser().getIdLong()); String data = table.getData(guild.getIdLong(), target.getUser().getIdLong());
JSONObject json = table.updateData(data); JSONObject json = table.updateData(data);
try {
guild.removeTimeout(target).queue();
} catch (Exception ignored){}
try {
guild.ban(target,purge ? 1 : 0,reason).queue();
} catch (Exception e){
return Response.error("Failed to ban user");
}
JSONObject status = json.getJSONObject("status"); JSONObject status = json.getJSONObject("status");
status.put("type", "ban"); status.put("type", "ban");
status.put("reason", reason); status.put("reason", reason);
@ -82,7 +92,6 @@ public class Ban {
.appendDescription("`Reason:` " + reason); .appendDescription("`Reason:` " + reason);
channel.sendMessageEmbeds(builder.build()).queue(); channel.sendMessageEmbeds(builder.build()).queue();
} }
guild.ban(target,purge ? 1 : 0,reason).queue();
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(String.format("Permanently banned %s for %s", target, reason)); .appendDescription(String.format("Permanently banned %s for %s", target, reason));
return Response.success(builder.build()); return Response.success(builder.build());

View file

@ -6,6 +6,7 @@ import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken; import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Response; import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.command.annotation.ButtonCallback;
import net.tylermurphy.ken.command.annotation.Command; import net.tylermurphy.ken.command.annotation.Command;
import net.tylermurphy.ken.command.annotation.Option; import net.tylermurphy.ken.command.annotation.Option;
import net.tylermurphy.ken.command.annotation.Requirement; import net.tylermurphy.ken.command.annotation.Requirement;
@ -40,19 +41,58 @@ public class History {
ModerationTable table = Ken.getInstance().getDatabase().getModerationTable(); ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
String data = table.getData(guild.getIdLong(), target); String data = table.getData(guild.getIdLong(), target);
JSONObject json = table.updateData(data); JSONObject json = table.updateData(data);
JSONArray history = json.getJSONArray("history"); JSONArray history = json.getJSONArray("history");
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() int page = 1;
.setAuthor("Moderation History"); int pages = (history.length()-1)/4+1;
return Response.success(generateEmbed(history, page, username, discriminator)).addSecondaryButton("history", "previous", "Previous").addSecondaryButton("history", "next", "Next");
}
@ButtonCallback(name="history")
public Response onButton(String id, Message message, Guild guild){
if(message == null || message.getEmbeds().size() < 1){
return Response.error("Message missing");
}
MessageEmbed temp = message.getEmbeds().get(0);
String username = temp.getDescription().substring(6).split("#")[0];
String discriminator = temp.getDescription().substring(6).split("#")[1];
long target = Ken.getInstance().getDatabase().getUserTable().getData(username, Integer.parseInt(discriminator));
if(target == 0L || temp.getFooter() == null) {
return Response.error("Either the user is invalid or the user has no cached history");
}
ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
String data = table.getData(guild.getIdLong(), target);
JSONObject json = table.updateData(data);
JSONArray history = json.getJSONArray("history");
int page = Integer.parseInt(temp.getFooter().getText().split("/")[0].substring(5));
int pages = (history.length()-1)/4+1;
if(id.equals("previous"))
page = page - 1 < 1 ? pages : page - 1;
else
page = page + 1 > pages ? 1 : page + 1;
MessageEmbed embed = generateEmbed(history, page, username, discriminator);
return Response.success(embed);
}
private MessageEmbed generateEmbed(JSONArray history, int page, String username, String discriminator){
int pages = (history.length()-1)/4+1;
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setAuthor("Moderation History")
.setDescription("User: "+username+"#"+discriminator)
.setFooter("Page "+page+"/"+pages);
if(history.length() < 1){ if(history.length() < 1){
builder.appendDescription("User has no moderation history"); builder.appendDescription("User has no moderation history");
} else { } else {
history.forEach(audit -> builder.addField(parseStatus((JSONObject) audit))); for(int i =(page-1)*4; i<Math.min((page-1)*4+4, history.length()); i++){
builder.addField(parseStatus(history.getJSONObject(history.length()-i-1)));
} }
}
return Response.success(builder.build()); return builder.build();
} }
private MessageEmbed.Field parseStatus(JSONObject status){ private MessageEmbed.Field parseStatus(JSONObject status){
@ -63,9 +103,11 @@ public class History {
case "temp-ban" -> "Temp banned"; case "temp-ban" -> "Temp banned";
case "unban" -> "Unbanned"; case "unban" -> "Unbanned";
case "kick" -> "Kicked"; case "kick" -> "Kicked";
case "mute" -> "Muted";
case "unmute" -> "Unmuted";
default -> throw new RuntimeException("Unknown value: " + type); default -> throw new RuntimeException("Unknown value: " + type);
}; };
SimpleDateFormat format = new SimpleDateFormat("MMM d, y ha zz"); SimpleDateFormat format = new SimpleDateFormat("MMM d, y h:ma zz");
String date = status.has("until") ? String date = status.has("until") ?
"Until: " + format.format(new Date(status.getLong("until"))) : "Until: " + format.format(new Date(status.getLong("until"))) :
"Date: " + format.format(new Date(status.getLong("date"))); "Date: " + format.format(new Date(status.getLong("date")));

View file

@ -56,6 +56,16 @@ public class Kick {
String data = table.getData(guild.getIdLong(), target.getUser().getIdLong()); String data = table.getData(guild.getIdLong(), target.getUser().getIdLong());
JSONObject json = table.updateData(data); JSONObject json = table.updateData(data);
try {
guild.removeTimeout(target).queue();
} catch (Exception ignored){}
try {
guild.kick(target).queue();
} catch (Exception e){
return Response.error("Failed to kick user");
}
JSONObject status = json.getJSONObject("status"); JSONObject status = json.getJSONObject("status");
status.put("type", "None"); status.put("type", "None");
status.put("reason", ""); status.put("reason", "");
@ -63,7 +73,7 @@ public class Kick {
json.put("status", status); json.put("status", status);
JSONArray history = json.getJSONArray("history"); JSONArray history = json.getJSONArray("history");
history.put(new JSONObject().put("type", "kick").put("reason", reason).put("date",new Date().getTime())); history.put(new JSONObject().put("type", "kick").put("reason", reason).put("date",new Date().getTime()).put("by", sender.getIdLong()));
json.put("history", history); json.put("history", history);
table.setData(guild.getIdLong(), target.getUser().getIdLong(), json.toString()); table.setData(guild.getIdLong(), target.getUser().getIdLong(), json.toString());
@ -73,14 +83,13 @@ public class Kick {
PrivateChannel channel = target.getUser().openPrivateChannel().complete(); PrivateChannel channel = target.getUser().openPrivateChannel().complete();
if(channel != null){ if(channel != null){
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.red) .setColor(new Color(250,63,63))
.setTitle("**Kicked**") .setTitle("**Kicked**")
.appendDescription("You have been kicked from "+guild.getName()+"\n") .appendDescription("You have been kicked from "+guild.getName()+"\n")
.appendDescription("`By:` " + sender.getEffectiveName()+"\n") .appendDescription("`By:` " + sender.getEffectiveName()+"\n")
.appendDescription("`Reason:` " + reason); .appendDescription("`Reason:` " + reason);
channel.sendMessageEmbeds(builder.build()).queue(); channel.sendMessageEmbeds(builder.build()).queue();
} }
guild.kick(target, reason).queue();
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(String.format("Kicked %s for %s", target, reason)); .appendDescription(String.format("Kicked %s for %s", target, reason));
return Response.success(builder.build()); return Response.success(builder.build());

View file

@ -1,4 +1,108 @@
package net.tylermurphy.ken.command.moderation; 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.sql.Time;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class Mute { public class Mute {
@Command(name="mute", description="Mute a user")
@Option(name="member", description="Member to mute", type= OptionType.USER, required=true)
@Option(name="time", description="Time for mute", type= OptionType.STRING, required=true)
@Option(name="reason", description="Reason for mute", type=OptionType.STRING, required=true)
@Requirement(Permission.MODERATE_MEMBERS)
public Response execute(Member sender, List<Object> args, Guild guild){
Member target = (Member) args.get(0);
String timeString = (String) args.get(1);
String reason = (String) args.get(2);
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");
}
if(target.isTimedOut()){
return Response.error("User is already muted");
}
long time = Checks.convertTime(timeString);
if(time == 0L){
return Response.error("Time to ban cannot be 0");
}
long diff = TimeUnit.DAYS.convert(Math.abs(new Date().getTime() - new Date(time).getTime()), TimeUnit.MILLISECONDS);
if(diff >= 28) {
return Response.error("Time cannot be or exceed 28 days");
}
SimpleDateFormat format = new SimpleDateFormat("MMM d, y h:ma zz");
String date = format.format(time);
ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
String data = table.getData(guild.getIdLong(), target.getUser().getIdLong());
JSONObject json = table.updateData(data);
try {
guild.timeoutUntil(target, new Date(time).toInstant()).queue();
} catch (Exception e){
return Response.error("Failed to mute user");
}
JSONObject status = json.getJSONObject("status");
status.put("type", "mute");
status.put("reason", reason);
status.put("until", time);
json.put("status", status);
JSONArray history = json.getJSONArray("history");
history.put(new JSONObject().put("type", "mute").put("reason", reason).put("date",new Date().getTime()).put("by", sender.getIdLong()));
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(new Color(250,140,140))
.setTitle("**Muted**")
.appendDescription("You have been muted from "+guild.getName()+"\n")
.appendDescription("`By:` " + sender.getEffectiveName()+"\n")
.appendDescription("`Reason:` " + reason+"\n")
.appendDescription("`Until:` " + date);
channel.sendMessageEmbeds(builder.build()).queue();
}
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(String.format("Muted %s for %s until %s", target, reason, date));
return Response.success(builder.build());
}
} }

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.command.main; package net.tylermurphy.ken.command.moderation;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;

View file

@ -20,7 +20,6 @@ import org.json.JSONObject;
import java.awt.*; import java.awt.*;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -28,17 +27,15 @@ public class TempBan {
@Command(name="tempban", description="Temp ban a user and delete all messages in past 24h") @Command(name="tempban", description="Temp ban a user and delete all messages in past 24h")
@Option(name="member", description="Member to temp-ban", type= OptionType.USER, required=true) @Option(name="member", description="Member to temp-ban", type= OptionType.USER, required=true)
@Option(name="days", description="Days for temp ban", type= OptionType.INTEGER, required=true) @Option(name="time", description="Time for temp ban", type= OptionType.STRING, 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="reason", description="Reason to temp-ban", type=OptionType.STRING, required=true)
@Option(name="delete_messages", 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) @Requirement(Permission.BAN_MEMBERS)
public Response execute(Member sender, List<Object> args, Guild guild){ public Response execute(Member sender, List<Object> args, Guild guild){
Member target = (Member) args.get(0); Member target = (Member) args.get(0);
int days = (int) args.get(1); String timeString = (String) args.get(1);
int hours = (int) args.get(2); String reason = (String) args.get(2);
String reason = (String) args.get(3); boolean purge = (boolean) args.get(3);
boolean purge = (boolean) args.get(4);
if(target == sender){ if(target == sender){
return Response.error("You are not allowed to do this to yourself"); return Response.error("You are not allowed to do this to yourself");
} }
@ -54,36 +51,35 @@ public class TempBan {
if(guild.getOwner() == target){ if(guild.getOwner() == target){
return Response.error("You cannot to this to the server owner"); return Response.error("You cannot to this to the server owner");
} }
if(hours < 0){
return Response.error("Hours must be 0 or greater");
}
if(days < 0){
return Response.error("Days must be 0 or greater");
}
if(days == 0 && hours == 0){
return Response.error("Time to ban cannot be 0");
}
try { try {
guild.retrieveBan(target).complete(); guild.retrieveBan(target).complete();
return Response.error("User is already banned from this server"); return Response.error("User is already banned from this server");
} catch (ErrorResponseException ignored) {} } catch (ErrorResponseException ignored) {}
long time = Checks.convertTime(timeString);
Calendar cal = Calendar.getInstance(); if(time == 0L){
cal.setTime(new Date()); return Response.error("Time to ban cannot be 0");
cal.add(Calendar.DATE, days); }
cal.add(Calendar.HOUR, hours); SimpleDateFormat format = new SimpleDateFormat("MMM d, y h:ma zz");
SimpleDateFormat format = new SimpleDateFormat("MMM d, y ha zz"); String date = format.format(time);
String date = format.format(cal.getTime());
ModerationTable table = Ken.getInstance().getDatabase().getModerationTable(); ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
String data = table.getData(guild.getIdLong(), target.getUser().getIdLong()); String data = table.getData(guild.getIdLong(), target.getUser().getIdLong());
JSONObject json = table.updateData(data); JSONObject json = table.updateData(data);
try {
guild.removeTimeout(target).queue();
} catch (Exception ignored){}
try {
guild.ban(target,purge ? 1 : 0,reason).queue();
} catch (Exception e){
return Response.error("Failed to temp ban user");
}
JSONObject status = json.getJSONObject("status"); JSONObject status = json.getJSONObject("status");
status.put("type", "temp-ban"); status.put("type", "temp-ban");
status.put("reason", reason); status.put("reason", reason);
status.put("until", cal.getTime().getTime()); status.put("until", time);
json.put("status", status); json.put("status", status);
JSONArray history = json.getJSONArray("history"); JSONArray history = json.getJSONArray("history");
@ -105,7 +101,6 @@ public class TempBan {
.appendDescription("`Until:` " + date); .appendDescription("`Until:` " + date);
channel.sendMessageEmbeds(builder.build()).queue(); channel.sendMessageEmbeds(builder.build()).queue();
} }
guild.ban(target,purge ? 1 : 0,reason).queue();
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(String.format("Temporarily banned %s for %s until %s", target, reason, date)); .appendDescription(String.format("Temporarily banned %s for %s until %s", target, reason, date));
return Response.success(builder.build()); return Response.success(builder.build());

View file

@ -62,6 +62,12 @@ public class UnBan {
String data = table.getData(guild.getIdLong(), target.getIdLong()); String data = table.getData(guild.getIdLong(), target.getIdLong());
JSONObject json = table.updateData(data); JSONObject json = table.updateData(data);
try {
guild.unban(target).queue();
} catch (Exception e){
return Response.error("Failed to unban user");
}
JSONObject status = json.getJSONObject("status"); JSONObject status = json.getJSONObject("status");
status.put("type", "None"); status.put("type", "None");
status.put("reason", ""); status.put("reason", "");
@ -79,14 +85,13 @@ public class UnBan {
PrivateChannel channel = target.openPrivateChannel().complete(); PrivateChannel channel = target.openPrivateChannel().complete();
if(channel != null){ if(channel != null){
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.green) .setColor(new Color(138,255,138))
.setTitle("**Unbanned**") .setTitle("**Unbanned**")
.appendDescription("You have been unbanned from "+guild.getName()+"\n") .appendDescription("You have been unbanned from "+guild.getName()+"\n")
.appendDescription("`By:` " + sender.getEffectiveName()+"\n") .appendDescription("`By:` " + sender.getEffectiveName()+"\n")
.appendDescription("`Reason:` " + reason); .appendDescription("`Reason:` " + reason);
channel.sendMessageEmbeds(builder.build()).queue(); channel.sendMessageEmbeds(builder.build()).queue();
} }
guild.unban(target).queue();
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(String.format("Unbanned %s for %s", target, reason)); .appendDescription(String.format("Unbanned %s for %s", target, reason));
return Response.success(builder.build()); return Response.success(builder.build());

View file

@ -1,4 +1,77 @@
package net.tylermurphy.ken.command.moderation; 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.awt.*;
import java.util.Date;
import java.util.List;
public class UnMute { public class UnMute {
@Command(name="unmute", description="Unmute a user")
@Option(name="member", description="Member to unmute", type= OptionType.USER, required=true)
@Option(name="reason", description="Reason for mute", type=OptionType.STRING, required=true)
@Requirement(Permission.MODERATE_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.getUser() == sender.getUser()){
return Response.error("You are not allowed to do this to yourself");
}
if(!target.isTimedOut()){
return Response.error("User is not muted");
}
ModerationTable table = Ken.getInstance().getDatabase().getModerationTable();
String data = table.getData(guild.getIdLong(), target.getIdLong());
JSONObject json = table.updateData(data);
try {
guild.removeTimeout(target).queue();
} catch (Exception e){
return Response.error("Failed to unmute user");
}
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", "unmute").put("reason", reason).put("date",new Date().getTime()).put("by", sender.getIdLong()));
json.put("history", history);
table.setData(guild.getIdLong(), target.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(new Color(138,255,138))
.setTitle("**Unmuted**")
.appendDescription("You have been un muted from "+guild.getName()+"\n")
.appendDescription("`By:` " + sender.getEffectiveName()+"\n")
.appendDescription("`Reason:` " + reason);
channel.sendMessageEmbeds(builder.build()).queue();
}
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(String.format("Unmutted %s for %s", target, reason));
return Response.success(builder.build());
}
} }

View file

@ -5,6 +5,8 @@ import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
import java.sql.*; import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
public class ModerationTable { public class ModerationTable {
@ -61,16 +63,18 @@ public class ModerationTable {
public void callOverdue(long date, Consumer<String[]> callback){ public void callOverdue(long date, Consumer<String[]> callback){
String sql = "SELECT * FROM moderation_data WHERE until < ? AND until > 0"; String sql = "SELECT * FROM moderation_data WHERE until < ? AND until > 0";
List<String[]> store = new ArrayList<>();
try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) { try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, date); statement.setLong(1, date);
ResultSet rs = statement.executeQuery(); ResultSet rs = statement.executeQuery();
while (rs.next()){ while (rs.next()){
String[] data = {String.valueOf(rs.getLong("guild_id")), String.valueOf(rs.getLong("user_id")), rs.getString("data")}; String[] data = {String.valueOf(rs.getLong("guild_id")), String.valueOf(rs.getLong("user_id")), rs.getString("data")};
callback.accept(data); store.add(data);
} }
} catch (SQLException e) { } catch (SQLException e) {
Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage()); Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
} }
store.forEach(callback);
} }
public JSONObject updateData(String data) { public JSONObject updateData(String data) {

View file

@ -3,6 +3,8 @@ package net.tylermurphy.ken.util;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.Role;
import java.util.Calendar;
import java.util.Date;
import java.util.List; import java.util.List;
public class Checks { public class Checks {
@ -23,6 +25,7 @@ public class Checks {
}).orElse(null); }).orElse(null);
} }
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public static boolean getRolePermission(Role first, Role second){ public static boolean getRolePermission(Role first, Role second){
if(first == null) return false; if(first == null) return false;
if(second == null) return true; if(second == null) return true;
@ -30,4 +33,43 @@ public class Checks {
return first.getPosition() > second.getPosition(); return first.getPosition() > second.getPosition();
} }
public static long convertTime(String pattern){
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
String[] data = pattern.toLowerCase().split("(?<!^)(?=\\D)|(?<=\\D)");
for(int i=0; i<data.length;){
if(i+1 == data.length) break;
if(!isInt(data[i])) { i++; continue; }
if(isInt(data[i+1])) { i++; continue; }
int n = Integer.parseInt(data[i]);
char c = data[i+1].charAt(0);
switch (c) {
case 'y' -> cal.add(Calendar.YEAR, n);
case 'm' -> cal.add(Calendar.MONTH, n);
case 'w' -> cal.add(Calendar.WEEK_OF_YEAR, n);
case 'd' -> cal.add(Calendar.DAY_OF_YEAR, n);
case 'h' -> cal.add(Calendar.HOUR, n);
}
i+=2;
}
Date newDate = cal.getTime();
if(newDate.getTime() == date.getTime()) {
return 0L;
} else {
return newDate.getTime();
}
}
public static boolean isInt(String number){
try {
Integer.parseInt(number);
return true;
} catch (NumberFormatException e){
return false;
}
}
} }

View file

@ -0,0 +1,64 @@
package net.tylermurphy.ken.util;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.PrivateChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.database.ModerationTable;
import org.json.JSONArray;
import org.json.JSONObject;
import java.awt.*;
import java.util.*;
import java.util.List;
public class ModerationChecker {
private final Timer timer = new Timer();
public void start(){
int minutes = 30;
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
Ken.getInstance().getDatabase().getModerationTable().callOverdue(new Date().getTime(), data -> {
long guildId = Long.parseLong(data[0]);
long userId = Long.parseLong(data[1]);
JSONObject json = new JSONObject(data[2]);
JSONObject status = json.getJSONObject("status");
String type = status.getString("type");
if(!type.equals("temp-ban")) return;
Guild guild = Ken.getInstance().getGuildById(guildId);
if(guild == null) return;
List<Guild.Ban> bans = guild.retrieveBanList().complete();
Optional<Guild.Ban> ban = bans.stream().filter(temp-> temp.getUser().getIdLong() == userId).findFirst();
if(ban.isEmpty()) return;
User user = ban.get().getUser();
try {
guild.unban(user).queue();
PrivateChannel channel = user.openPrivateChannel().complete();
if(channel != null){
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(new Color(138,255,138))
.setTitle("**Unbanned**")
.appendDescription("You have been unbanned from "+guild.getName()+"\n")
.appendDescription("`By:` Automated System\n")
.appendDescription("`Reason:` Ban period ended");
channel.sendMessageEmbeds(builder.build()).queue();
}
status.put("type", "None");
status.put("reason", "");
status.put("until", 0L);
JSONArray history = json.getJSONArray("history");
history.put(new JSONObject().put("type", "unban").put("reason", "Ban Period Ended").put("date",new Date().getTime()).put("by", guild.getSelfMember().getIdLong()));
json.put("history", history);
json.put("status", status);
Ken.getInstance().getDatabase().getModerationTable().setData(guildId, userId, json.toString());
} catch (ErrorResponseException ignored) {}
});
}
}, 0, minutes * 60 * 1000);
}
}