ChatModService.java (4827B)
1 package com.wimdupont.sxcybot.services.guild; 2 3 import com.wimdupont.sxcybot.repository.guild.ChatDataRepository; 4 import com.wimdupont.sxcybot.repository.guild.dao.ChatData; 5 import net.dv8tion.jda.api.entities.Guild; 6 import net.dv8tion.jda.api.events.message.MessageReceivedEvent; 7 import net.dv8tion.jda.api.exceptions.ErrorResponseException; 8 import net.dv8tion.jda.api.exceptions.HierarchyException; 9 import net.dv8tion.jda.api.exceptions.RateLimitedException; 10 import org.slf4j.Logger; 11 import org.slf4j.LoggerFactory; 12 import org.springframework.stereotype.Service; 13 import org.springframework.transaction.annotation.Transactional; 14 import org.springframework.util.StringUtils; 15 16 import java.time.LocalDateTime; 17 import java.util.List; 18 19 @Service 20 @Transactional 21 public class ChatModService { 22 23 private static final Logger LOGGER = LoggerFactory.getLogger(ChatModService.class); 24 private final ChatDataRepository chatDataRepository; 25 26 public ChatModService(ChatDataRepository chatDataRepository) { 27 this.chatDataRepository = chatDataRepository; 28 } 29 30 public boolean isAllowed(MessageReceivedEvent event) { 31 if (event.getMember() == null || event.getMember().getUser().isBot() || !containsUrl(event)) 32 return true; 33 34 var discordId = event.getMember().getUser().getId(); 35 var previousUrlMessages = chatDataRepository.findAllByDiscordIdAndWithUrlTrueOrderByCreatedDateTimeDesc(discordId); 36 var currentData = persist(discordId, event.getChannel().asTextChannel().getId(), event.getMessageId()); 37 38 return isValidForHistory(previousUrlMessages, event, currentData); 39 } 40 41 private boolean isValidForHistory(List<ChatData> previousUrlMessages, 42 MessageReceivedEvent event, 43 ChatData currentData) { 44 if (previousUrlMessages.isEmpty()) 45 return true; 46 try { 47 LocalDateTime latest = previousUrlMessages.stream().findFirst() 48 .map(ChatData::getCreatedDateTime) 49 .orElseThrow(); 50 if (latest.plusMinutes(1L).isBefore(LocalDateTime.now())) { 51 chatDataRepository.deleteAll(previousUrlMessages); 52 } else if (previousUrlMessages.size() >= 2 && previousUrlMessages.size() < 4) { 53 dmWarning(event); 54 } else if (previousUrlMessages.size() >= 4 && event.getMember() != null) { 55 try { 56 event.getMember().kick().reason("Spamming URL's.").queue(); 57 } catch (HierarchyException | ErrorResponseException e) { 58 LOGGER.error(e.getMessage(), e); 59 } 60 for (ChatData chatData : previousUrlMessages) { 61 removeMessage(event.getGuild(), chatData); 62 } 63 removeMessage(event.getGuild(), currentData); 64 return false; 65 } 66 } catch (RateLimitedException | ErrorResponseException e) { 67 LOGGER.error(e.getMessage(), e); 68 } 69 return true; 70 } 71 72 private ChatData persist(String discordId, String channelId, String messageId) { 73 return chatDataRepository.save(ChatData.Builder.newBuilder() 74 .discordId(discordId) 75 .channelId(channelId) 76 .messageId(messageId) 77 .withUrl(true) 78 .build()); 79 } 80 81 private void dmWarning(MessageReceivedEvent event) throws RateLimitedException { 82 if (event.getMember() != null) { 83 var privateChannel = event.getMember().getUser().openPrivateChannel().complete(true); 84 privateChannel.sendMessage(String.format("Warning: stop spamming URL's! (server: %s)", 85 event.getGuild().getName())).queue(); 86 } 87 } 88 89 private void removeMessage(Guild guild, ChatData chatData) throws RateLimitedException { 90 var channel = guild.getTextChannelById(chatData.getChannelId()); 91 if (channel != null) { 92 channel.retrieveMessageById(chatData.getMessageId()).complete(true).delete().queue(); 93 chatDataRepository.delete(chatData); 94 } 95 } 96 97 private boolean containsUrl(MessageReceivedEvent event) { 98 var msg = event.getMessage().getContentRaw().toLowerCase(); 99 if (containsUrl(msg)) 100 return true; 101 102 if (!event.getMessage().getEmbeds().isEmpty()) { 103 return event.getMessage().getEmbeds().stream() 104 .anyMatch(f -> StringUtils.hasLength(f.getUrl()) 105 || containsUrl(f.getTitle()) 106 || containsUrl(f.getDescription())); 107 } 108 return false; 109 } 110 111 private boolean containsUrl(String msg) { 112 return msg != null && msg.matches(".*https?://.*|.*www\\..*"); 113 } 114 }