package com.shadorc.shadbot.core.command; import com.shadorc.shadbot.Shadbot; import com.shadorc.shadbot.command.MissingArgumentException; import com.shadorc.shadbot.data.Config; import com.shadorc.shadbot.music.GuildMusic; import com.shadorc.shadbot.music.MusicManager; import com.shadorc.shadbot.music.NoMusicException; import com.shadorc.shadbot.utils.DiscordUtils; import com.shadorc.shadbot.utils.NumberUtils; import com.shadorc.shadbot.utils.StringUtils; import discord4j.common.util.Snowflake; import discord4j.core.GatewayDiscordClient; import discord4j.core.event.domain.message.MessageCreateEvent; import discord4j.core.object.entity.Guild; import discord4j.core.object.entity.Member; import discord4j.core.object.entity.Message; import discord4j.core.object.entity.User; import discord4j.core.object.entity.channel.Channel; import discord4j.core.object.entity.channel.MessageChannel; import discord4j.core.object.entity.channel.TextChannel; import discord4j.rest.util.Permission; import reactor.bool.BooleanUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.util.annotation.Nullable; import java.util.List; import java.util.Optional; public class Context { private final MessageCreateEvent event; private final String prefix; private final String cmdName; @Nullable private final String arg; public Context(MessageCreateEvent event, String prefix) { this.event = event; this.prefix = prefix; final List<String> splittedMsg = StringUtils.split(this.getContent(), 2); this.cmdName = splittedMsg.get(0).substring(prefix.length()).toLowerCase(); this.arg = splittedMsg.size() > 1 ? splittedMsg.get(1).trim() : null; } public MessageCreateEvent getEvent() { return this.event; } public Optional<String> getArg() { return Optional.ofNullable(this.arg); } public User getAuthor() { return this.getMessage().getAuthor().orElseThrow(); } public Snowflake getAuthorId() { return this.getAuthor().getId(); } public String getAvatarUrl() { return this.getAuthor().getAvatarUrl(); } public Mono<MessageChannel> getChannel() { return this.getMessage().getChannel(); } public Snowflake getChannelId() { return this.getMessage().getChannelId(); } public GatewayDiscordClient getClient() { return this.event.getClient(); } public String getCommandName() { return this.cmdName; } public String getContent() { return this.getMessage().getContent(); } public Mono<Guild> getGuild() { return this.event.getGuild(); } public Snowflake getGuildId() { return this.event.getGuildId().orElseThrow(); } public Member getMember() { return this.event.getMember().orElseThrow(); } public Message getMessage() { return this.event.getMessage(); } public Flux<CommandPermission> getPermissions() { // The author is a bot's owner final Mono<CommandPermission> ownerPerm = Mono.just(this.getAuthorId()) .filter(Shadbot.getOwnerId()::equals) .map(ignored -> CommandPermission.OWNER); // The member is an administrator or it's a private message final Mono<CommandPermission> adminPerm = this.getChannel() .filterWhen(channel -> BooleanUtils.or( DiscordUtils.hasPermission(channel, this.getAuthorId(), Permission.ADMINISTRATOR), Mono.just(channel.getType() == Channel.Type.DM))) .map(ignored -> CommandPermission.ADMIN); return Flux.merge(ownerPerm, adminPerm, Mono.just(CommandPermission.USER)); } public String getPrefix() { return this.prefix; } public Mono<User> getSelf() { return this.getClient().getSelf(); } public Snowflake getSelfId() { return this.getClient().getSelfId(); } public Mono<Member> getSelfAsMember() { return this.getSelf().flatMap(self -> self.asMember(this.getGuildId())); } public int getShardCount() { return this.getEvent().getShardInfo().getCount(); } public int getShardIndex() { return this.getEvent().getShardInfo().getIndex(); } public String getUsername() { return this.getAuthor().getUsername(); } public Mono<Boolean> isChannelNsfw() { return this.getChannel() .ofType(TextChannel.class) .map(TextChannel::isNsfw); } public String requireArg() { return this.getArg() .map(StringUtils::normalizeSpace) .orElseThrow(MissingArgumentException::new); } public List<String> requireArgs(int count) { return this.requireArgs(count, count); } public List<String> requireArgs(int min, int max) { return this.requireArgs(min, max, Config.COMMAND_DELIMITER); } public List<String> requireArgs(int min, int max, String delimiter) { final List<String> args = StringUtils.split(this.requireArg(), max, delimiter); if (!NumberUtils.isBetween(args.size(), min, max)) { throw new MissingArgumentException(); } return args; } public GuildMusic requireGuildMusic() { return MusicManager.getInstance() .getGuildMusic(this.getGuildId()) .filter(guildMusic -> !guildMusic.getTrackScheduler().isStopped()) .orElseThrow(NoMusicException::new); } }