add message snipe feature

This commit is contained in:
Lee
2024-07-01 21:20:39 +01:00
parent 727a4c9a6f
commit 8b451c6ee5
16 changed files with 562 additions and 3 deletions

@ -8,7 +8,6 @@ import cc.fascinated.bat.common.NumberFormatter;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;

@ -0,0 +1,123 @@
package cc.fascinated.bat.features.messagesnipe;
import cc.fascinated.bat.command.Category;
import cc.fascinated.bat.event.EventListener;
import cc.fascinated.bat.features.Feature;
import cc.fascinated.bat.features.messagesnipe.command.MessageSnipeCommand;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import cc.fascinated.bat.model.DiscordMessage;
import cc.fascinated.bat.service.CommandService;
import lombok.NonNull;
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.events.message.MessageUpdateEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @author Fascinated (fascinated7)
*/
@Component
public class MessageSnipeFeature extends Feature implements EventListener {
/**
* The sniped messages for each guild
*/
private static final Map<BatGuild, List<SnipedMessage>> snipedMessages = new HashMap<>();
@Autowired
public MessageSnipeFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) {
super("Message Snipe", false, Category.SNIPE);
super.registerCommand(commandService, context.getBean(MessageSnipeCommand.class));
}
/**
* Clears the sniped messages for the given guild
*
* @param guild the guild
* @return if the sniped messages were cleared
*/
public static boolean clearSnipedMessages(BatGuild guild) {
if (snipedMessages.containsKey(guild)) {
snipedMessages.remove(guild);
return true;
}
return false;
}
/**
* Gets the sniped messages for the given guild
*
* @param guild the guild
* @return the sniped messages for the given guild
*/
public static SnipedMessage getDeletedMessage(BatGuild guild, String channelId) {
List<SnipedMessage> messages = snipedMessages.getOrDefault(guild, new ArrayList<>());
for (SnipedMessage message : messages) {
if (message.getDeletedDate() != null // Check if the message was deleted
&& message.getMessage().getChannel().getId().equals(channelId)) {
return message;
}
}
return null;
}
/**
* Gets the sniped message with the given id
*
* @param guild the guild
* @param messageId the id of the message
* @return the sniped message with the given id
*/
private SnipedMessage getSnipedMessage(BatGuild guild, String messageId) {
List<SnipedMessage> messages = snipedMessages.getOrDefault(guild, new ArrayList<>());
for (SnipedMessage message : messages) {
if (message.getMessage().getId().equals(messageId)) {
return message;
}
}
return null;
}
@Override
public void onGuildMessageReceive(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull MessageReceivedEvent event) {
if (event.getAuthor().isBot()) return;
List<SnipedMessage> messages = snipedMessages.getOrDefault(guild, new ArrayList<>());
if (messages.size() >= 10) {
messages.remove(0);
}
messages.add(new SnipedMessage(event.getMessage(), null));
snipedMessages.put(guild, messages);
}
@Override
public void onGuildMessageDelete(@NonNull BatGuild guild, BatUser user, DiscordMessage message, @NonNull MessageDeleteEvent event) {
List<SnipedMessage> messages = snipedMessages.getOrDefault(guild, new ArrayList<>());
if (messages.size() >= 10) {
messages.remove(0);
}
SnipedMessage snipedMessage = getSnipedMessage(guild, event.getMessageId());
if (snipedMessage == null) {
return;
}
snipedMessage.setDeletedDate(new Date());
}
@Override
public void onGuildMessageEdit(@NonNull BatGuild guild, @NonNull BatUser user, @NonNull MessageUpdateEvent event) {
List<SnipedMessage> messages = snipedMessages.getOrDefault(guild, new ArrayList<>());
if (messages.size() >= 10) {
messages.remove(0);
}
SnipedMessage snipedMessage = getSnipedMessage(guild, event.getMessageId());
if (snipedMessage == null) {
return;
}
snipedMessage.setMessage(event.getMessage());
}
}

@ -0,0 +1,26 @@
package cc.fascinated.bat.features.messagesnipe;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Message;
import java.util.Date;
/**
* @author Fascinated (fascinated7)
*/
@AllArgsConstructor
@Getter
@Setter
public class SnipedMessage {
/**
* The message that was sniped
*/
private Message message;
/**
* The date when the message was deleted
*/
private Date deletedDate;
}

@ -0,0 +1,36 @@
package cc.fascinated.bat.features.messagesnipe.command;
import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.messagesnipe.MessageSnipeFeature;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component("messagesnipe:clear.sub")
@CommandInfo(name = "clear", description = "Clears the known sniped messages for this guild", requiredPermissions = Permission.MESSAGE_MANAGE)
public class ClearSubCommand extends BatSubCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
boolean cleared = MessageSnipeFeature.clearSnipedMessages(guild);
if (!cleared) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("There are no messages to clear in this guild")
.build()).queue();
return;
}
event.replyEmbeds(EmbedUtils.successEmbed()
.setDescription("Successfully cleared the sniped messages for this guild")
.build()).queue();
}
}

@ -0,0 +1,50 @@
package cc.fascinated.bat.features.messagesnipe.command;
import cc.fascinated.bat.command.BatSubCommand;
import cc.fascinated.bat.command.CommandInfo;
import cc.fascinated.bat.common.EmbedUtils;
import cc.fascinated.bat.features.messagesnipe.MessageSnipeFeature;
import cc.fascinated.bat.features.messagesnipe.SnipedMessage;
import cc.fascinated.bat.model.BatGuild;
import cc.fascinated.bat.model.BatUser;
import lombok.NonNull;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(name = "deleted", description = "Snipe the last deleted message in this channel")
public class DeletedSubCommand extends BatSubCommand {
@Override
public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) {
SnipedMessage message = MessageSnipeFeature.getDeletedMessage(guild, channel.getId());
if (message == null) {
event.replyEmbeds(EmbedUtils.errorEmbed()
.setDescription("There are no deleted messages to snipe in this channel")
.build()).queue();
return;
}
User author = message.getMessage().getAuthor();
event.replyEmbeds(EmbedUtils.genericEmbed()
.setDescription("""
**Deleted Message Snipe**
➜ Author: **%s** (%s)
➜ Deleted: <t:%d:R>
➜ Content:
```
%s
```
""".formatted(
author.getAsMention(),
author.getId(),
message.getDeletedDate().getTime() / 1000,
message.getMessage().getContentRaw()
)).build()).queue();
}
}

@ -0,0 +1,19 @@
package cc.fascinated.bat.features.messagesnipe.command;
import cc.fascinated.bat.command.BatCommand;
import cc.fascinated.bat.command.CommandInfo;
import lombok.NonNull;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* @author Fascinated (fascinated7)
*/
@Component
@CommandInfo(name = "snipe", description = "Snipe messages")
public class MessageSnipeCommand extends BatCommand {
public MessageSnipeCommand(@NonNull ApplicationContext context) {
super.addSubCommand(context.getBean(DeletedSubCommand.class));
super.addSubCommand(context.getBean(ClearSubCommand.class));
}
}