messaging.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. from dataclasses import dataclass
  2. from enum import Enum, auto
  3. BANGS = ('!',)
  4. def pop_arg(text):
  5. if text is None:
  6. return None, None
  7. parts = text.split(maxsplit=1)
  8. if len(parts) == 1:
  9. return parts[0], None
  10. return parts[0], parts[1].strip()
  11. @dataclass
  12. class RollbotMessage:
  13. src: str
  14. name: str
  15. sender_id: str
  16. group_id: str
  17. message_id: str
  18. message_txt: str
  19. from_admin: bool
  20. def __post_init__(self):
  21. self.is_command = False
  22. if len(self.message_txt) > 0 and self.message_txt[0] in BANGS:
  23. cmd, raw = pop_arg(self.message_txt[1:].strip())
  24. if cmd is not None:
  25. self.is_command = True
  26. self.command = cmd.lower()
  27. self.raw_args = raw
  28. @staticmethod
  29. def from_subcommand(msg):
  30. subc = RollbotMessage(
  31. msg.src,
  32. msg.name,
  33. msg.sender_id,
  34. msg.group_id,
  35. msg.message_id,
  36. msg.raw_args, # this strips the command of the old message
  37. msg.from_admin
  38. )
  39. if subc.is_command:
  40. return subc
  41. # silently return None if a subcommand could not be made
  42. @staticmethod
  43. def from_groupme(msg, global_admins=(), group_admins={}):
  44. sender_id = msg["sender_id"]
  45. group_id = msg["group_id"]
  46. return RollbotMessage(
  47. "GROUPME",
  48. msg["name"],
  49. sender_id,
  50. group_id,
  51. msg["id"],
  52. msg["text"].strip(),
  53. sender_id in global_admins or (
  54. group_id in group_admins and
  55. sender_id in group_admins[group_id])
  56. )
  57. @staticmethod
  58. def from_discord(msg, global_admins=(), group_admins={}):
  59. sender_id = str(msg.author.id)
  60. group_id = str(msg.channel.id)
  61. return RollbotMessage(
  62. "DISCORD",
  63. msg.author.name,
  64. sender_id,
  65. group_id,
  66. msg.id,
  67. msg.content.strip(),
  68. sender_id in global_admins or (
  69. group_id in group_admins and
  70. sender_id in group_admins[group_id])
  71. )
  72. def args(self, normalize=True):
  73. arg, rest = pop_arg(self.raw_args)
  74. while arg is not None:
  75. yield arg.lower() if normalize else arg
  76. arg, rest = pop_arg(rest)
  77. class RollbotFailure(Enum):
  78. INVALID_COMMAND = auto()
  79. MISSING_SUBCOMMAND = auto()
  80. INVALID_SUBCOMMAND = auto()
  81. INVALID_ARGUMENTS = auto()
  82. SERVICE_DOWN = auto()
  83. PERMISSIONS = auto()
  84. INTERNAL_ERROR = auto()
  85. _RESPONSE_TEMPLATE = """Response{
  86. Original Message: %s,
  87. Text Response: %s,
  88. Image Response: %s,
  89. Respond: %s,
  90. Failure Reason: %s,
  91. Failure Notes: %s
  92. }"""
  93. @dataclass
  94. class RollbotResponse:
  95. msg: RollbotMessage
  96. txt: str = None
  97. img: str = None
  98. respond: bool = True
  99. failure: RollbotFailure = None
  100. debugging: dict = None
  101. def __post_init__(self):
  102. self.info = _RESPONSE_TEMPLATE % (self.msg, self.txt, self.img, self.respond, self.failure, self.debugging)
  103. self.is_success = self.failure is None
  104. if self.failure is None:
  105. self.failure_msg = None
  106. elif self.failure == RollbotFailure.INVALID_COMMAND:
  107. self.failure_msg = "Sorry - I don't think I understand the command '!%s'... " % self.msg.command \
  108. + "I'll try to figure it out and get back to you!"
  109. elif self.failure == RollbotFailure.MISSING_SUBCOMMAND:
  110. self.failure_msg = "Sorry - !%s requires a sub-command." % self.msg.command
  111. elif self.failure == RollbotFailure.INVALID_SUBCOMMAND:
  112. self.failure_msg = "Sorry - the sub-command you used for %s was not valid." % self.msg.command
  113. elif self.failure == RollbotFailure.INVALID_ARGUMENTS:
  114. self.failure_msg = "Sorry - %s cannot use those arguments!" % self.msg.command
  115. elif self.failure == RollbotFailure.SERVICE_DOWN:
  116. self.failure_msg = "Sorry - %s relies on a service I couldn't reach!" % self.msg.command
  117. elif self.failure == RollbotFailure.PERMISSIONS:
  118. self.failure_msg = "Sorry - you don't have permission to use that command or sub-command in this chat!"
  119. elif self.failure == RollbotFailure.INTERNAL_ERROR:
  120. self.failure_msg = "Sorry - I encountered an unrecoverable error, please review internal logs."
  121. if self.debugging is not None and "explain" in self.debugging:
  122. self.failure_msg += " " + self.debugging["explain"]