This commit is contained in:
Tyler Murphy 2022-08-24 15:59:11 -04:00
parent 04d5376fa3
commit 14e9087dfa
45 changed files with 557 additions and 383 deletions

View file

@ -7,12 +7,10 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.VoiceChannel;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.tylermurphy.ken.command.Responder;
import net.tylermurphy.ken.event.Responder;
import net.tylermurphy.ken.database.Database;
import net.tylermurphy.ken.music.PlayerManager;
import org.jetbrains.annotations.NotNull;
@ -22,7 +20,6 @@ import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
public class Ken {
@ -52,12 +49,7 @@ public class Ken {
throw new RuntimeException("Unable to Initialize JDA");
}
this.responder = new Responder(api);
try{
responder.registerCommands();
} catch (InvocationTargetException | InstantiationException | IllegalAccessException | NoSuchMethodException e) {
log.error(e.getMessage());
throw new RuntimeException("Unable to register commands");
}
this.responder.registerCommands();
this.addEventListener(responder);
this.playerManager = new PlayerManager();
try {
@ -108,14 +100,6 @@ public class Ken {
return builder;
}
public TextChannel getTextChannel(long id) {
return api.getTextChannelById(id);
}
public VoiceChannel getVoiceChannel(long id) {
return api.getVoiceChannelById(id);
}
public void addEventListener(ListenerAdapter listener){
api.addEventListener(listener);
}

View file

@ -1,49 +0,0 @@
package net.tylermurphy.ken.command;
import net.dv8tion.jda.api.Permission;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Container {
private final Method method;
private final Object handle;
private Method buttonCallback;
private Permission permission;
public Container(Method method) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
this.method = method;
this.handle = method.getDeclaringClass().getConstructor().newInstance();
}
public Container setButtonCallback(Method method){
this.buttonCallback = method;
return this;
}
public Container setPermission(Permission permission){
this.permission = permission;
return this;
}
public Method getMethod(){
return method;
}
public Object getHandle(){
return handle;
}
public Method getButtonCallback(){
return buttonCallback;
}
public Permission getPermission(){
return permission;
}
}

View file

@ -0,0 +1,96 @@
package net.tylermurphy.ken.command;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.tylermurphy.ken.event.annotation.*;
import java.lang.reflect.Method;
import java.util.*;
public class Register {
private final Map<String, Object> HANDLES;
private final Map<String, Method> COMMAND_CALLBACKS;
private final Map<String, Method> BUTTON_CALLBACKS;
private final Map<String, Permission> PERMISSIONS;
private final JDA api;
public Register(JDA api){
HANDLES = new HashMap<>();
COMMAND_CALLBACKS = new HashMap<>();
BUTTON_CALLBACKS = new HashMap<>();
PERMISSIONS = new HashMap<>();
this.api = api;
}
public void register(Object handle) {
if(HANDLES.containsKey(handle.getClass().getName())) return;
List<Method> commands = Arrays.stream(handle.getClass().getMethods()).filter(method -> method.isAnnotationPresent(Command.class)).toList();
List<Method> buttons = Arrays.stream(handle.getClass().getMethods()).filter(method -> method.isAnnotationPresent(ButtonCallback.class)).toList();
if(commands.isEmpty() && buttons.isEmpty()) return;
HANDLES.put(handle.getClass().getName(), handle);
commands.forEach(this::registerCommand);
buttons.forEach(this::registerButton);
}
private void registerCommand(Method method){
Command command = method.getAnnotation(Command.class);
if(COMMAND_CALLBACKS.containsKey(command.name())) return;
COMMAND_CALLBACKS.put(command.name(), method);
if (method.isAnnotationPresent(Requirement.class)){
PERMISSIONS.put(command.name(), method.getAnnotation(Requirement.class).value());
}
SlashCommandData data = Commands.slash(command.name(), command.description());
if(method.isAnnotationPresent(Options.class)) {
Option[] options = method.getAnnotation(Options.class).value();
for(Option option : options){
data = data.addOption(option.type(), option.name(), option.description(), option.required());
}
} else if (method.isAnnotationPresent(Option.class)) {
Option option = method.getAnnotation(Option.class);
data = data.addOption(option.type(), option.name(), option.description(), option.required());
}
if(method.isAnnotationPresent(Selections.class)){
Selection[] selections = method.getAnnotation(Selections.class).value();
for(Selection selection : selections){
OptionData optionData = new OptionData(selection.type(), selection.name(), selection.description(), selection.required());
Arrays.stream(selection.choices()).forEach(choice -> optionData.addChoice(choice, choice.toLowerCase(Locale.ROOT)));
data.addOptions(optionData);
}
} else if(method.isAnnotationPresent(Selection.class)){
Selection selection = method.getAnnotation(Selection.class);
OptionData optionData = new OptionData(selection.type(), selection.name(), selection.description(), selection.required());
Arrays.stream(selection.choices()).forEach(choice -> optionData.addChoice(choice, choice.toLowerCase(Locale.ROOT)));
data.addOptions(optionData);
}
api.upsertCommand(data).queue();
}
private void registerButton(Method method){
ButtonCallback callback = method.getAnnotation(ButtonCallback.class);
if(BUTTON_CALLBACKS.containsKey(callback.name())) return;
BUTTON_CALLBACKS.put(callback.name(), method);
}
public Method getCommand(String name){
return COMMAND_CALLBACKS.get(name);
}
public Method getButtonCallback(String name){
return BUTTON_CALLBACKS.get(name);
}
public Permission getPermission(String name){
return PERMISSIONS.get(name);
}
public Object getHandle(String name){
return HANDLES.get(name);
}
}

View file

@ -1,245 +0,0 @@
package net.tylermurphy.ken.command;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildMessageChannel;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
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;
import net.tylermurphy.ken.util.*;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import java.awt.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.List;
public class Responder extends ListenerAdapter {
private final Map<String, Container> register;
private final JDA api;
public Responder(JDA api) {
this.register = new HashMap<>();
this.api = api;
}
public void registerCommands() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
// Reset register
register.clear();
// Get all Methods that use the @Command annotation
for (Method method : new Reflections("net.tylermurphy.ken.command", new MethodAnnotationsScanner()).getMethodsAnnotatedWith(Command.class)) {
if(method.getReturnType() != Response.class) continue;
// Register Main Command Information If Not Already Registered;
Command command = method.getAnnotation(Command.class);
if (register.containsKey(command.name())) continue;
// Create Command Container
Container container = new Container(method);
// Check For Permissions
if (method.isAnnotationPresent(Requirement.class))
container.setPermission(method.getAnnotation(Requirement.class).value());
// Add Command To Register
register.put(command.name(), container);
// Create Slash Command Data
SlashCommandData data = Commands.slash(command.name(), command.description());
// Add Options to Slash Command Data if @Option is used
if(method.isAnnotationPresent(Options.class)) {
Option[] options = method.getAnnotation(Options.class).value();
for(Option option : options){
data = data.addOption(option.type(), option.name(), option.description(), option.required());
}
} else if (method.isAnnotationPresent(Option.class)) {
Option option = method.getAnnotation(Option.class);
data = data.addOption(option.type(), option.name(), option.description(), option.required());
}
if(method.isAnnotationPresent(Selections.class)){
Selection[] selections = method.getAnnotation(Selections.class).value();
for(Selection selection : selections){
OptionData optionData = new OptionData(selection.type(), selection.name(), selection.description(), selection.required());
Arrays.stream(selection.choices()).forEach(choice -> optionData.addChoice(choice, choice.toLowerCase(Locale.ROOT)));
data.addOptions(optionData);
}
} else if(method.isAnnotationPresent(Selection.class)){
Selection selection = method.getAnnotation(Selection.class);
OptionData optionData = new OptionData(selection.type(), selection.name(), selection.description(), selection.required());
Arrays.stream(selection.choices()).forEach(choice -> optionData.addChoice(choice, choice.toLowerCase(Locale.ROOT)));
data.addOptions(optionData);
}
api.upsertCommand(data).queue();
}
// Get all Methods that use the @ButtonCallback annotation
for (Method method : new Reflections("net.tylermurphy.ken.command", new MethodAnnotationsScanner()).getMethodsAnnotatedWith(ButtonCallback.class)) {
if(method.getReturnType() != Response.class) continue;
ButtonCallback callback = method.getAnnotation(ButtonCallback.class);
if(!register.containsKey(callback.name())) continue;
Container container = register.get(callback.name());
container.setButtonCallback(method);
register.put(callback.name(), container);
}
}
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
// Make sure the Bot can Talk
if(!event.getChannel().canTalk()) return;
// Bots are not allowed to use commands
if (event.getMember() == null || event.getUser().isBot()) return;
// Get Command Information From Invoke
final String invoke = event.getName().toLowerCase(Locale.ROOT);
if(!register.containsKey(invoke)) return;
Container container = register.get(invoke);
Method method = container.getMethod();
// Check Permissions
if(!event.getMember().hasPermission(container.getPermission())) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(":x: **Invalid Permissions**\n")
.appendDescription("You require the "+ container.getPermission().toString()+" permission to use this command.");
event.getHook().sendMessageEmbeds(builder.build()).queue();
return;
}
// Get slash command options if there are any
List<Object> args = new ArrayList<>();
event.getOptions().forEach(option -> {
switch (option.getType()){
case STRING: args.add(option.getAsString()); break;
case INTEGER: args.add(option.getAsInt()); break;
case BOOLEAN: args.add(option.getAsBoolean()); break;
case USER: args.add(option.getAsMember()); break;
case CHANNEL: args.add(option.getAsChannel()); break;
case ROLE: args.add(option.getAsRole()); break;
case MENTIONABLE: args.add(option.getAsMentionable()); break;
default: break;
}
});
// Get parameters to send to Method
Object[] parameters = new Object[method.getParameterTypes().length];
Class<?>[] types = method.getParameterTypes();
for(int i = 0; i < types.length; i++){
if(types[i] == Member.class){
parameters[i] = event.getMember();
} else if(types[i] == GuildMessageChannel.class){
parameters[i] = event.getGuildChannel();
} else if(types[i] == Guild.class) {
parameters[i] = event.getGuild();
} else if(types[i] == List.class) {
parameters[i] = args;
} else {
parameters[i] = null;
}
}
// Invoke Method and Respond to User
try {
Object temp = method.invoke(container.getHandle(), parameters);
Response response = (Response)temp;
if(response.error()) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setDescription(response.getMessage());
event.replyEmbeds(builder.build()).setEphemeral(true).queue();
} else {
ReplyCallbackAction message;
if(response.hasEmbed()) {
message = event.replyEmbeds(response.getEmbeds());
} else {
message = event.reply(response.getMessage());
}
if(response.hasButtons()) message = message.addActionRow(response.getButtons());
if(response.hasFile()) message = message.addFiles(FileUpload.fromData(response.getFile()));
message.queue();
}
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(e.getCause().getMessage());
event.replyEmbeds(builder.build()).setEphemeral(true).queue();
}
}
public void onButtonInteraction(ButtonInteractionEvent event) {
// Make sure the Bot can Talk
if(!event.getChannel().canTalk()) return;
// Bots are not allowed to use commands
if (event.getMember() == null || event.getUser().isBot()) return;
// Get Command Information From Invoke
final String invoke = event.getComponentId().toLowerCase(Locale.ROOT).split("_")[0];
if(!register.containsKey(invoke)) return;
Container container = register.get(invoke);
Method method = container.getButtonCallback();
// Defer Reply
event.deferEdit().queue();
// Get parameters to send to Method
Object[] parameters = new Object[method.getParameterTypes().length];
Class<?>[] types = method.getParameterTypes();
for(int i = 0; i < types.length; i++){
if(types[i] == Member.class){
parameters[i] = event.getMember();
} else if(types[i] == GuildMessageChannel.class){
parameters[i] = event.getGuildChannel();
} else if(types[i] == Guild.class) {
parameters[i] = event.getGuild();
} else if(types[i] == Button.class) {
parameters[i] = event.getButton();
} else if(types[i] == Message.class) {
parameters[i] = event.getMessage();
} else if(types[i] == String.class) {
parameters[i] = event.getComponentId().substring(invoke.length()+1);
} else {
parameters[i] = null;
}
}
// Invoke Method and Respond to User
try {
Object temp = method.invoke(container.getHandle(), parameters);
Response response = (Response) temp;
if(response.error()) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(response.getMessage());
event.getHook().sendMessageEmbeds(builder.build()).queue();
} else {
if(response.hasEmbed()) {
event.getHook().editOriginalEmbeds(response.getEmbeds()).queue();
} else {
event.getHook().editOriginal(response.getMessage()).queue();
}
}
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(e.getCause().getMessage());
event.getHook().editOriginalEmbeds(builder.build()).queue();
}
}
}

