Преглед на файлове

Adding URL spam cog. Fixing joinraid cog.

tags/1.0.1
Rocketsoup преди 4 години
родител
ревизия
0d09d27221
променени са 5 файла, в които са добавени 85 реда и са изтрити 25 реда
  1. 1
    0
      cogs/basecog.py
  2. 3
    25
      cogs/joinraidcog.py
  3. 75
    0
      cogs/urlspamcog.py
  4. 4
    0
      config.py.sample
  5. 2
    0
      rocketbot.py

+ 1
- 0
cogs/basecog.py Целия файл

2
 from discord.ext import commands
2
 from discord.ext import commands
3
 from datetime import timedelta
3
 from datetime import timedelta
4
 
4
 
5
+from config import CONFIG
5
 from rscollections import AgeBoundDict
6
 from rscollections import AgeBoundDict
6
 from storage import ConfigKey, Storage
7
 from storage import ConfigKey, Storage
7
 import json
8
 import json

+ 3
- 25
cogs/joinraidcog.py Целия файл

162
 	"""
162
 	"""
163
 	def __init__(self, guild_id: int):
163
 	def __init__(self, guild_id: int):
164
 		self.guild_id = guild_id
164
 		self.guild_id = guild_id
165
-		self.join_warning_count = self.get_cog_default('warning_count')
166
-		self.join_warning_seconds = self.get_cog_default('warning_seconds')
167
 		# Non-persisted runtime state
165
 		# Non-persisted runtime state
168
 		self.current_raid = JoinRaidRecord()
166
 		self.current_raid = JoinRaidRecord()
169
 		self.all_raids = [ self.current_raid ] # periodically culled of old ones
167
 		self.all_raids = [ self.current_raid ] # periodically culled of old ones
170
 
168
 
171
-	# Events
172
-
173
-	async def handle_join(self, member: Member) -> None:
174
-		"""
175
-		Event handler for all joins to this guild.
176
-		"""
177
-		now = member.joined_at
178
-		raid = self.current_raid
179
-		raid.handle_join(
180
-			member,
181
-			now=now,
182
-			max_age_seconds = self.join_warning_seconds,
183
-			max_join_count = self.join_warning_count)
184
-		self.__trace(f'raid phase: {raid.phase}')
185
-		if raid.phase == RaidPhase.JUST_STARTED:
186
-			await self.__on_join_raid_begin(raid)
187
-		elif raid.phase == RaidPhase.CONTINUING:
188
-			await self.__on_join_raid_updated(raid)
189
-		elif raid.phase == RaidPhase.ENDED:
190
-			self.__start_new_raid(member)
191
-			await self.__on_join_raid_end(raid)
192
-		self.__cull_old_raids(now)
193
-
194
 	def reset_raid(self, now: datetime):
169
 	def reset_raid(self, now: datetime):
195
 		"""
170
 		"""
196
 		Retires self.current_raid and creates a new empty one.
171
 		Retires self.current_raid and creates a new empty one.
467
 		if gc is not None:
442
 		if gc is not None:
468
 			return gc
443
 			return gc
469
 		gc = GuildContext(guild.id)
444
 		gc = GuildContext(guild.id)
445
+		gc.join_warning_count = self.get_cog_default('warning_count')
446
+		gc.join_warning_seconds = self.get_cog_default('warning_seconds')
447
+
470
 		self.guild_id_to_context[guild.id] = gc
448
 		self.guild_id_to_context[guild.id] = gc
471
 		return gc
449
 		return gc
472
 
450
 

+ 75
- 0
cogs/urlspamcog.py Целия файл

