99import net .discordjug .javabot .util .ExceptionLogger ;
1010import net .discordjug .javabot .util .MessageUtils ;
1111import net .dv8tion .jda .api .Permission ;
12- import net .dv8tion .jda .api .entities .Guild ;
1312import net .dv8tion .jda .api .entities .Member ;
1413import net .dv8tion .jda .api .entities .Message ;
1514import net .dv8tion .jda .api .entities .channel .unions .MessageChannelUnion ;
2625import java .net .URL ;
2726import java .time .Duration ;
2827import java .time .temporal .ChronoUnit ;
29- import java .util .ArrayList ;
30- import java .util .Collections ;
31- import java .util .List ;
32- import java .util .Scanner ;
28+ import java .util .*;
3329import java .util .concurrent .TimeUnit ;
3430import java .util .regex .Matcher ;
3531import java .util .regex .Pattern ;
@@ -54,17 +50,18 @@ public class AutoMod extends ListenerAdapter {
5450
5551 /**
5652 * Constructor of the class, that creates a list of strings with potential spam/scam URLs.
53+ *
5754 * @param notificationService The {@link QOTWPointsService}
58- * @param botConfig The main configuration of the bot
59- * @param moderationService Service object for moderating members
60- * @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
6158 */
6259 public AutoMod (NotificationService notificationService , BotConfig botConfig , ModerationService moderationService , MessageCache messageCache ) {
6360 this .notificationService = notificationService ;
6461 this .botConfig = botConfig ;
6562 this .moderationService = moderationService ;
6663 this .messageCache = messageCache ;
67- 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" )) {
6865 String response = scan .next ();
6966 spamUrls = List .of (response .split ("\n " ));
7067 } catch (IOException e ) {
@@ -108,36 +105,46 @@ private boolean canBypassAutomod(Member member) {
108105 private void checkNewMessageAutomod (@ Nonnull Message message ) {
109106 // spam
110107 long spamCount = messageCache .getMessagesAfter (message .getTimeCreated ().minusSeconds (6 ))
111- .stream ()
112- .filter (cached -> cached .getMessageId () != message .getIdLong ()) // exclude new/current message
113- .filter (cached -> cached .getAuthorId () == message .getAuthor ().getIdLong ())
114- .filter (cached ->
115- // only java files -> not spam
116- cached .getAttachments ().isEmpty () ||
117- cached .getAttachments ().stream ()
118- .anyMatch (attachment -> !attachment .contains (".java?" )))
119- .count () + 1 ; // include new message
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
120117
121118 if (spamCount >= 5 ) {
122- handleSpam (message , message . getMember () );
119+ handleSpam (message );
123120 }
124-
125121 checkContentAutomod (message );
126122 checkCrossChannelSpam (message );
127123 }
128124
129125 private void checkCrossChannelSpam (@ Nonnull Message message ) {
126+ int spamWindowSeconds = (botConfig .get (message .getGuild ()).getModerationConfig ()).getCrossChannelSpamWindowSeconds ();
127+ Set <Long > channelIds = new HashSet <>();
130128 List <CachedMessage > spamMessages = new ArrayList <>();
131- messageCache .getMessagesAfter (message .getTimeCreated ().minusSeconds ((botConfig .get (message .getGuild ()).getModerationConfig ()).getCrossChannelSpamWindowSeconds ())).stream ()
132- .filter (cachedMessage -> cachedMessage .getAuthorId () == message .getAuthor ().getIdLong ())
133- .filter (cachedMessage -> spamMessages .stream ().noneMatch (
134- spamMessage -> spamMessage .getChannelId () == cachedMessage .getChannelId ()))
135- .forEach (spamMessages ::add );
136129
137- if ( spamMessages . size () > ( botConfig . get ( message . getGuild ()). getModerationConfig ()). getCrossChannelSpamMinChannels ()) {
138- handleSpam ( spamMessages , message ) ;
130+ if ( spamWindowSeconds <= 0 ) {
131+ return ;
139132 }
140133
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+ }
141148 }
142149
143150 /**
@@ -148,7 +155,7 @@ private void checkCrossChannelSpam(@Nonnull Message message) {
148155 private void checkContentAutomod (@ Nonnull Message message ) {
149156 //Check for Advertising Links
150157 if (hasAdvertisingLink (message )) {
151- doAutomodActions (message ,"Advertising" );
158+ doAutomodActions (message , "Advertising" );
152159 }
153160
154161 //Check for suspicious Links
@@ -176,24 +183,20 @@ private void doAutomodActions(Message message, String reason) {
176183 /**
177184 * Handles detected spam messages.
178185 *
179- * @param msg the (last) spam message
180- * @param member the member to be potentially warned
186+ * @param msg the (last) spam message
181187 */
182- private void handleSpam (@ Nonnull Message msg , Member member ) {
183- moderationService
184- .timeout (
185- member .getUser (),
186- "Automod: Spam" ,
187- msg .getGuild ().getSelfMember (),
188- Duration .of (6 , ChronoUnit .HOURS ),
189- msg .getChannel (),
190- false
191- );
188+ private void handleSpam (@ Nonnull Message msg ) {
189+ markSpam (msg );
192190 msg .delete ().queue ();
193191 }
194192
195193 private void handleSpam (@ Nonnull List <CachedMessage > cachedMessages , Message message ) {
196- Guild guild = message .getGuild ();
194+ markSpam (message );
195+ cachedMessages .forEach (cachedMessage -> message .getGuild ().getTextChannelById (cachedMessage .getChannelId ())
196+ .deleteMessageById (cachedMessage .getMessageId ()).queue ());
197+ }
198+
199+ private void markSpam (@ Nonnull Message message ) {
197200 moderationService
198201 .timeout (
199202 message .getAuthor (),
@@ -203,9 +206,6 @@ private void handleSpam(@Nonnull List<CachedMessage> cachedMessages, Message mes
203206 message .getChannel (),
204207 false
205208 );
206-
207- cachedMessages .forEach (cachedMessage -> guild .getTextChannelById (cachedMessage .getChannelId ())
208- .deleteMessageById (cachedMessage .getMessageId ()).queue ());
209209 }
210210
211211 /**
@@ -252,7 +252,7 @@ public boolean hasSuspiciousLink(@NotNull Message message) {
252252 * Checks whether the given message contains a discord invite link.
253253 *
254254 * @param message The Message to check.
255- * @return True if an invitation is found and False if not.
255+ * @return True if an invites is found and False if not.
256256 */
257257 public boolean hasAdvertisingLink (@ NotNull Message message ) {
258258 // Advertising
0 commit comments