Pārlūkot izejas kodu

Adding autokick option to only kick users who go offline seconds after joining. Added presence permission to intents to get member status.

master
Rocketsoup 2 gadus atpakaļ
vecāks
revīzija
6292a00b59
2 mainītis faili ar 52 papildinājumiem un 2 dzēšanām
  1. 1
    0
      bot.py
  2. 51
    2
      rocketbot/cogs/autokickcog.py

+ 1
- 0
bot.py Parādīt failu

57
 intents = Intents.default()
57
 intents = Intents.default()
58
 intents.messages = True  # pylint: disable=assigning-non-slot
58
 intents.messages = True  # pylint: disable=assigning-non-slot
59
 intents.members = True  # pylint: disable=assigning-non-slot
59
 intents.members = True  # pylint: disable=assigning-non-slot
60
+intents.presences = True
60
 bot = Rocketbot(command_prefix=CONFIG['command_prefix'], intents=intents)
61
 bot = Rocketbot(command_prefix=CONFIG['command_prefix'], intents=intents)
61
 
62
 
62
 # Core
63
 # Core

+ 51
- 2
rocketbot/cogs/autokickcog.py Parādīt failu

1
 from datetime import datetime, timedelta
1
 from datetime import datetime, timedelta
2
+from typing import cast
2
 
3
 
3
-from discord import Guild, Member
4
-from discord.ext import commands
4
+from discord import Guild, Member, Status
5
+from discord.ext import commands, tasks
6
+from discord.ext.tasks import Loop
5
 
7
 
6
 from config import CONFIG
8
 from config import CONFIG
7
 from rocketbot.cogs.basecog import BaseCog, BotMessage, CogSetting
9
 from rocketbot.cogs.basecog import BaseCog, BotMessage, CogSetting
8
 from rocketbot.collections import AgeBoundDict
10
 from rocketbot.collections import AgeBoundDict
9
 from rocketbot.storage import Storage
11
 from rocketbot.storage import Storage
12
+from rocketbot.utils import bot_log
10
 
13
 
11
 class AutoKickContext:
14
 class AutoKickContext:
12
 	"""
15
 	"""
22
 		self.last_kick = time
25
 		self.last_kick = time
23
 		self.kick_count += 1
26
 		self.kick_count += 1
24
 
27
 
28
+class StatusCheckContext:
29
+	def __init__(self, member: Member):
30
+		self.member = member
31
+		self.joined_at = datetime.now()
32
+
25
 class AutoKickCog(BaseCog, name='Auto Kick'):
33
 class AutoKickCog(BaseCog, name='Auto Kick'):
26
 	"""
34
 	"""
27
 	Cog for automatically kicking ALL new joins. For temporary use during join raids.
35
 	Cog for automatically kicking ALL new joins. For temporary use during join raids.
36
 					'disables this feature (only kick, never ban).',
44
 					'disables this feature (only kick, never ban).',
37
 			usage='<count:int>',
45
 			usage='<count:int>',
38
 			min_value=0)
46
 			min_value=0)
47
+	SETTING_OFFLINE_ONLY = CogSetting('offlineonly', bool,
48
+			brief='whether to only kick users whose status is offline',
49
+			description='Compromised accounts may have a status of offline. ' + \
50
+					'If this setting is enabled, the user\'s status will be ' + \
51
+					'checked a few seconds after joining. If it is offline ' + \
52
+					'they will be kicked.',
53
+			usage='<true|false>')
39
 
54
 
40
 	STATE_KEY_RECENT_KICKS = "AutoKickCog.recent_joins"
55
 	STATE_KEY_RECENT_KICKS = "AutoKickCog.recent_joins"
41
 
56
 
43
 		super().__init__(bot)
58
 		super().__init__(bot)
44
 		self.add_setting(AutoKickCog.SETTING_ENABLED)
59
 		self.add_setting(AutoKickCog.SETTING_ENABLED)
45
 		self.add_setting(AutoKickCog.SETTING_BAN_COUNT)
60
 		self.add_setting(AutoKickCog.SETTING_BAN_COUNT)
61
+		self.add_setting(AutoKickCog.SETTING_OFFLINE_ONLY)
62
+		self.status_check_members = []
63
+		timer: Loop = cast(Loop, self.status_check_timer)
64
+		timer.start()
46
 
65
 
47
 	@commands.group(
66
 	@commands.group(
48
 		brief='Automatically kicks all new users as soon as they join',
67
 		brief='Automatically kicks all new users as soon as they join',
60
 		guild: Guild = member.guild
79
 		guild: Guild = member.guild
61
 		if not self.get_guild_setting(guild, self.SETTING_ENABLED):
80
 		if not self.get_guild_setting(guild, self.SETTING_ENABLED):
62
 			return
81
 			return
82
+		if self.get_guild_setting(guild, self.SETTING_OFFLINE_ONLY):
83
+			self.log(guild, f'New member {member.name} status is {member.status}')
84
+			self.status_check_members.append(StatusCheckContext(member))
85
+			return
86
+		self.__kick_or_ban_if_needed(member)
87
+
88
+	@tasks.loop(seconds=5.0)
89
+	async def status_check_timer(self):
90
+		'Checks status of new members shortly after joining to see if they go offline'
91
+		contexts = self.status_check_members.copy()
92
+		self.status_check_members = []
93
+		now = datetime.now()
94
+		# bot_log(guild=None, cog_class=None, message=f'Found {len(contexts)} members to check')
95
+		for c in contexts:
96
+			context: StatusCheckContext = c
97
+			member: Member = context.member
98
+			guild: Guild = member.guild
99
+			if now - context.joined_at < timedelta(seconds=5.0):
100
+				# Too soon, check again later
101
+				self.status_check_members.append(context)
102
+				continue
103
+			if member.status != Status.offline:
104
+				# Online, ignore
105
+				self.log(guild, f'{member.name} status is {member.status}. Not kicking.')
106
+				continue
107
+			self.log(guild, f'{member.name} went offline 5s later')
108
+			await self.__kick_or_ban_if_needed(member)
109
+
110
+	async def __kick_or_ban_if_needed(self, member: Member):
111
+		guild: Guild = member.guild
63
 		recent_kicks: AgeBoundDict = Storage.get_state_value(guild, AutoKickCog.STATE_KEY_RECENT_KICKS)
112
 		recent_kicks: AgeBoundDict = Storage.get_state_value(guild, AutoKickCog.STATE_KEY_RECENT_KICKS)
64
 		if recent_kicks is None:
113
 		if recent_kicks is None:
65
 			recent_kicks = AgeBoundDict(timedelta(seconds=3600), lambda i, context : context.last_kick)
114
 			recent_kicks = AgeBoundDict(timedelta(seconds=3600), lambda i, context : context.last_kick)

Notiek ielāde…
Atcelt
Saglabāt