33import lombok .extern .slf4j .Slf4j ;
44import net .discordjug .javabot .data .config .BotConfig ;
55import net .discordjug .javabot .data .h2db .message_cache .MessageCache ;
6+ import net .discordjug .javabot .data .h2db .message_cache .model .CachedMessage ;
67import net .discordjug .javabot .systems .moderation .warn .model .WarnSeverity ;
78import net .discordjug .javabot .systems .notification .NotificationService ;
89import net .discordjug .javabot .util .ExceptionLogger ;
2425import java .net .URL ;
2526import java .time .Duration ;
2627import java .time .temporal .ChronoUnit ;
27- import java .util .Collections ;
28- import java .util .List ;
29- import java .util .Scanner ;
28+ import java .util .*;
3029import java .util .concurrent .TimeUnit ;
3130import java .util .regex .Matcher ;
3231import java .util .regex .Pattern ;
@@ -50,18 +49,19 @@ public class AutoMod extends ListenerAdapter {
5049 private final MessageCache messageCache ;
5150
5251 /**
53- * Constructor of the class, that creates a list of strings with potential spam/scam urls.
52+ * Constructor of the class, that creates a list of strings with potential spam/scam URLs.
53+ *
5454 * @param notificationService The {@link QOTWPointsService}
55- * @param botConfig The main configuration of the bot
56- * @param moderationService Service object for moderating members
57- * @param messageCache service for retrieving cached messages
55+ * @param botConfig The main configuration of the bot
56+ * @param moderationService Service object for moderating members
57+ * @param messageCache service for retrieving cached messages
5858 */
5959 public AutoMod (NotificationService notificationService , BotConfig botConfig , ModerationService moderationService , MessageCache messageCache ) {
6060 this .notificationService = notificationService ;
6161 this .botConfig = botConfig ;
6262 this .moderationService = moderationService ;
6363 this .messageCache = messageCache ;
64- try (Scanner scan = new Scanner (new URL ("https://raw.githubusercontent.com/DevSpen/scam-links/master/src/links.txt" ).openStream ()).useDelimiter ("\\ A" )) {
64+ try (Scanner scan = new Scanner (new URL ("https://raw.githubusercontent.com/DevSpen/scam-links/master/src/links.txt" ).openStream ()).useDelimiter ("\\ A" )) {
6565 String response = scan .next ();
6666 spamUrls = List .of (response .split ("\n " ));
6767 } catch (IOException e ) {
@@ -105,21 +105,46 @@ private boolean canBypassAutomod(Member member) {
105105 private void checkNewMessageAutomod (@ Nonnull Message message ) {
106106 // spam
107107 long spamCount = messageCache .getMessagesAfter (message .getTimeCreated ().minusSeconds (6 ))
108- .stream ()
109- .filter (cached -> cached .getMessageId () != message .getIdLong ()) // exclude new/current message
110- .filter (cached -> cached .getAuthorId () == message .getAuthor ().getIdLong ())
111- .filter (cached ->
112- // only java files -> not spam
113- cached .getAttachments ().isEmpty () ||
114- cached .getAttachments ().stream ()
115- .anyMatch (attachment -> !attachment .contains (".java?" )))
116- .count () + 1 ; // include new message
117-
108+ .stream ()
109+ .filter (cached -> cached .getMessageId () != message .getIdLong ()) // exclude new/current message
110+ .filter (cached -> cached .getAuthorId () == message .getAuthor ().getIdLong ())
111+ .filter (cached ->
112+ // only java files -> not spam
113+ cached .getAttachments ().isEmpty () ||
114+ cached .getAttachments ().stream ()
115+ .anyMatch (attachment -> !attachment .contains (".java?" )))
116+ .count () + 1 ; // include new message
117+
118118 if (spamCount >= 5 ) {
119- handleSpam (message , message . getMember () );
119+ handleSpam (message );
120120 }
121-
122121 checkContentAutomod (message );
122+ checkCrossChannelSpam (message );
123+ }
124+
125+ private void checkCrossChannelSpam (@ Nonnull Message message ) {
126+ int spamWindowSeconds = (botConfig .get (message .getGuild ()).getModerationConfig ()).getCrossChannelSpamWindowSeconds ();
127+ Set <Long > channelIds = new HashSet <>();
128+ List <CachedMessage > spamMessages = new ArrayList <>();
129+
130+ if (spamWindowSeconds <= 0 ) {
131+ return ;
132+ }
133+
134+ for (CachedMessage cachedMessage : messageCache .getMessagesAfter (message .getTimeCreated ().minusSeconds (spamWindowSeconds ))) {
135+ if (cachedMessage .getMessageId () == message .getIdLong ()) {
136+ continue ;
137+ }
138+ if (cachedMessage .getAuthorId () != message .getAuthor ().getIdLong ()) {
139+ continue ;
140+ }
141+ channelIds .add (cachedMessage .getChannelId ());
142+ spamMessages .add (cachedMessage );
143+ }
144+
145+ if (channelIds .size () >= (botConfig .get (message .getGuild ()).getModerationConfig ()).getCrossChannelSpamMinChannels ()) {
146+ handleSpam (spamMessages , message );
147+ }
123148 }
124149
125150 /**
@@ -130,7 +155,7 @@ private void checkNewMessageAutomod(@Nonnull Message message) {
130155 private void checkContentAutomod (@ Nonnull Message message ) {
131156 //Check for Advertising Links
132157 if (hasAdvertisingLink (message )) {
133- doAutomodActions (message ,"Advertising" );
158+ doAutomodActions (message , "Advertising" );
134159 }
135160
136161 //Check for suspicious Links
@@ -158,20 +183,29 @@ private void doAutomodActions(Message message, String reason) {
158183 /**
159184 * Handles detected spam messages.
160185 *
161- * @param msg the (last) spam message
162- * @param member the member to be potentially warned
186+ * @param msg the (last) spam message
163187 */
164- private void handleSpam (@ Nonnull Message msg , Member member ) {
188+ private void handleSpam (@ Nonnull Message msg ) {
189+ timeoutForSpam (msg );
190+ msg .delete ().queue ();
191+ }
192+
193+ private void handleSpam (@ Nonnull List <CachedMessage > cachedMessages , Message message ) {
194+ timeoutForSpam (message );
195+ cachedMessages .forEach (cachedMessage -> message .getGuild ().getTextChannelById (cachedMessage .getChannelId ())
196+ .deleteMessageById (cachedMessage .getMessageId ()).queue ());
197+ }
198+
199+ private void timeoutForSpam (@ Nonnull Message message ) {
165200 moderationService
166201 .timeout (
167- member . getUser (),
202+ message . getAuthor (),
168203 "Automod: Spam" ,
169- msg .getGuild ().getSelfMember (),
204+ message .getGuild ().getSelfMember (),
170205 Duration .of (6 , ChronoUnit .HOURS ),
171- msg .getChannel (),
206+ message .getChannel (),
172207 false
173208 );
174- msg .delete ().queue ();
175209 }
176210
177211 /**
@@ -237,5 +271,5 @@ private boolean isSuggestionsChannel(@NotNull MessageChannelUnion channel) {
237271 return channel .getType ().isGuild () &&
238272 channel .getIdLong () == botConfig .get (channel .asGuildMessageChannel ().getGuild ()).getModerationConfig ().getSuggestionChannel ().getIdLong ();
239273 }
240-
274+
241275}
0 commit comments