Selaa lähdekoodia

Adding ignored domains list to urlspamcog

main
Rocketsoup 3 kuukautta sitten
vanhempi
commit
108de727d1
2 muutettua tiedostoa jossa 105 lisäystä ja 52 poistoa
  1. 1
    1
      README.md
  2. 104
    51
      rocketbot/cogs/urlspamcog.py

+ 1
- 1
README.md Näytä tiedosto

@@ -4,7 +4,7 @@ Discord bot for detecting and dealing with jerks. This bot is Rocketsoup's fault
4 4
 
5 5
 ## Requirements
6 6
 
7
-* Python 3.9
7
+* Python 3.10
8 8
 
9 9
 ## Setup
10 10
 

+ 104
- 51
rocketbot/cogs/urlspamcog.py Näytä tiedosto

@@ -5,7 +5,7 @@ import re
5 5
 from datetime import timedelta
6 6
 from typing import Literal
7 7
 
8
-from discord import Member, Message
8
+from discord import Guild, Member, Message
9 9
 from discord import utils as discordutils
10 10
 from discord.ext.commands import Cog
11 11
 from discord.utils import escape_markdown
@@ -69,6 +69,14 @@ class URLSpamCog(BaseCog, name='URL Spam'):
69 69
 		enum_values={'nothing', 'modwarn', 'modwarndelete',
70 70
 					 'chatwarn', 'chatwarndelete', 'delete', 'kick', 'ban'},
71 71
 	)
72
+	SETTING_IGNORED_DOMAINS = CogSetting(
73
+		'ignoreddomains',
74
+		str,
75
+		default_value='tenor.com;giphy.com;imgur.com',
76
+		brief='List of allowed domains to exclude from detecting',
77
+		description='A semicolon-delimited list of domains that can be posted '
78
+					'without triggering a warning. E.g. GIF hosting sites.'
79
+	)
72 80
 
73 81
 	def __init__(self, bot):
