Experimental Discord bot written in Python
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

autokickcog.py 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. from datetime import datetime, timedelta
  2. from discord import Guild, Member
  3. from discord.ext import commands
  4. from config import CONFIG
  5. from rocketbot.cogs.basecog import BaseCog, BotMessage, CogSetting
  6. from rocketbot.collections import AgeBoundDict
  7. from rocketbot.storage import Storage
  8. class AutoKickContext:
  9. """
  10. Data about a join raid.
  11. """
  12. def __init__(self, member: Member, first_kick: datetime):
  13. self.member = member
  14. self.first_kick = first_kick
  15. self.last_kick = first_kick
  16. self.kick_count = 1
  17. def record_kick(self, time: datetime):
  18. self.last_kick = time
  19. self.kick_count += 1
  20. class AutoKickCog(BaseCog, name='Auto Kick'):
  21. """
  22. Cog for automatically kicking ALL new joins. For temporary use during join raids.
  23. """
  24. SETTING_ENABLED = CogSetting('enabled', bool,
  25. brief='autokick',
  26. description='Whether this cog is enabled for a guild.')
  27. SETTING_BAN_COUNT = CogSetting('bancount', int,
  28. brief='number of repeat kicks before a ban',
  29. description='The number of times a user can join and be kicked ' + \
  30. 'before the next rejoin will result in a ban. A value of 0 ' + \
  31. 'disables this feature (only kick, never ban).',
  32. usage='<count:int>',
  33. min_value=0)
  34. STATE_KEY_RECENT_KICKS = "AutoKickCog.recent_joins"
  35. def __init__(self, bot):
  36. super().__init__(bot)
  37. self.add_setting(AutoKickCog.SETTING_ENABLED)
  38. self.add_setting(AutoKickCog.SETTING_BAN_COUNT)
  39. @commands.group(
  40. brief='Automatically kicks all new users as soon as they join',
  41. )
  42. @commands.has_permissions(ban_members=True)
  43. @commands.guild_only()
  44. async def autokick(self, context: commands.Context):
  45. 'Auto-kick'
  46. if context.invoked_subcommand is None:
  47. await context.send_help()
  48. @commands.Cog.listener()
  49. async def on_member_join(self, member: Member) -> None:
  50. 'Event handler'
  51. guild: Guild = member.guild
  52. if not self.get_guild_setting(guild, self.SETTING_ENABLED):
  53. return
  54. recent_kicks: AgeBoundDict = Storage.get_state_value(guild, AutoKickCog.STATE_KEY_RECENT_KICKS)
  55. if recent_kicks is None:
  56. recent_kicks = AgeBoundDict(timedelta(seconds=3600), lambda i, context : context.last_kick)
  57. Storage.set_state_value(guild, self.STATE_KEY_RECENT_KICKS, recent_kicks)
  58. context: AutoKickContext = recent_kicks.get(member.id)
  59. if context is None:
  60. context = AutoKickContext(member, datetime.now())
  61. recent_kicks[member.id] = context
  62. else:
  63. context.record_kick(datetime.now())
  64. max_kick_count: int = self.get_guild_setting(guild, self.SETTING_BAN_COUNT)
  65. disable_help = f'To disable this feature: `{CONFIG["command_prefix"]}autokick disable`.'
  66. ban_help = f'To configure ban threshold: `{CONFIG["command_prefix"]}autokick ' + \
  67. 'setbancount #` (0 to disable).'
  68. if max_kick_count > 0 and context.kick_count > max_kick_count:
  69. await member.ban(reason=f'Rocketbot: Ban after {context.kick_count} joins',
  70. delete_message_days=0)
  71. msg = BotMessage(guild,
  72. text=f'Banned {member.mention} ({member.id}) after {context.kick_count} joins. ' + \
  73. disable_help + ' ' + ban_help,
  74. type=BotMessage.TYPE_INFO,
  75. context=None)
  76. await self.post_message(msg)
  77. self.log(guild, f'Banned {member.name} after {context.kick_count} joins')
  78. else:
  79. await member.kick(reason='Rocketbot: Autokick enabled.')
  80. msg = BotMessage(guild,
  81. text=f'Autokicked {member.mention} ({member.id}) ' + \
  82. f'({AutoKickCog.ordinal(context.kick_count)} time). ' + \
  83. disable_help + ' ' + ban_help,
  84. type=BotMessage.TYPE_INFO,
  85. context=None)
  86. await self.post_message(msg)
  87. self.log(guild, f'Autokicked {member.name} ' + \
  88. f'({AutoKickCog.ordinal(context.kick_count)} time)')
  89. @staticmethod
  90. def ordinal(val: int):
  91. 'Formats an integer with an ordinal suffix (English only)'
  92. if val % 10 == 1:
  93. return f'{val}st'
  94. if val % 10 == 2:
  95. return f'{val}nd'
  96. if val % 10 == 3:
  97. return f'{val}rd'
  98. return f'{val}th'