X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=turbot%2Finteraction.py;h=d14c3d4ad07195aeefc916b9e0649ca664b9e98b;hb=ac83e42a735ae1098ebcec783b5f816369eb3917;hp=b50a6588129e9fbf04e117d7ec2a33ddefb70661;hpb=408a27119a549bba8e4e27f60f13354cf074359f;p=turbot diff --git a/turbot/interaction.py b/turbot/interaction.py index b50a658..d14c3d4 100644 --- a/turbot/interaction.py +++ b/turbot/interaction.py @@ -1,9 +1,9 @@ from slack.errors import SlackApiError from turbot.blocks import ( - input_block, section_block, text_block, multi_select_block + input_block, section_block, text_block, multi_select_block, checkbox_block ) from turbot.hunt import find_hunt_for_hunt_id, hunt_blocks -from turbot.puzzle import find_puzzle_for_url +from turbot.puzzle import find_puzzle_for_url, find_puzzle_for_puzzle_id import turbot.rot import turbot.sheets import turbot.slack @@ -16,10 +16,16 @@ from turbot.slack import slack_send_message import shlex actions = {} +actions['button'] = {} commands = {} submission_handlers = {} # Hunt/Puzzle IDs are restricted to lowercase letters, numbers, and underscores +# +# Note: This restriction not only allows for hunt and puzzle ID values to +# be used as Slack channel names, but it also allows for '-' as a valid +# separator between a hunt and a puzzle ID (for example in the puzzle +# edit dialog where a single attribute must capture both values). valid_id_re = r'^[_a-z0-9]+$' lambda_ok = {'statusCode': 200} @@ -63,6 +69,100 @@ def multi_static_select(turb, payload): actions['multi_static_select'] = {"*": multi_static_select} +def edit_puzzle(turb, payload): + """Handler for the action of user pressing an edit_puzzle button""" + + action_id = payload['actions'][0]['action_id'] + response_url = payload['response_url'] + trigger_id = payload['trigger_id'] + + (hunt_id, puzzle_id) = action_id.split('-', 1) + + puzzle = find_puzzle_for_puzzle_id(turb, hunt_id, puzzle_id) + + if not puzzle: + requests.post(response_url, + json = {"text": "Error: Puzzle not found!"}, + headers = {"Content-type": "application/json"}) + return bot_reply("Error: Puzzle not found.") + + round_options = hunt_rounds(turb, hunt_id) + + if len(round_options): + round_options_block = [ + multi_select_block("Round(s)", "rounds", + "Existing round(s) this puzzle belongs to", + round_options, + initial_options=puzzle.get("rounds", None)), + ] + else: + round_options_block = [] + + solved = False + if puzzle.get("status", "unsolved") == solved: + solved = True + + solution_str = None + solution_list = puzzle.get("solution", []) + if solution_list: + solution_str = ", ".join(solution_list) + + view = { + "type": "modal", + "private_metadata": json.dumps({ + "hunt_id": hunt_id, + "SK": puzzle["SK"], + "puzzle_id": puzzle_id, + "channel_id": puzzle["channel_id"], + "channel_url": puzzle["channel_url"], + "sheet_url": puzzle["sheet_url"], + }), + "title": {"type": "plain_text", "text": "Edit Puzzle"}, + "submit": { "type": "plain_text", "text": "Save" }, + "blocks": [ + input_block("Puzzle name", "name", "Name of the puzzle", + initial_value=puzzle["name"]), + input_block("Puzzle URL", "url", "External URL of puzzle", + initial_value=puzzle.get("url", None), + optional=True), + * round_options_block, + input_block("New round(s)", "new_rounds", + "New round(s) this puzzle belongs to " + + "(comma separated)", + optional=True), + input_block("State", "state", + "State of this puzzle (partial progress, next steps)", + initial_value=puzzle.get("state", None), + optional=True), + checkbox_block( + "Puzzle status", "Solved", "solved", + checked=(puzzle.get('status', 'unsolved') == 'solved')), + input_block("Solution", "solution", + "Solutions (comma-separated if multiple", + initial_value=solution_str, + optional=True), + ] + } + + result = turb.slack_client.views_open(trigger_id=trigger_id, + view=view) + + if (result['ok']): + submission_handlers[result['view']['id']] = edit_puzzle_submission + + return lambda_ok + +actions['button']['edit_puzzle'] = edit_puzzle + +def edit_puzzle_submission(turb, payload, metadata): + """Handler for the user submitting the edit puzzle modal + + This is the modal view presented to the user by the edit_puzzle + function above. + """ + + return lambda_ok + def new_hunt(turb, payload): """Handler for the action of user pressing the new_hunt button""" @@ -88,7 +188,7 @@ def new_hunt(turb, payload): return lambda_ok -actions['button'] = {"new_hunt": new_hunt} +actions['button']['new_hunt'] = new_hunt def new_hunt_submission(turb, payload, metadata): """Handler for the user submitting the new hunt modal @@ -600,7 +700,7 @@ def solved(turb, body, args): # And rename the sheet to suffix with "-SOLVED" turbot.sheets.renameSheet(turb, puzzle['sheet_url'], - puzzle['name'] + "-SOLVED") + puzzle['name'] + "-SOLVED") # Finally, rename the Slack channel to add the suffix '-solved' channel_name = "{}-{}-solved".format(