2 # Copyright (c) 2016-2022 by Someone <someone@somenet.org> (aka. Jan Vales <jan@jvales.net>)
3 # published under MIT-License
6 class RequireException(Exception):
7 """Required precondition not met-exception. Mostly used for permission checks. Message will be forwarded to command-caller/user"""
10 class AbstractCommand():
13 ICON_PRIVATE = "🥷 "
18 CONFIG = {"display_name": "somebot-command", "auto_complete": True}
22 mm_secret_token = None
25 def __init__(self, team_id):
26 self.TEAM_ID = team_id
29 return str(self.__class__)+" for team_id: "+str(self.TEAM_ID)
35 # can/should be overridden by the user
36 def on_register(self):
37 """Consider to override. Handles the post-command-registration logic at bot startup."""
38 self._create_slash_command()
40 # can/should be overridden by the user
41 def on_shutdown(self):
42 """Consider to override. Handles the shutdown-procedure."""
45 # can/should be overridden by the user
46 def on_SIGUSR1(self, sigusr1_cnt):
47 """Consider to override. Handles the SIGUSR1-signal."""
50 # should be overridden by the user
51 def on_POST(self, request, data):
52 """Override. Handles the post-command logic."""
55 # should be overridden by the user
56 # manual command authentication needed!
57 def on_POST_interactive(self, request, data):
58 """Consider to override. Handles the interactive-message logic."""
61 # should be overridden by the user
62 # manual command authentication needed!
63 def on_POST_dialog(self, request, data):
64 """Consider to override. Handles the dialog logic."""
68 def _on_register(self, bot):
70 self.URL = self.bot.local_websrv_url+"/"+self.TEAM_ID+"/"+self.TRIGGER
72 self.bot.USETOPICS.setdefault("/"+self.TRIGGER, self.USEINFO)
76 def _on_shutdown(self):
80 def _on_SIGUSR1(self, sigusr1_cnt):
81 self.on_SIGUSR1(sigusr1_cnt)
84 def _on_POST(self, request, data):
86 self._require_not_guest(data)
87 self.on_POST(request, data)
88 except RequireException as ex:
89 request.respond_cmd_err(str(ex))
92 def _on_POST_interactive(self, request, data):
94 self._require_not_guest(data)
95 self.on_POST_interactive(request, data)
96 except RequireException as ex:
97 request.respond_cmd_err(str(ex))
100 def _on_POST_dialog(self, request, data):
102 self._require_not_guest(data)
103 self.on_POST_dialog(request, data)
104 except RequireException as ex:
105 request.respond_cmd_err(str(ex))
108 def _create_slash_command(self):
109 # (possibly) delete old version of command
110 for command in self.bot.api.list_custom_slash_commands_for_team(self.TEAM_ID):
111 if command["url"] == self.URL or command["trigger"].lower() == self.TRIGGER.lower():
112 self.bot.api.delete_slash_command(command["id"])
114 # create slash command
115 res = self.bot.api.create_slash_command(self.TEAM_ID, self.TRIGGER.lower(), self.URL+"/command")
116 res.update(self.CONFIG)
117 self.bot.api.update_slash_command(res)
118 self.mm_secret_token = res["token"]
121 def _require_bot_admin(self, data):
123 Require exactly bot admin priviledges.
124 Throws RequireException if not priviledged.
126 if not data["user_id"] in self.bot.admin_ids:
127 raise RequireException("### Leave me alone. You are not by real dad.")
130 def _require_system_admin(self, data, exc=True):
132 Require at least team admin priviledges.
133 Throws RequireException if not priviledged.
135 user = self.bot.api.get_user(data["user_id"])
136 if "system_admin" not in user["roles"]:
138 raise RequireException("### You are not SYSTEM_ADMIN. :(")
143 def _require_team_admin(self, data, exc=True):
145 Require at least team admin priviledges.
146 Throws RequireException if not priviledged.
148 team_member = self.bot.api.get_team_member(data["team_id"], data["user_id"])
149 if "team_admin" not in team_member["roles"] and not self._require_system_admin(data, exc=False):
151 raise RequireException("### You are not TEAM_ADMIN. :(")
156 def _require_channel_admin(self, data, exc=True):
158 Require at least channel admin priviledges.
159 Throws RequireException if not priviledged.
161 channel_member = self.bot.api.get_channel_member(data["channel_id"], data["user_id"])
162 if "channel_admin" not in channel_member["roles"] and not self._require_team_admin(data, exc=False):
164 raise RequireException("### You are not CHANNEL_ADMIN. :(")
169 def _require_not_guest(self, data, exc=True):
171 Require to not be a guest.
172 Throws RequireException if guest.
174 channel_member = self.bot.api.get_channel_member(data["channel_id"], data["user_id"])
175 if "channel_guest" in channel_member["roles"]:
177 raise RequireException("### The bot cannot be used by guests. :(")