View file

@ -40,6 +40,8 @@ public class Response {
return new Response("success", "", null, embed);
}
public static Response delete() { return new Response("delete", "", null, null); }
public Response addPrimaryButton(String callback, String id, String label){
buttons.add(Button.primary(callback + "_" + id ,label));
return this;
@ -64,6 +66,8 @@ public class Response {
return type.equals("error");
}
public boolean remove() { return type.equals("delete"); }
public boolean hasEmbed() { return embeds != null; }
public boolean hasFile() { return file != null; }

View file

@ -4,7 +4,7 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
public class Coinflip {

View file

@ -4,8 +4,8 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.command.Response;
import java.util.List;

View file

@ -2,8 +2,8 @@ package net.tylermurphy.ken.command.fun;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.image.GifFactory;

View file

@ -0,0 +1,44 @@
package net.tylermurphy.ken.command.main;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.event.annotation.Requirement;
import org.json.JSONArray;
import java.util.List;
public class AddRole {
@Command(name="addrole", description="Add a role to the /rolls command on a certain page")
@Option(name="role", description="Role to add", type=OptionType.ROLE, required=true)
@Option(name="page#", description="Page to add it on", type=OptionType.INTEGER, required=true)
@Requirement(Permission.MANAGE_SERVER)
public Response execute(Guild guild, List<Object> args) {
int page = (int)args.get(1);
Role role = (Role)args.get(0);
String data = Ken.getInstance().getDatabase().getSelfRoleData().getData(guild.getIdLong(), page);
if(data == null){
return Response.error("Page "+page+" does not exist. Please add it with /addrolespage");
}
JSONArray array = new JSONArray(data);
for(Object o : array){
if((long) o == role.getIdLong()) return Response.error("Role is already on that page");
}
if(array.length() == 15) return Response.error("Each page has a max of 15 roles");
array.put(role.getId());
data = array.toString();
boolean result = Ken.getInstance().getDatabase().getSelfRoleData().setData(guild.getIdLong(), page, data);
if(result){
return Response.success("Added "+ role +" to page "+page+" successfully");
} else {
return Response.error("Failed to add role to page");
}
}
}

View file

@ -0,0 +1,40 @@
package net.tylermurphy.ken.command.main;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.event.annotation.Requirement;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.List;
public class AddRolesPage {
@Command(name="addrolespage", description="Add a page to the /rolls command")
@Option(name="title", description="Page title", type=OptionType.STRING, required=true)
@Option(name="description", description="Description of the page", type=OptionType.STRING, required=true)
@Requirement(Permission.MANAGE_SERVER)
public Response execute(Guild guild, List<Object> args){
String data = Ken.getInstance().getDatabase().getSelfRoleData().getData(guild.getIdLong(), 0);
JSONArray array;
if(data == null) array = new JSONArray();
else array = new JSONArray(data);
JSONObject page = new JSONObject();
page.put("title", args.get(0));
page.put("description", args.get(1));
array.put(page);
data = array.toString();
boolean result = Ken.getInstance().getDatabase().getSelfRoleData().setData(guild.getIdLong(), 0, data);
if(result){
return Response.success("Added new page called "+args.get(0)+" successfully");
} else {
return Response.error("Failed to create page");
}
}
}

View file

@ -1,13 +0,0 @@
package net.tylermurphy.ken.command.main;
import net.tylermurphy.ken.command.Response;
import javax.management.relation.Role;
public class AddSelfRole {
// public Response execute(Role role, String){
//
// }
}

View file

@ -0,0 +1,53 @@
package net.tylermurphy.ken.command.main;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.event.annotation.Requirement;
import org.json.JSONArray;
import java.util.List;
public class DeleteRole {
@Command(name="deleterole", description="Delete a role from the /rolls command on a certain page")
@Option(name="role", description="Role to delete", type= OptionType.ROLE, required=true)
@Option(name="page#", description="Page to remove it from", type=OptionType.INTEGER, required=true)
@Requirement(Permission.MANAGE_SERVER)
public Response execute(Guild guild, List<Object> args) {
int page = (int)args.get(1);
Role role = (Role)args.get(0);
String data = Ken.getInstance().getDatabase().getSelfRoleData().getData(guild.getIdLong(), page);
if(data == null){
return Response.error("Page "+page+" does not exist.");
}
JSONArray array = new JSONArray(data);
int index = getIndex(array, role);
if(index == -1){
return Response.error("Role is not that page");
}
array.remove(index);
data = array.toString();
boolean result = Ken.getInstance().getDatabase().getSelfRoleData().setData(guild.getIdLong(), page, data);
if(result){
return Response.success("Removed "+ role +" from page "+page+" successfully");
} else {
return Response.error("Failed to remove role from page");
}
}
private int getIndex(JSONArray array, Role role){
int i = 0;
for(Object o : array){
if((long) o == role.getIdLong()) return i;
i++;
}
return -1;
}
}

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.command.main;
public class DeleteSelfRole {
public class DeleteRolesPage {
}

View file

@ -5,8 +5,8 @@ import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.ButtonCallback;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.ButtonCallback;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
public class Help {

View file

@ -5,9 +5,9 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildMessageChannel;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.util.Requirement;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.event.annotation.Requirement;
import net.tylermurphy.ken.command.Response;
import java.util.List;

View file

@ -5,7 +5,7 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -4,7 +4,7 @@ import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -4,7 +4,7 @@ import net.dv8tion.jda.api.entities.AudioChannel;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -6,7 +6,7 @@ import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.PlayerManager;

View file

@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -6,8 +6,8 @@ import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.PlayerManager;

View file

@ -7,8 +7,8 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.ButtonCallback;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.ButtonCallback;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.PlayerManager;

View file

@ -7,8 +7,8 @@ import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -8,7 +8,7 @@ import net.dv8tion.jda.api.entities.GuildMessageChannel;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.PlayerManager;

View file

@ -6,7 +6,7 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.managers.AudioManager;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.music.GuildMusicManager;
import net.tylermurphy.ken.music.MusicPermissions;

View file

@ -7,8 +7,8 @@ import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.JsonRequest;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -6,8 +6,8 @@ import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.JsonRequest;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.command.Response;
import org.json.JSONArray;
import org.json.JSONException;

View file

@ -7,8 +7,8 @@ import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.XmlRequest;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import org.json.JSONException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

View file

@ -7,8 +7,8 @@ import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.JsonRequest;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Selection;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Selection;
import org.json.JSONException;
import org.json.JSONObject;

View file

@ -2,14 +2,13 @@ package net.tylermurphy.ken.command.nsfw;
import net.dv8tion.jda.api.entities.GuildMessageChannel;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.XmlRequest;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import org.json.JSONException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

View file

@ -6,8 +6,8 @@ import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.XmlRequest;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import net.tylermurphy.ken.command.Response;
import org.json.JSONException;
import org.w3c.dom.Document;

View file

@ -7,8 +7,8 @@ import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.XmlRequest;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import org.json.JSONException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

View file

@ -9,9 +9,9 @@ import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.api.HTTPMethod;
import net.tylermurphy.ken.api.JsonRequest;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.util.ButtonCallback;
import net.tylermurphy.ken.util.Command;
import net.tylermurphy.ken.util.Option;
import net.tylermurphy.ken.event.annotation.ButtonCallback;
import net.tylermurphy.ken.event.annotation.Command;
import net.tylermurphy.ken.event.annotation.Option;
import org.json.JSONArray;
import org.json.JSONObject;

View file

@ -10,12 +10,13 @@ public class SelfRoleTable {
public SelfRoleTable(Database database){
String sql = "CREATE TABLE IF NOT EXISTS self_role_data (\n"
+ " guild_id BIGINT NOT NULL,\n"
+ " page INT NOT NULL,\n"
+ " data TEXT NOT NULL,"
+ " PRIMARY KEY (guild_id,page)\n"
+ ");";
String sql = """
CREATE TABLE IF NOT EXISTS self_role_data (
guild_id BIGINT NOT NULL,
page INT NOT NULL,
data TEXT NOT NULL,
PRIMARY KEY (guild_id,page)
);""";
try(Connection connection = database.connect(); Statement statement = connection.createStatement()) {
statement.executeUpdate(sql);
@ -53,4 +54,30 @@ public class SelfRoleTable {
}
}
public boolean deleteData(long guildId, int page){
String sql = "DELETE FROM self_role_data WHERE guild_id = ? AND page = ?; UPDATE self_role_data SET page = page - 1 WHERE guild_id = ? AND page > ?;";
try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, guildId);
statement.setInt(2, page);
statement.setLong(3, guildId);
statement.setInt(4, page);
return statement.executeUpdate() != 0;
} catch (SQLException e) {
Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
return false;
}
}
public int getPages(long guildId) {
String sql = "SELECT MAX(page) AS pageCount FROM self_role_data WHERE guild_id = ?";
try(Connection connection = database.connect(); PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setLong(1, guildId);
ResultSet rs = statement.executeQuery();
return rs.getInt("pageCount");
} catch (SQLException e) {
Ken.getInstance().getLogger().error("SQL Error: " + e.getMessage());
return -1;
}
}
}

View file

@ -0,0 +1,234 @@
package net.tylermurphy.ken.event;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildMessageChannel;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.InteractionHook;
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction;
import net.dv8tion.jda.api.utils.FileUpload;
import net.tylermurphy.ken.Ken;
import net.tylermurphy.ken.command.Register;
import net.tylermurphy.ken.command.Response;
import net.tylermurphy.ken.command.fun.*;
import net.tylermurphy.ken.command.main.*;
import net.tylermurphy.ken.command.music.*;
import net.tylermurphy.ken.command.music.Queue;
import net.tylermurphy.ken.command.nsfw.*;
import java.awt.*;
import java.lang.reflect.Method;
import java.util.*;
import java.util.List;
public class Responder extends ListenerAdapter {
private final Register register;
public Responder(JDA api) {
this.register = new Register(api);
}
public void registerCommands(){
Object[] objects = new Object[]{
new Coinflip(),
new Dice(),
new Eject(),
new AddRole(),
new DeleteRole(),
new Help(),
new Purge(),
new Roles(),
new ForceSkip(),
new Join(),
new Leave(),
new Loop(),
new LoopQueue(),
new NowPlaying(),
new Pause(),
new Play(),
new Queue(),
new Remove(),
new Resume(),
new Skip(),
new Stop(),
new Danbooru(),
new E621(),
new Gelbooru(),
new Hentai(),
new Konachan(),
new nHentai(),
new Rule34(),
new Yandere(),
};
Arrays.stream(objects).forEach(register::register);
}
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
// Make sure the Bot can Talk
if(!event.getChannel().canTalk()) return;
// Bots are not allowed to use commands
if (event.getMember() == null || event.getUser().isBot()) return;
// Get Command Information From Invoke
final String invoke = event.getName().toLowerCase(Locale.ROOT);
Method method = register.getCommand(invoke);
// Check Permissions
if(!event.getMember().hasPermission(register.getPermission(invoke))) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.appendDescription(":x: **Invalid Permissions**\n")
.appendDescription("You require the "+ register.getPermission(invoke)+" permission to use this command.");
event.getHook().sendMessageEmbeds(builder.build()).queue();
return;
}
// Get slash command options if there are any
List<Object> args = getOptions(event.getOptions());
// Get parameters to send to Method
Object[] parameters = new Object[method.getParameterTypes().length];
Class<?>[] types = method.getParameterTypes();
for(int i = 0; i < types.length; i++){
if(types[i] == Member.class){
parameters[i] = event.getMember();
} else if(types[i] == GuildMessageChannel.class){
parameters[i] = event.getGuildChannel();
} else if(types[i] == Guild.class) {
parameters[i] = event.getGuild();
} else if(types[i] == List.class) {
parameters[i] = args;
} else {
parameters[i] = null;
}
}
// Invoke Method and Respond to User
try {
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
Response response = (Response)temp;
reply(response, event);
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
event.replyEmbeds(builder.build()).setEphemeral(true).queue();
e.printStackTrace();
}
}
public void onButtonInteraction(ButtonInteractionEvent event) {
// Make sure the Bot can Talk
if(!event.getChannel().canTalk()) return;
// Bots are not allowed to use commands
if (event.getMember() == null || event.getUser().isBot()) return;
// Get Command Information From Invoke
final String invoke = event.getComponentId().toLowerCase(Locale.ROOT).split("_")[0];
Method method = register.getButtonCallback(invoke);
// Defer Reply
event.deferEdit().queue();
// Get parameters to send to Method
Object[] parameters = new Object[method.getParameterTypes().length];
Class<?>[] types = method.getParameterTypes();
for(int i = 0; i < types.length; i++){
if(types[i] == Member.class){
parameters[i] = event.getMember();
} else if(types[i] == GuildMessageChannel.class){
parameters[i] = event.getGuildChannel();
} else if(types[i] == Guild.class) {
parameters[i] = event.getGuild();
} else if(types[i] == Button.class) {
parameters[i] = event.getButton();
} else if(types[i] == Message.class) {
parameters[i] = event.getMessage();
} else if(types[i] == String.class) {
parameters[i] = event.getComponentId().substring(invoke.length()+1);
} else {
parameters[i] = null;
}
}
// Invoke Method and Respond to User
try {
Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters);
Response response = (Response) temp;
edit(response, event.getHook());
} catch (Exception e) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setTitle(":x: **Error**")
.setDescription(e.getCause().getMessage());
event.getHook().editOriginalEmbeds(builder.build()).queue();
}
}
private void reply(Response response, IReplyCallback event){
if(response.error()) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setDescription(response.getMessage());
event.replyEmbeds(builder.build()).setEphemeral(true).queue();
} else {
ReplyCallbackAction message;
if(response.hasEmbed()) {
message = event.replyEmbeds(response.getEmbeds());
} else {
message = event.reply(response.getMessage());
}
if(response.hasButtons()) message = message.addActionRow(response.getButtons());
if(response.hasFile()) message = message.addFiles(FileUpload.fromData(response.getFile()));
message.queue();
}
}
private void edit(Response response, InteractionHook hook){
if(response.error()) {
EmbedBuilder builder = Ken.getInstance().getDefaultEmbed()
.setColor(Color.RED)
.setDescription(response.getMessage());
hook.sendMessageEmbeds(builder.build()).queue();
} else {
if(response.hasEmbed()) {
hook.editOriginalEmbeds(response.getEmbeds()).queue();
} else {
hook.editOriginal(response.getMessage()).queue();
}
}
}
private List<Object> getOptions(List<OptionMapping> options){
List<Object> args = new ArrayList<>();
options.forEach(option -> {
switch (option.getType()) {
case STRING -> args.add(option.getAsString());
case INTEGER -> args.add(option.getAsInt());
case BOOLEAN -> args.add(option.getAsBoolean());
case USER -> args.add(option.getAsMember());
case CHANNEL -> args.add(option.getAsChannel());
case ROLE -> args.add(option.getAsRole());
case MENTIONABLE -> args.add(option.getAsMentionable());
default -> {
}
}
});
return args;
}
}

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import net.dv8tion.jda.api.interactions.commands.OptionType;

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import net.dv8tion.jda.api.interactions.commands.OptionType;

View file

@ -1,4 +1,4 @@
package net.tylermurphy.ken.util;
package net.tylermurphy.ken.event.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;