Skip to content

Commit b2334ef

Browse files
committed
Pull out Slack API exception handler and refactor /roll
1 parent 49caa35 commit b2334ef

3 files changed

Lines changed: 66 additions & 66 deletions

File tree

pybot/endpoints/slack/commands.py

Lines changed: 22 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import functools
21
import logging
32
import random
43

54
from sirbot import SirBot
65
from sirbot.plugins.slack import SlackPlugin
76
from slack import methods
87
from slack.commands import Command
9-
from slack.exceptions import SlackAPIError
108

119
from pybot.endpoints.slack.message_templates.commands import (
1210
ticket_dialog,
@@ -23,6 +21,7 @@
2321
get_slash_here_messages,
2422
get_slash_repeat_messages,
2523
)
24+
from pybot.endpoints.slack.utils.general_utils import catch_command_slack_error
2625
from pybot.endpoints.slack.utils.slash_lunch import LunchCommand
2726

2827
logger = logging.getLogger(__name__)
@@ -38,43 +37,7 @@ def create_endpoints(plugin: SlackPlugin):
3837
# plugin.on_command('/mentor', slash_mentor, wait=False)
3938

4039

41-
def catch_slack_error(func):
42-
"""
43-
Decorator for wrapping/catching exceptions thrown by
44-
the slack client and displaying an error to the user.
45-
46-
Only necessary (for now) for functions that post messages to
47-
slack channels
48-
"""
49-
50-
@functools.wraps(func)
51-
async def handler(command: Command, app: SirBot, *args, **kwargs):
52-
try:
53-
await func(command, app, *args, **kwargs)
54-
55-
except SlackAPIError:
56-
channel_id = command["channel_id"]
57-
slash_command = command["command"]
58-
slack_id = command["user_id"]
59-
slack = app["plugins"]["slack"]
60-
61-
await slack.api.query(
62-
methods.CHAT_POST_EPHEMERAL,
63-
dict(
64-
user=slack_id,
65-
channel=slack_id,
66-
as_user=True,
67-
text=(
68-
f"Could not post result of `{slash_command}` "
69-
f"to channel <#{channel_id}>"
70-
),
71-
),
72-
)
73-
74-
return handler
75-
76-
77-
@catch_slack_error
40+
@catch_command_slack_error
7841
async def slash_mentor(command: Command, app: SirBot):
7942
airtable = app.plugins["airtable"].api
8043
services = await airtable.get_all_records("Services", "Name")
@@ -87,7 +50,7 @@ async def slash_mentor(command: Command, app: SirBot):
8750
await app.plugins["slack"].api.query(methods.CHAT_POST_MESSAGE, response)
8851

8952

90-
@catch_slack_error
53+
@catch_command_slack_error
9154
async def slash_ticket(command: Command, app: SirBot):
9255
trigger_id = command["trigger_id"]
9356
user_id = command["user_id"]
@@ -106,7 +69,7 @@ async def slash_ticket(command: Command, app: SirBot):
10669
await app.plugins["slack"].api.query(methods.DIALOG_OPEN, response)
10770

10871

109-
@catch_slack_error
72+
@catch_command_slack_error
11073
async def slash_report(command: Command, app: SirBot):
11174
"""
11275
Sends text supplied with the /report command to the moderators channel along
@@ -128,7 +91,7 @@ async def slash_report(command: Command, app: SirBot):
12891
await slack.query(methods.CHAT_POST_MESSAGE, response)
12992

13093

131-
@catch_slack_error
94+
@catch_command_slack_error
13295
async def slash_here(command: Command, app: SirBot):
13396
"""
13497
/here allows admins to give non-admins the ability to use @here-esque functionality for specific channels.
@@ -143,7 +106,7 @@ async def slash_here(command: Command, app: SirBot):
143106

144107
logger.debug(f"/here params: {params}, /here headers {headers}")
145108
async with app.http_session.get(
146-
f"http://{PYBACK_HOST}:{PYBACK_PORT}/api/mods/", params=params, headers=headers
109+
f"http://{PYBACK_HOST}:{PYBACK_PORT}/api/mods/", params=params, headers=headers
147110
) as r:
148111

149112
logger.debug(f"pyback response status: {r.status}")
@@ -169,7 +132,7 @@ async def slash_here(command: Command, app: SirBot):
169132
)
170133

171134