74 82
 		super().__init__(
@@ -80,79 +88,115 @@ class URLSpamCog(BaseCog, name='URL Spam'):
80 88
 		self.add_setting(URLSpamCog.SETTING_ACTION)
81 89
 		self.add_setting(URLSpamCog.SETTING_JOIN_AGE)
82 90
 		self.add_setting(URLSpamCog.SETTING_DECEPTIVE_ACTION)
91
+		self.add_setting(URLSpamCog.SETTING_IGNORED_DOMAINS)
83 92
 
84 93
 	@Cog.listener()
85 94
 	async def on_message(self, message: Message):
86 95
 		"""Event listener"""
87 96
 		if message.author is None or \
88
-				message.author.bot or \
89 97
 				message.guild is None or \
90 98
 				message.channel is None or \
91 99
 				message.content is None:
100
+			self.__trace("Missing message data")
101
+			return
102
+		if message.author.bot:
103
+			self.__trace("Message from bot")
104
+			return
105
+		if message.channel.permissions_for(message.author).ban_members:
106
+			self.__trace("User exempt")
92 107
 			return
93 108
 		if not self.get_guild_setting(message.guild, self.SETTING_ENABLED):
109
+			self.__trace("Cog disabled")
110
+			return
111
+		urls = self.__find_urls(message.content)
112
+		if len(urls) == 0:
113
+			self.__trace("Contains no URLs")
114
+			return
115
+		if self.__all_ignored_domains(message.guild, urls):
116
+			self.__trace("All URLs are ignored domains")
94 117
 			return
95 118
 		await self.check_message_recency(message)
96 119
 		await self.check_deceptive_links(message)
97 120
 
121
+	def __all_ignored_domains(self, guild: Guild, urls: list[str]) -> bool:
122
+		domain_list: str = self.get_guild_setting(guild, self.SETTING_IGNORED_DOMAINS)
123
+		self.__trace(f"Domain list is {domain_list}")
124
+		domains = domain_list.split(';')
125
+		self.__trace(f"Split into {len(domains)} domains")
126
+		for url in urls:
127
+			if not self.__is_ignored_url(url, domains):
128
+				return False
129
+		return True
130
+
131
+	def __is_ignored_url(self, url: str, ignored_domains: list[str]) -> bool:
132
+		p = re.compile(r'https?://([\w\.]+)')
133
+		domain = re.search(p, url).group(1)
134
+		for ignored_domain in ignored_domains:
135
+			if domain.endswith(ignored_domain.strip()):
136
+				self.__trace(f"URL {url} matches ignored domain {ignored_domain}")
137
+				return True
138
+		self.__trace("URL {url} not ignored")
139
+		return False
140
+
98 141
 	async def check_message_recency(self, message: Message):
99 142
 		"""Checks if the message was sent too recently by a new user"""
100 143
 		action = self.get_guild_setting(message.guild, self.SETTING_ACTION)
101 144
 		join_seconds = self.get_guild_setting(message.guild, self.SETTING_JOIN_AGE)
102 145
 		min_join_age = timedelta(seconds=join_seconds)
103 146
 		if action == 'nothing':
104
-			return
105
-		if not self.__contains_url(message.content):
147
+			self.__trace("Configured action is nothing")
106 148
 			return
107 149
 		join_age = message.created_at - message.author.joined_at
108 150
 		join_age_str = describe_timedelta(join_age)
109
-		if join_age < min_join_age:
110
-			context = URLSpamContext(message)
111
-			needs_attention = False
112
-			if action == 'modwarn':
113
-				needs_attention = not self.was_warned_recently(message.author)
114
-				self.log(message.guild, f'New user {message.author.name} ' + \
115
-					f'({message.author.id}) posted URL {join_age_str} after ' + \
116
-					'joining.' + (' Mods alerted.' if needs_attention else ''))
117
-			elif action == 'delete':
118
-				await message.delete()
119
-				context.is_deleted = True
120
-				self.log(message.guild, f'New user {message.author.name} ' + \
121
-					f'({message.author.id}) posted URL {join_age_str} after ' + \
122
-					'joining. Message deleted.')
123
-			elif action == 'kick':
124
-				await message.delete()
125
-				context.is_deleted = True
126
-				await message.author.kick(
127
-					reason=f'Rocketbot: Posted a link {join_age_str} after joining')
128
-				context.is_kicked = True
129
-				self.log(message.guild, f'New user {message.author.name} ' + \
130
-					f'({message.author.id}) posted URL {join_age_str} after ' + \
131
-					'joining. User kicked.')
132
-			elif action == 'ban':
133
-				await message.author.ban(
134
-					reason=f'Rocketbot: User posted a link {join_age_str} after joining',
135
-					delete_message_days=1)
136
-				context.is_deleted = True
137
-				context.is_kicked = True
138
-				context.is_banned = True
139
-				self.log(message.guild, f'New user {message.author.name} ' + \
140
-					f'({message.author.id}) posted URL {join_age_str} after ' + \
141
-					'joining. User banned.')
142
-			bm = BotMessage(
143
-					message.guild,
144
-					f'User {message.author.mention} posted a URL ' + \
145
-					f'{join_age_str} after joining: {message.jump_url}',
146
-					type = BotMessage.TYPE_MOD_WARNING if needs_attention else BotMessage.TYPE_INFO,
147
-					context = context)
148
-			bm.quote = discordutils.remove_markdown(message.clean_content)
149
-			await bm.set_reactions(BotMessageReaction.standard_set(
150
-				did_delete=context.is_deleted,
151
-				did_kick=context.is_kicked,
152
-				did_ban=context.is_banned))
153
-			await self.post_message(bm)
154
-			if needs_attention:
155
-				self.record_warning(message.author)
151
+		if join_age > min_join_age:
152
+			self.__trace("User has been member long enough")
153
+			return
154
+		context = URLSpamContext(message)
155
+		needs_attention = False
156
+		if action == 'modwarn':
157
+			needs_attention = not self.was_warned_recently(message.author)
158
+			self.log(message.guild, f'New user {message.author.name} ' + \
159
+				f'({message.author.id}) posted URL {join_age_str} after ' + \
160
+				'joining.' + (' Mods alerted.' if needs_attention else ''))
161
+		elif action == 'delete':
162
+			await message.delete()
163
+			context.is_deleted = True
164
+			self.log(message.guild, f'New user {message.author.name} ' + \
165
+				f'({message.author.id}) posted URL {join_age_str} after ' + \
166
+				'joining. Message deleted.')
167
+		elif action == 'kick':
168
+			await message.delete()
169
+			context.is_deleted = True
170
+			await message.author.kick(
171
+				reason=f'Rocketbot: Posted a link {join_age_str} after joining')
172
+			context.is_kicked = True
173
+			self.log(message.guild, f'New user {message.author.name} ' + \
174
+				f'({message.author.id}) posted URL {join_age_str} after ' + \
175
+				'joining. User kicked.')
176
+		elif action == 'ban':
177
+			await message.author.ban(
178
+				reason=f'Rocketbot: User posted a link {join_age_str} after joining',
179
+				delete_message_days=1)
180
+			context.is_deleted = True
181
+			context.is_kicked = True
182
+			context.is_banned = True
183
+			self.log(message.guild, f'New user {message.author.name} ' + \
184
+				f'({message.author.id}) posted URL {join_age_str} after ' + \
185
+				'joining. User banned.')
186
+		bm = BotMessage(
187
+				message.guild,
188
+				f'User {message.author.mention} posted a URL ' + \
189
+				f'{join_age_str} after joining: {message.jump_url}',
190
+				type = BotMessage.TYPE_MOD_WARNING if needs_attention else BotMessage.TYPE_INFO,
191
+				context = context)
192
+		bm.quote = discordutils.remove_markdown(message.clean_content)
193
+		await bm.set_reactions(BotMessageReaction.standard_set(
194
+			did_delete=context.is_deleted,
195
+			did_kick=context.is_kicked,
196
+			did_ban=context.is_banned))
197
+		await self.post_message(bm)
198
+		if needs_attention:
199
+			self.record_warning(message.author)
156 200
 
157 201
 	async def check_deceptive_links(self, message: Message):
158 202
 		"""
@@ -302,7 +346,16 @@ class URLSpamCog(BaseCog, name='URL Spam'):
302 346
 			did_kick=context.is_kicked,
303 347
 			did_ban=context.is_banned))
304 348
 
349
+	def __trace(self, message: str):
350
+		# print(f'URLSpamCog: {message}')
351
+		pass
352
+
305 353
 	@classmethod
306 354
 	def __contains_url(cls, text: str) -> bool:
307 355
 		p = re.compile(r'https?://\S+')
308 356
 		return p.search(text) is not None
357
+
358
+	@classmethod
359
+	def __find_urls(cls, text: str) -> list[str]:
360
+		p = re.compile(r'https?://\S+')
361
+		return re.findall(p, text)

Loading…
Peruuta
Tallenna