001package co.aikar.commands; 002 003import co.aikar.commands.annotation.Author; 004import co.aikar.commands.annotation.CrossGuild; 005import co.aikar.commands.annotation.SelfUser; 006import net.dv8tion.jda.api.JDA; 007import net.dv8tion.jda.api.entities.ChannelType; 008import net.dv8tion.jda.api.entities.Guild; 009import net.dv8tion.jda.api.entities.Message; 010import net.dv8tion.jda.api.entities.MessageChannel; 011import net.dv8tion.jda.api.entities.Role; 012import net.dv8tion.jda.api.entities.TextChannel; 013import net.dv8tion.jda.api.entities.User; 014import net.dv8tion.jda.api.events.message.MessageReceivedEvent; 015 016import java.util.List; 017 018// TODO: Message Keys !!! 019public class JDACommandContexts extends CommandContexts<JDACommandExecutionContext> { 020 private final JDACommandManager manager; 021 private final JDA jda; 022 023 public JDACommandContexts(JDACommandManager manager) { 024 super(manager); 025 this.manager = manager; 026 this.jda = this.manager.getJDA(); 027 this.registerIssuerOnlyContext(JDACommandEvent.class, CommandExecutionContext::getIssuer); 028 this.registerIssuerOnlyContext(MessageReceivedEvent.class, c -> c.getIssuer().getIssuer()); 029 this.registerIssuerOnlyContext(Message.class, c -> c.issuer.getIssuer().getMessage()); 030 this.registerIssuerOnlyContext(ChannelType.class, c -> c.issuer.getIssuer().getChannelType()); 031 this.registerIssuerOnlyContext(JDA.class, c -> jda); 032 this.registerIssuerOnlyContext(Guild.class, c -> { 033 MessageReceivedEvent event = c.getIssuer().getIssuer(); 034 if (event.isFromType(ChannelType.PRIVATE) && !c.isOptional()) { 035 throw new InvalidCommandArgument("This command can only be executed in a Guild.", false); 036 } else { 037 return event.getGuild(); 038 } 039 }); 040 this.registerIssuerAwareContext(MessageChannel.class, c -> { 041 if (c.hasAnnotation(Author.class)) { 042 return c.issuer.getIssuer().getChannel(); 043 } 044 boolean isCrossGuild = c.hasAnnotation(CrossGuild.class); 045 String argument = c.popFirstArg(); // we pop because we are only issuer aware if we are annotated 046 MessageChannel channel = null; 047 if (argument.startsWith("<#")) { 048 String id = argument.substring(2, argument.length() - 1); 049 channel = isCrossGuild ? jda.getTextChannelById(id) : c.issuer.getIssuer().getGuild().getTextChannelById(id); 050 } else { 051 List<TextChannel> channelList = isCrossGuild ? jda.getTextChannelsByName(argument, true) : 052 c.issuer.getEvent().getGuild().getTextChannelsByName(argument, true); 053 if (channelList.size() > 1) { 054 throw new InvalidCommandArgument("Too many channels were found with the given name. Try with the `#channelname` syntax.", false); 055 } else if (channelList.size() == 1) { 056 channel = channelList.get(0); 057 } 058 } 059 if (channel == null) { 060 throw new InvalidCommandArgument("Couldn't find a channel with that name or ID."); 061 } 062 return channel; 063 }); 064 this.registerIssuerAwareContext(User.class, c -> { 065 if (c.hasAnnotation(SelfUser.class)) { 066 return jda.getSelfUser(); 067 } 068 String arg = c.getFirstArg(); 069 if (c.isOptional() && (arg == null || arg.isEmpty())) { 070 return null; 071 } 072 arg = c.popFirstArg(); // we pop because we are only issuer aware if we are annotated 073 User user = null; 074 if (arg.startsWith("<@!")) { // for some reason a ! is added when @'ing and clicking their name. 075 user = jda.getUserById(arg.substring(3, arg.length() - 1)); 076 } else if (arg.startsWith("<@")) { // users can /also/ be mentioned like this... 077 user = jda.getUserById(arg.substring(2, arg.length() - 1)); 078 } else { 079 List<User> users = jda.getUsersByName(arg, true); 080 if (users.size() > 1) { 081 throw new InvalidCommandArgument("Too many users were found with the given name. Try with the `@username#0000` syntax.", false); 082 } 083 if (!users.isEmpty()) { 084 user = users.get(0); 085 } 086 } 087 if (user == null) { 088 throw new InvalidCommandArgument("Could not find a user with that name or ID."); 089 } 090 return user; 091 }); 092 this.registerContext(Role.class, c -> { 093 boolean isCrossGuild = c.hasAnnotation(CrossGuild.class); 094 String arg = c.popFirstArg(); 095 Role role = null; 096 if (arg.startsWith("<@&")) { 097 String id = arg.substring(3, arg.length() - 1); 098 role = isCrossGuild ? jda.getRoleById(id) : c.issuer.getIssuer().getGuild().getRoleById(id); 099 } else { 100 List<Role> roles = isCrossGuild ? jda.getRolesByName(arg, true) 101 : c.issuer.getIssuer().getGuild().getRolesByName(arg, true); 102 if (roles.size() > 1) { 103 throw new InvalidCommandArgument("Too many roles were found with the given name. Try with the `@role` syntax.", false); 104 } 105 if (!roles.isEmpty()) { 106 role = roles.get(0); 107 } 108 } 109 if (role == null) { 110 throw new InvalidCommandArgument("Could not find a role with that name or ID."); 111 } 112 return role; 113 }); 114 } 115}