]> git.somenet.org - pub/jan/mattermost-bot.git/blob - core/AbstractCommand.py
README.md
[pub/jan/mattermost-bot.git] / core / AbstractCommand.py
1 # Mattermost Bot.
2 #  Copyright (c) 2016-2022 by Someone <someone@somenet.org> (aka. Jan Vales <jan@jvales.net>)
3 #  published under MIT-License
4
5
6 class RequireException(Exception):
7     """Required precondition not met-exception. Mostly used for permission checks. Message will be forwarded to command-caller/user"""
8
9
10 class AbstractCommand():
11     URL = None
12     TEAM_ID = None
13     TRIGGER = None
14     CONFIG = {"display_name": "somebot-command", "auto_complete": True}
15     USEINFO = None
16
17     bot = None
18     mm_secret_token = None
19
20
21     def __init__(self, team_id):
22         self.TEAM_ID = team_id
23
24     def __str__(self):
25         return str(self.__class__)+" for team_id: "+str(self.TEAM_ID)
26
27     def __repr__(self):
28         return self.__str__()
29
30
31     # can/should be overridden by the user
32     def on_register(self):
33         """Consider to override. Handles the post-command-registration logic at bot startup."""
34         self._create_slash_command()
35
36     # can/should be overridden by the user
37     def on_shutdown(self):
38         """Consider to override. Handles the shutdown-procedure."""
39         return
40
41     # can/should be overridden by the user
42     def on_SIGUSR1(self, sigusr1_cnt):
43         """Consider to override. Handles the SIGUSR1-signal."""
44         return
45
46     # should be overridden by the user
47     def on_POST(self, request, data):
48         """Override. Handles the post-command logic."""
49         return
50
51     # should be overridden by the user
52     # manual command authentication needed!
53     def on_POST_interactive(self, request, data):
54         """Consider to override. Handles the interactive-message logic."""
55         return
56
57     # should be overridden by the user
58     # manual command authentication needed!
59     def on_POST_dialog(self, request, data):
60         """Consider to override. Handles the dialog logic."""
61         return
62
63
64     def _on_register(self, bot):
65         self.bot = bot
66         self.URL = self.bot.local_websrv_url+"/"+self.TEAM_ID+"/"+self.TRIGGER
67         if self.USEINFO:
68             self.bot.USETOPICS.setdefault("/"+self.TRIGGER, self.USEINFO)
69         self.on_register()
70
71
72     def _on_shutdown(self):
73         self.on_shutdown()
74
75
76     def _on_SIGUSR1(self, sigusr1_cnt):
77         self.on_SIGUSR1(sigusr1_cnt)
78
79
80     def _on_POST(self, request, data):
81         try:
82             self._require_not_guest(data)
83             self.on_POST(request, data)
84         except RequireException as ex:
85             request.respond_cmd_err(str(ex))
86
87
88     def _on_POST_interactive(self, request, data):
89         try:
90             self._require_not_guest(data)
91             self.on_POST_interactive(request, data)
92         except RequireException as ex:
93             request.respond_cmd_err(str(ex))
94
95
96     def _on_POST_dialog(self, request, data):
97         try:
98             self._require_not_guest(data)
99             self.on_POST_dialog(request, data)
100         except RequireException as ex:
101             request.respond_cmd_err(str(ex))
102
103
104     def _create_slash_command(self):
105         # (possibly) delete old version of command
106         for command in self.bot.api.list_custom_slash_commands_for_team(self.TEAM_ID):
107             if command["url"] == self.URL or command["trigger"].lower() == self.TRIGGER.lower():
108                 self.bot.api.delete_slash_command(command["id"])
109
110         # create slash command
111         res = self.bot.api.create_slash_command(self.TEAM_ID, self.TRIGGER.lower(), self.URL+"/command")
112         res.update(self.CONFIG)
113         self.bot.api.update_slash_command(res)
114         self.mm_secret_token = res["token"]
115
116
117     def _require_bot_admin(self, data):
118         """
119         Require exactly bot admin priviledges.
120         Throws RequireException if not priviledged.
121         """
122         if not data["user_id"] in self.bot.admin_ids:
123             raise RequireException("### Leave me alone. You are not by real dad.")
124
125
126     def _require_system_admin(self, data, exc=True):
127         """
128         Require at least team admin priviledges.
129         Throws RequireException if not priviledged.
130         """
131         user = self.bot.api.get_user(data["user_id"])
132         if "system_admin" not in user["roles"]:
133             if exc:
134                 raise RequireException("### You are not SYSTEM_ADMIN. :(")
135             return False
136         return True
137
138
139     def _require_team_admin(self, data, exc=True):
140         """
141         Require at least team admin priviledges.
142         Throws RequireException if not priviledged.
143         """
144         team_member = self.bot.api.get_team_member(data["team_id"], data["user_id"])
145         if "team_admin" not in team_member["roles"] and not self._require_system_admin(data, exc=False):
146             if exc:
147                 raise RequireException("### You are not TEAM_ADMIN. :(")
148             return False
149         return True
150
151
152     def _require_channel_admin(self, data, exc=True):
153         """
154         Require at least channel admin priviledges.
155         Throws RequireException if not priviledged.
156         """
157         channel_member = self.bot.api.get_channel_member(data["channel_id"], data["user_id"])
158         if "channel_admin" not in channel_member["roles"] and not self._require_team_admin(data, exc=False):
159             if exc:
160                 raise RequireException("### You are not CHANNEL_ADMIN. :(")
161             return False
162         return True
163
164
165     def _require_not_guest(self, data, exc=True):
166         """
167         Require to not be a guest.
168         Throws RequireException if guest.
169         """
170         channel_member = self.bot.api.get_channel_member(data["channel_id"], data["user_id"])
171         if "channel_guest" in channel_member["roles"]:
172             if exc:
173                 raise RequireException("### The bot cannot be used by guests. :(")
174             return False
175         return True