From 3201514c9991ffcd1ceefa57ce180a095af7ba0a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 16 Oct 2020 13:22:15 -0700 Subject: [PATCH] Handle the submission of the "New Hunt" modal By creating a new entry in the hunts table. As part of this change we rework turbot/views.py so that the block functions it had are now in turbot/blocks.py (where they are usefully shared). Meanwhile, the actual views that were being created are now created above in events.py, actions.py, etc. where they can be associated with functions to handle the submission of those views, etc. --- turbot/actions.py | 67 +++++++++++++++++++++++++-- turbot/blocks.py | 48 +++++++++++++++++++ turbot/events.py | 27 ++++++++++- turbot/views.py | 84 ---------------------------------- turbot_lambda/turbot_lambda.py | 3 +- 5 files changed, 137 insertions(+), 92 deletions(-) create mode 100644 turbot/blocks.py delete mode 100644 turbot/views.py diff --git a/turbot/actions.py b/turbot/actions.py index c68de14..bf64c73 100644 --- a/turbot/actions.py +++ b/turbot/actions.py @@ -1,17 +1,74 @@ -import turbot.views +from turbot.blocks import input_block +import uuid + +submission_handlers = {} def new_hunt(turb, payload): + """Handler for the action of user pressing the new_hunt button""" + + view = { + "type": "modal", + "title": { "type": "plain_text", "text": "New Hunt" }, + "submit": { "type": "plain_text", "text": "Create" }, + "blocks": [ + input_block("Hunt name", "name", "Name of the hunt"), + input_block("Hunt ID", "slug", "Short prefix for hunt (no spaces)"), + input_block("Hunt URL", "url", "External URL of hunt") + ], + } - print("In new_hunt function") - view = turbot.views.new_hunt() - turb.slack_client.views_open(trigger_id=payload['trigger_id'], - view=view) + result = turb.slack_client.views_open(trigger_id=payload['trigger_id'], + view=view) + if (result['ok']): + submission_handlers[result['view']['id']] = new_hunt_submission return { 'statusCode': 200, 'body': 'OK' } +def new_hunt_submission(turb, payload): + """Handler for the user submitting the new hunt modal + + This is the modal view presented to the user by the new_hunt + function above.""" + + state = payload['view']['state']['values'] + name = state['name']['name']['value'] + slug = state['slug']['slug']['value'] + url = state['url']['url']['value'] + + table = turb.db.Table("hunts") + table.put_item( + Item={ + 'channel_id': "placeholder-" + str(uuid.uuid4()), + "active": True, + "name": name, + "slug": slug, + "url": url + } + ) + + return { + 'statusCode': 200, + } + +def view_submission(turb, payload): + + """Handler for Slack interactive view submission + + Specifically, those that have a payload type of 'view_submission'""" + + view_id = payload['view']['id'] + + if view_id in submission_handlers: + return submission_handlers[view_id](turb, payload) + + print("Error: Unknown view ID: {}".format(view_id)) + return { + 'statusCode': 400 + } + actions = { "button": { "new_hunt": new_hunt diff --git a/turbot/blocks.py b/turbot/blocks.py new file mode 100644 index 0000000..5222e87 --- /dev/null +++ b/turbot/blocks.py @@ -0,0 +1,48 @@ +def text_block(body): + return { + "text": { + "type": "mrkdwn", + "text": body + } + } + +def section_block(block): + return { + "type": "section", + **block + } + +def actions_block(*elements): + return { + "type": "actions", + "elements": list(elements) + } + +def button_block(label, name): + return { + "type": "button", + "text": { + "type": "plain_text", + "text": label, + "emoji": True + }, + "value": name + } + +def input_block(label, name, placeholder): + return { + "type": "input", + "block_id": name, + "element": { + "type": "plain_text_input", + "action_id": name, + "placeholder": { + "type": "plain_text", + "text": placeholder, + } + }, + "label": { + "type": "plain_text", + "text": label + } + } diff --git a/turbot/events.py b/turbot/events.py index be14295..dfe4cb9 100644 --- a/turbot/events.py +++ b/turbot/events.py @@ -1,8 +1,31 @@ -import turbot.views +from turbot.blocks import section_block, text_block, button_block, actions_block + +def hunt_block(hunt): + text = "{}: <#{}>".format(hunt['name'], hunt['channel_id']) + return section_block(text_block(text)) + +def home(turb, user_id, body): + """Returns a view to be published as the turbot home tab for user_id + + The body argument is a dictionary as provided by the Slack request. + The return value is a dictionary suitable to be published to the + Slack views_publish API.""" + + response = turb.db.Table("hunts").scan() + hunts = response['Items'] + + return { + "type": "home", + "blocks": [ + section_block(text_block("*Active hunts*")), + *[hunt_block(hunt) for hunt in hunts if hunt['active']], + actions_block(button_block("New hunt", "new_hunt")) + ] + } def app_home_opened(turb, body): user_id = body['event']['user'] - view = turbot.views.home(turb, user_id, body) + view = home(turb, user_id, body) turb.slack_client.views_publish(user_id=user_id, view=view) return "OK" diff --git a/turbot/views.py b/turbot/views.py deleted file mode 100644 index e05593d..0000000 --- a/turbot/views.py +++ /dev/null @@ -1,84 +0,0 @@ -def text_block(body): - return { - "text": { - "type": "mrkdwn", - "text": body - } - } - -def section(block): - return { - "type": "section", - **block - } - -def actions(*elements): - return { - "type": "actions", - "elements": list(elements) - } - -def button(label, name): - return { - "type": "button", - "text": { - "type": "plain_text", - "text": label, - "emoji": True - }, - "value": name - } - -def input(label, name, placeholder): - return { - "type": "input", - "element": { - "type": "plain_text_input", - "action_id": name, - "placeholder": { - "type": "plain_text", - "text": placeholder, - } - }, - "label": { - "type": "plain_text", - "text": label - } - } - -def hunt_block(hunt): - text = "{}: <#{}>".format(hunt['name'], hunt['channel_id']) - return section(text_block(text)) - -def home(turb, user_id, body): - """Returns a view to be published as the turbot home tab for user_id - - The body argument is a dictionary as provided by the Slack request. - The return value is a dictionary suitable to be published to the - Slack views_publish API.""" - - response = turb.db.Table("hunts").scan() - hunts = response['Items'] - - return { - "type": "home", - "blocks": [ - section(text_block("*Active hunts*")), - *[hunt_block(hunt) for hunt in hunts if hunt['active']], - actions(button("New hunt", "new_hunt")) - ] - } - -def new_hunt(): - """Returns a view to be published as the new_hunt modal""" - - return { - "type": "modal", - "title": { "type": "plain_text", "text": "New Hunt" }, - "submit": { "type": "plain_text", "text": "Create" }, - "blocks": [ - input("Hunt name", "name", "Name of the hunt"), - input("Hunt ID", "slug", "Short prefix for hunt (no spaces)"), - input("Hunt URL", "url", "External URL of hunt") - ] - } diff --git a/turbot_lambda/turbot_lambda.py b/turbot_lambda/turbot_lambda.py index 113e639..9d878af 100644 --- a/turbot_lambda/turbot_lambda.py +++ b/turbot_lambda/turbot_lambda.py @@ -9,7 +9,6 @@ from types import SimpleNamespace import turbot.actions import turbot.commands import turbot.events -import turbot.views ssm = boto3.client('ssm') @@ -138,6 +137,8 @@ def turbot_interactive(turb, payload): if type == 'block_actions': return turbot_block_action(turb, payload) + if type == 'view_submission': + return turbot.actions.view_submission(turb, payload) return error("Unrecognized interactive type: {}".format(type)) def turbot_block_action(turb, payload): -- 2.45.2