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.

crosspostcog.py 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. from rscollections import SizeBoundList
  2. from discord import Guild, Message
  3. from cogs.basecog import BaseCog
  4. class CrossPostCog(BaseCog):
  5. class SpamContext:
  6. def __init__(self, member):
  7. self.member = member
  8. self.age = timedate.now()
  9. self.is_warned = False
  10. STATE_KEY_RECENT_MESSAGES = "crosspost_recent_messages"
  11. STATE_KEY_SPAM_CONTEXT = "crosspost_spam_context"
  12. def __init__(self, bot):
  13. super().__init__(bot)
  14. self.max_recent_messages = 20
  15. self.max_spam_contexts = 12
  16. self.messages_per_user = 3
  17. self.min_message_length = 10
  18. def __record_message(self, message: Message) -> None:
  19. recent_messages = Storage.get_state_value(message.guild, self.STATE_KEY_RECENT_MESSAGES) \
  20. or SizeBoundList(self.max_recent_messages, lambda index, message : message.created_at)
  21. recent_messages.append(message)
  22. Storage.set_state_value(message.guild, self.STATE_KEY_RECENT_MESSAGES, recent_messages)
  23. def __check_for_spam(self, guild: Guild) -> None:
  24. recent_messages = Storage.get_state_value(guild, self.STATE_KEY_RECENT_MESSAGES)
  25. if recent_messages is None:
  26. return
  27. user_id_to_count = {}
  28. spamming_members = set()
  29. for message in recent_messages:
  30. content = message.content
  31. if len(content) < self.min_message_length:
  32. continue
  33. key = str(message.author.id) + '|' + hash(content)
  34. count = (user_id_to_count.get(key) or 0) + 1
  35. user_id_to_count[key] = count
  36. if count >= self.messages_per_user:
  37. spamming_members.add(message.author)
  38. for member in spamming_members:
  39. context = self.__spam_context_for_user(member, True)
  40. if not context.is_warned:
  41. self.__on_new_spam(context)
  42. def __on_new_spam(self, context: SpamContext):
  43. context.is_warned = True
  44. # TODO
  45. def __spam_context_for_user(self,
  46. member: Member,
  47. create_if_missing: bool = False) -> SpamContext:
  48. spam_lookup = Storage.get_state_value(member.guild, self.STATE_KEY_SPAM_CONTEXT) \
  49. or SizeBoundDict(self.max_spam_contexts, lambda key, context : context.age)
  50. context = spam_lookup.get(member.id)
  51. if context:
  52. return context
  53. if not create_if_missing:
  54. return None
  55. context = SpamContext(member)
  56. spam_lookup[member.id] = context
  57. Storage.set_state_value(member.guild, self.STATE_KEY_SPAM_CONTEXT, spam_lookup)
  58. return context
  59. @commands.Cog.listener()
  60. def on_message(self, message: Message):
  61. self.__record_message(message)
  62. self.__check_for_spam(message.guild)