Skip to content

Commit e441129

Browse files
committed
fix(slack-api): handle slash commands acknowledgents and invalid slash command error message
1 parent 19c5992 commit e441129

File tree

2 files changed

+93
-14
lines changed

2 files changed

+93
-14
lines changed

llmstack/apps/apis.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,15 @@ def run(self, request, uid, session_id=None, platform=None):
807807
)
808808
response.is_async = True
809809
return response
810+
if request.data.get("command"):
811+
return DRFResponse(
812+
result["message"],
813+
status=200,
814+
headers={
815+
"Content-Security-Policy": result["csp"] if "csp" in result else "frame-ancestors self",
816+
},
817+
)
818+
810819
response_body = {k: v for k, v in result.items() if k != "csp"}
811820
response_body["_id"] = request_uuid
812821
return DRFResponse(

llmstack/apps/handlers/slack_app.py

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ def __init__(self, *args, **kwargs):
5454
self._slack_user = {}
5555
self._slack_user_email = ""
5656

57+
# the request type should be either url_verification or event_callback
58+
self._request_type = self.request.data.get("type")
59+
self._is_valid_request_type = self._request_type in ["url_verification", "event_callback"]
60+
self._is_valid_app_token = self.request.data.get("token") == self.slack_config.get("verification_token")
61+
self._is_valid_app_id = self.request.data.get("api_app_id") == self.slack_config.get("app_id")
62+
63+
self._request_slash_command = self.request.data.get("command")
64+
self._configured_slash_command = self.slack_config.get("slash_command_name")
65+
66+
is_valid_slash_command = False
67+
if self._request_slash_command and self._configured_slash_command:
68+
is_valid_slash_command = self._request_slash_command == self._configured_slash_command
69+
70+
self._is_valid_slash_command = is_valid_slash_command
71+
5772
def app_init(self):
5873
self.slack_config = (
5974
SlackIntegrationConfig().from_dict(
@@ -220,30 +235,33 @@ def _is_app_accessible(self):
220235
):
221236
raise Exception("Invalid Slack request")
222237

223-
request_type = self.request.data.get("type")
238+
if not self._is_valid_app_token:
239+
raise Exception("Invalid App Token")
224240

225-
# the request type should be either url_verification or event_callback
226-
is_valid_request_type = request_type in ["url_verification", "event_callback"]
227-
is_valid_app_token = self.request.data.get("token") == self.slack_config.get("verification_token")
228-
is_valid_app_id = self.request.data.get("api_app_id") == self.slack_config.get("app_id")
241+
elif not self._is_valid_app_id:
242+
raise Exception("Invalid App ID")
229243

230-
is_valid_slash_command = False
231-
if self.request.data.get("command") and self.slack_config.get("slash_command_name"):
232-
request_slash_command = self.request.data.get("command")
233-
configured_slash_command = self.slack_config.get("slash_command_name")
234-
is_valid_slash_command = request_slash_command == configured_slash_command
244+
elif self._request_slash_command and not self._is_valid_slash_command:
245+
raise Exception("Invalid Slash Command")
246+
247+
elif self._request_type and not self._is_valid_request_type:
248+
raise Exception("Invalid Slack request type. Only url_verification and event_callback are allowed.")
235249

236250
# Validate that the app token, app ID and the request type are all valid.
237-
if not (is_valid_app_token and is_valid_app_id and (is_valid_request_type or is_valid_slash_command)):
251+
elif not (
252+
self._is_valid_app_token
253+
and self._is_valid_app_id
254+
and (self._is_valid_request_type or self._is_valid_slash_command)
255+
):
238256
raise Exception("Invalid Slack request")
239257

240258
# URL verification is allowed without any further checks
241-
if request_type == "url_verification":
259+
if self._request_type == "url_verification":
242260
return True
243261

244262
# Verify the request is coming from the app we expect and the event
245263
# type is app_mention
246-
elif request_type == "event_callback":
264+
elif self._request_type == "event_callback":
247265
event_data = self.request.data.get("event") or {}
248266
event_type = event_data.get("type")
249267
channel_type = event_data.get("channel_type")
@@ -255,7 +273,7 @@ def _is_app_accessible(self):
255273
# Only allow direct messages from users and not from bots
256274
if channel_type == "im" and "subtype" not in event_data and "bot_id" not in event_data:
257275
return True
258-
raise Exception("Invalid Slack request")
276+
raise Exception("Invalid Slack event_callback request")
259277

260278
return super()._is_app_accessible()
261279

@@ -401,3 +419,55 @@ def _get_actor_configs(
401419
self._get_bookkeeping_actor_config(processor_configs),
402420
)
403421
return actor_configs
422+
423+
def run_app(self):
424+
# Check if the app access permissions are valid
425+
self._is_app_accessible()
426+
427+
csp = self._get_csp()
428+
429+
template = convert_template_vars_from_legacy_format(
430+
self.app_data["output_template"].get(
431+
"markdown",
432+
"",
433+
)
434+
if self.app_data and "output_template" in self.app_data
435+
else self.app.output_template.get(
436+
"markdown",
437+
"",
438+
),
439+
)
440+
processor_actor_configs, processor_configs = self._get_processor_actor_configs()
441+
actor_configs = self._get_actor_configs(
442+
template,
443+
processor_configs,
444+
processor_actor_configs,
445+
)
446+
447+
if self.app.type.slug == "agent":
448+
self._start_agent(
449+
self._get_input_data(),
450+
self.app_session,
451+
actor_configs,
452+
csp,
453+
template,
454+
processor_configs,
455+
)
456+
else:
457+
self._start(
458+
self._get_input_data(),
459+
self.app_session,
460+
actor_configs,
461+
csp,
462+
template,
463+
)
464+
465+
message = ""
466+
if self._is_valid_slash_command:
467+
message = f"Processing the Command - `{self.request.data.get('command')} {self.request.data.get('text')}`"
468+
elif self._request_slash_command and not self._is_valid_slash_command:
469+
message = f"Invalid Slack Command - `{self.request.data.get('command')}`"
470+
471+
return {
472+
"message": message,
473+
}

0 commit comments

Comments
 (0)