Implement basic permission check for message commands
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Bea 2022-11-22 17:08:31 +01:00
parent 11e4a07698
commit 655840dc82
6 changed files with 77 additions and 26 deletions

View File

@ -1,11 +1,13 @@
package wtf.beatrice.hidekobot.commands.message; package wtf.beatrice.hidekobot.commands.message;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import wtf.beatrice.hidekobot.Cache; import wtf.beatrice.hidekobot.Cache;
import wtf.beatrice.hidekobot.objects.commands.MessageCommand; import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
public class CommandsCommand implements MessageCommand public class CommandsCommand implements MessageCommand
{ {
@ -15,6 +17,9 @@ public class CommandsCommand implements MessageCommand
return new LinkedList<>(Collections.singletonList("commands")); return new LinkedList<>(Collections.singletonList("commands"));
} }
@Override
public List<Permission> getPermissions() { return null; }
@Override @Override
public boolean passRawArgs() { public boolean passRawArgs() {
return false; return false;

View File

@ -1,10 +1,12 @@
package wtf.beatrice.hidekobot.commands.message; package wtf.beatrice.hidekobot.commands.message;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import wtf.beatrice.hidekobot.objects.commands.MessageCommand; import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
public class HelloCommand implements MessageCommand public class HelloCommand implements MessageCommand
{ {
@ -14,6 +16,9 @@ public class HelloCommand implements MessageCommand
return new LinkedList<>(Arrays.asList("hi", "hello", "heya")); return new LinkedList<>(Arrays.asList("hi", "hello", "heya"));
} }
@Override
public List<Permission> getPermissions() { return null; }
@Override @Override
public boolean passRawArgs() { public boolean passRawArgs() {
return false; return false;

View File

@ -124,7 +124,7 @@ public class DatabaseSource
String guildId; String guildId;
ChannelType channelType = message.getChannelType(); ChannelType channelType = message.getChannelType();
if(channelType == ChannelType.PRIVATE) if(!(channelType.isGuild()))
{ {
guildId = userId; guildId = userId;
} else { } else {
@ -220,7 +220,7 @@ public class DatabaseSource
String guildId; String guildId;
ChannelType channelType = message.getChannelType(); ChannelType channelType = message.getChannelType();
if(channelType == ChannelType.PRIVATE) if(!(channelType.isGuild()))
{ {
guildId = "PRIVATE"; guildId = "PRIVATE";
} else { } else {

View File

@ -1,6 +1,9 @@
package wtf.beatrice.hidekobot.listeners; package wtf.beatrice.hidekobot.listeners;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -8,7 +11,10 @@ import wtf.beatrice.hidekobot.objects.commands.MessageCommand;
import wtf.beatrice.hidekobot.objects.comparators.MessageCommandAliasesComparator; import wtf.beatrice.hidekobot.objects.comparators.MessageCommandAliasesComparator;
import wtf.beatrice.hidekobot.util.Logger; import wtf.beatrice.hidekobot.util.Logger;
import java.util.*; import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;
public class MessageCommandListener extends ListenerAdapter public class MessageCommandListener extends ListenerAdapter
{ {
@ -21,7 +27,6 @@ public class MessageCommandListener extends ListenerAdapter
// (?i) -> case insensitive flag // (?i) -> case insensitive flag
// ^ -> start of string (not in middle of a sentence) // ^ -> start of string (not in middle of a sentence)
// \b -> the word has to end here // \b -> the word has to end here
// .* -> there can be anything else after this word
public void registerCommand(MessageCommand command) public void registerCommand(MessageCommand command)
@ -43,7 +48,6 @@ public class MessageCommandListener extends ListenerAdapter
return null; return null;
} }
public LinkedList<MessageCommand> getRegisteredCommands() public LinkedList<MessageCommand> getRegisteredCommands()
{ return new LinkedList<>(registeredCommands.values()); } { return new LinkedList<>(registeredCommands.values()); }
@ -55,10 +59,10 @@ public class MessageCommandListener extends ListenerAdapter
{ {
String eventMessage = event.getMessage().getContentDisplay(); String eventMessage = event.getMessage().getContentDisplay();
// check if the sent message matches the bot activation regex (prefix, name, ...)
if(!eventMessage.toLowerCase().matches(commandRegex + ".*")) if(!eventMessage.toLowerCase().matches(commandRegex + ".*"))
return; return;
MessageChannel channel = event.getChannel();
// generate args from the string // generate args from the string
String argsString = eventMessage.replaceAll(commandRegex + "\\s*", ""); String argsString = eventMessage.replaceAll(commandRegex + "\\s*", "");
@ -81,8 +85,37 @@ public class MessageCommandListener extends ListenerAdapter
String commandLabel = argsRaw[0]; String commandLabel = argsRaw[0];
MessageCommand commandObject = getRegisteredCommand(commandLabel); MessageCommand commandObject = getRegisteredCommand(commandLabel);
if(commandObject != null) if(commandObject == null)
{ {
event.getMessage().reply("Unrecognized command: `" + commandLabel + "`!").queue(); // todo prettier
return;
}
ChannelType channelType = event.getChannelType();
// permissions check
List<Permission> requiredPermissions = commandObject.getPermissions();
if(requiredPermissions != null && !requiredPermissions.isEmpty())
{
if(channelType.isGuild()) //todo: what about forum post
{
Member member = event.getMember();
GuildChannel channel = event.getGuildChannel(); //todo: what about forum post
if(member != null)
{
if(!member.hasPermission(channel, requiredPermissions))
{
event.getMessage()
.reply("You do not have permissions to run this command!")
.queue(); // todo prettier
return;
}
}
}
}
String[] commandArgs; String[] commandArgs;
if(commandObject.passRawArgs()) if(commandObject.passRawArgs())
{ {
@ -97,8 +130,5 @@ public class MessageCommandListener extends ListenerAdapter
commandArgs = Arrays.copyOfRange(argsRaw, 1, argsRaw.length); commandArgs = Arrays.copyOfRange(argsRaw, 1, argsRaw.length);
} }
commandObject.runCommand(event, commandLabel, commandArgs); commandObject.runCommand(event, commandLabel, commandArgs);
} else {
event.getMessage().reply("Unrecognized command: `" + commandLabel + "`!").queue(); // todo prettier
}
} }
} }

View File

@ -1,8 +1,11 @@
package wtf.beatrice.hidekobot.objects.commands; package wtf.beatrice.hidekobot.objects.commands;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
public interface MessageCommand public interface MessageCommand
{ {
@ -16,10 +19,19 @@ public interface MessageCommand
*/ */
LinkedList<String> getCommandLabels(); LinkedList<String> getCommandLabels();
/**
* A list of permissions required to run the command. This is preferred to checking them on your own
* as the message listener handles it more homogeneously.
*
* @return the list of required permissions.
*/
@Nullable
List<Permission> getPermissions();
/** /**
* Say if this command does its own text parsing, and tell the message listener if it should automatically * Say if this command does its own text parsing, and tell the message listener if it should automatically
* split all arguments in separate entries of an array, or pass everything as the first entry of that array. * split all arguments in separate entries of an array, or pass everything as the first entry of that array.
* * <p>
* This is better instead of getting the message contents from the event, because the message listener will * This is better instead of getting the message contents from the event, because the message listener will
* still strip the bot prefix and command name from the args, but leave the rest untouched. * still strip the bot prefix and command name from the args, but leave the rest untouched.
* *
@ -30,7 +42,6 @@ public interface MessageCommand
/** /**
* Run the command logic by parsing the event and replying accordingly. * Run the command logic by parsing the event and replying accordingly.
* *
*
* @param event the received message event. It should not be used for parsing message contents data as * @param event the received message event. It should not be used for parsing message contents data as
* the arguments already account for it in a better way. * the arguments already account for it in a better way.
* *

View File

@ -88,7 +88,7 @@ public class ExpiredMessageTask implements Runnable {
} }
// if this is a DM // if this is a DM
if(msgChannelType == ChannelType.PRIVATE) if(!(msgChannelType.isGuild()))
{ {
String userId = databaseSource.getTrackedReplyUserId(messageId); String userId = databaseSource.getTrackedReplyUserId(messageId);
User user = HidekoBot.getAPI().retrieveUserById(userId).complete(); User user = HidekoBot.getAPI().retrieveUserById(userId).complete();