1
+from discord import Guild, Message
2
+from discord.ext import commands
3
+import re
4
+from datetime import timedelta
5
+
6
+from cogs.basecog import BaseCog
7
+from config import CONFIG
8
+from storage import Storage
9
+
10
+class URLSpamCog(BaseCog):
11
+	CONFIG_KEY_EARLY_URL_TIMEOUT = "urlspam_early_url_timeout"
12
+	CONFIG_KEY_EARLY_URL_ACTION = "urlspam_early_url_action"
13
+
14
+	def __init__(self, bot):
15
+		super().__init__(bot)
16
+
17
+	def __early_url_timeout(self, guild: Guild) -> int:
18
+		return Storage.get_config_value(guild, self.CONFIG_KEY_EARLY_URL_TIMEOUT) or \
19
+			self.get_cog_default('early_url_timeout')
20
+
21
+	def __early_url_action(self, guild: Guild) -> str:
22
+		return Storage.get_config_value(guild, self.CONFIG_KEY_EARLY_URL_ACTION) or \
23
+			self.get_cog_default('early_url_action')
24
+
25
+	@commands.Cog.listener()
26
+	async def on_message(self, message: Message):
27
+		if message.guild is None or message.channel is None:
28
+			# DM or something
29
+			return
30
+		action = self.__early_url_action(message.guild)
31
+		if action == 'nothing':
32
+			return
33
+		if message.author.permissions_in(message.channel).ban_members:
34
+			# Mods are exempt
35
+			return
36
+		if not self.__contains_url(message.content):
37
+			return
38
+		join_age = message.created_at - message.author.joined_at
39
+		join_age_str = self.__format_timedelta(join_age)
40
+		if join_age.total_seconds() < self.__early_url_timeout(message.guild):
41
+			if action == 'modwarn':
42
+				await self.warn(message.guild, f'User {message.author.mention} ' +
43
+					f'posted a URL {join_age_str} after joining.\n\n> {message.content}')
44
+				# TODO: Emoji actions
45
+			elif action == 'delete':
46
+				await message.delete()
47
+				# TODO: Info to mods
48
+			elif action == 'kick':
49
+				await message.author.kick(reason=f'User posted a link {join_age_str} after joining')
50
+				# TODO: Info to mods
51
+			elif action == 'ban':
52
+				await message.author.ban(reason=f'User posted a link {join_age_str} after joining', delete_message_days=1)
53
+				# TODO: Info to mods
54
+
55
+	def __contains_url(self, text: str) -> bool:
56
+		p = re.compile(r'http[^\s]*')
57
+		return p.search(text) is not None
58
+
59
+	def __format_timedelta(self, timespan: timedelta) -> str:
60
+		parts = []
61
+		d = timespan.days
62
+		h = timespan.seconds // 3600
63
+		m = (timespan.seconds // 60) % 60
64
+		s = timespan.seconds % 60
65
+		if d > 0:
66
+			parts.append(f'{d}d')
67
+		if d > 0 or h > 0:
68
+			parts.append(f'{h}h')
69
+		if d > 0 or h > 0 or m > 0:
70
+			parts.append(f'{m}m')
71
+		parts.append(f'{s}s')
72
+		# Limit the precision to the two most significant elements
73
+		while len(parts) > 2:
74
+			parts.pop(-1)
75
+		return ' '.join(parts)

+ 4
- 0
config.py.sample Целия файл

22
 			'time_window_seconds': 120,
22
 			'time_window_seconds': 120,
23
 			'min_message_length': 0,
23
 			'min_message_length': 0,
24
 		},
24
 		},
25
+		'URLSpamCog': {
26
+			'early_url_timeout': 900,  # Should be > 10m due to Discord-imposed waiting period
27
+			'early_url_action': 'modwarn', # "nothing" | "modwarn" | "delete" | "kick" | "ban"
28
+		},
25
 	},
29
 	},
26
 }
30
 }

+ 2
- 0
rocketbot.py Целия файл

13
 from cogs.crosspostcog import CrossPostCog
13
 from cogs.crosspostcog import CrossPostCog
14
 from cogs.generalcog import GeneralCog
14
 from cogs.generalcog import GeneralCog
15
 from cogs.joinraidcog import JoinRaidCog
15
 from cogs.joinraidcog import JoinRaidCog
16
+# from cogs.urlspamcog import URLSpamCog
16
 
17
 
17
 CURRENT_CONFIG_VERSION = 1
18
 CURRENT_CONFIG_VERSION = 1
18
 if (CONFIG.get('__config_version') or 0) < CURRENT_CONFIG_VERSION:
19
 if (CONFIG.get('__config_version') or 0) < CURRENT_CONFIG_VERSION:
32
 bot.add_cog(ConfigCog(bot))
33
 bot.add_cog(ConfigCog(bot))
33
 bot.add_cog(JoinRaidCog(bot))
34
 bot.add_cog(JoinRaidCog(bot))
34
 bot.add_cog(CrossPostCog(bot))
35
 bot.add_cog(CrossPostCog(bot))
36
+# bot.add_cog(URLSpamCog(bot))
35
 bot.run(CONFIG['client_token'], bot=True, reconnect=True)
37
 bot.run(CONFIG['client_token'], bot=True, reconnect=True)
36
 print('\nBot aborted')
38
 print('\nBot aborted')

Loading…
Отказ
Запис