172-
@catch_slack_error
135+
@catch_command_slack_error
173136
async def slash_lunch(command: Command, app: SirBot):
174137
"""
175138
Provides the user with a random restaurant in their area.
@@ -192,7 +155,7 @@ async def slash_lunch(command: Command, app: SirBot):
192155
await slack.query(methods.CHAT_POST_EPHEMERAL, message_params)
193156

194157

195-
@catch_slack_error
158+
@catch_command_slack_error
196159
async def slash_repeat(command: Command, app: SirBot):
197160
logger.info(f"repeat command data incoming {command}")
198161
channel_id = command["channel_id"]
@@ -206,23 +169,23 @@ async def slash_repeat(command: Command, app: SirBot):
206169
await slack.query(method_type, message)
207170

208171

209-
@catch_slack_error
172+
@catch_command_slack_error
210173
async def slash_roll(command: Command, app: SirBot):
174+
"""
175+
Invoked via the command /roll XdY, where X is an integer between 1 and 10,
176+
and y is an integer between 1 and 20.
177+
178+
Parses the number of dice and the type from the command
179+
"""
180+
slack = app["plugins"]["slack"].api
211181
slack_id = command["user_id"]
212182
channel_id = command["channel_id"]
213183
text = command["text"]
214184

215-
slack = app["plugins"]["slack"].api
216-
217-
# parse the type of die and number to roll
218185
try:
219186
text = text.lower()
220-
numdice, typedice = text.split("d")
221-
numdice = int(numdice)
222-
typedice = int(typedice)
223-
if numdice <= 0 or numdice > 10:
224-
raise ValueError
225-
if typedice <= 0 or typedice > 20:
187+
numdice, typedice = [int(num) for num in text.split("d")]
188+
if numdice <= 0 or numdice > 10 or typedice <= 0 or typedice > 20:
226189
raise ValueError
227190
except ValueError:
228191
logger.debug("invalid input to roll: %s", text)
@@ -234,14 +197,9 @@ async def slash_roll(command: Command, app: SirBot):
234197
"Should be XDYY where X is the number of dice, and YY is the number of sides"
235198
),
236199
)
237-
await slack.query(methods.CHAT_POST_EPHEMERAL, response)
238-
239-
return
240-
dice = []
241-
for _ in range(0, numdice):
242-
dice.append(random.randint(1, typedice + 1))
200+
return await slack.query(methods.CHAT_POST_EPHEMERAL, response)
243201

202+
dice = [random.randint(1, typedice + 1) for _ in range(numdice)]
244203
message = f"<@{slack_id}> Rolled {numdice} D{typedice}: {dice}"
245-
await slack.query(
246-
methods.CHAT_POST_MESSAGE, {"channel": channel_id, "text": message}
247-
)
204+
response = dict(channel=channel_id, text=message)
205+
await slack.query(methods.CHAT_POST_MESSAGE, response)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import functools
2+
3+
from sirbot import SirBot
4+
from slack.methods import Methods
5+
from slack.commands import Command
6+
from slack.exceptions import SlackAPIError
7+
8+
9+
def catch_command_slack_error(func):
10+
"""
11+
Decorator for wrapping/catching exceptions thrown by
12+
the slack client and displaying an error to the user.
13+
14+
Only necessary (for now) for functions that post messages to
15+
slack channels
16+
"""
17+
18+
@functools.wraps(func)
19+
async def handler(command: Command, app: SirBot, *args, **kwargs):
20+
try:
21+
await func(command, app, *args, **kwargs)
22+
23+
except SlackAPIError:
24+
channel_id = command["channel_id"]
25+
slash_command = command["command"]
26+
slack_id = command["user_id"]
27+
slack = app["plugins"]["slack"]
28+
29+
await slack.api.query(
30+
Methods.CHAT_POST_EPHEMERAL,
31+
dict(
32+
user=slack_id,
33+
channel=slack_id,
34+
as_user=True,
35+
text=(
36+
f"Could not post result of `{slash_command}` "
37+
f"to channel <#{channel_id}>"
38+
),
39+
),
40+
)
41+
42+
return handler

pybot/endpoints/slack/utils/slash_lunch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ def _build_response_text(self, loc_dict: dict) -> dict:
7171
"user": self.user_id,
7272
"channel": self.channel_id,
7373
"text": (
74-
f'The Wheel of Lunch has selected {loc_dict["name"]} '
75-
+ f'at {" ".join(loc_dict["location"]["display_address"])}'
74+
f'The Wheel of Lunch has selected {loc_dict["name"]} '
75+
+ f'at {" ".join(loc_dict["location"]["display_address"])}'
7676
),
7777
}
7878

0 commit comments

Comments
 (0)