messaging.py 4.6 KB

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