]> git.cworth.org Git - turbot/blobdiff - turbot/interaction.py
Implement a `/puzzle edit` command
[turbot] / turbot / interaction.py
index 69db52149d1eda35e3a62fda6b70b1184e0476ba..6e353c120e1ba3d2a8a5dbca4584b2aa3033f750 100644 (file)
@@ -75,7 +75,25 @@ def multi_static_select(turb, payload):
 
 actions['multi_static_select'] = {"*": multi_static_select}
 
-def edit_puzzle(turb, payload):
+def edit_puzzle_command(turb, body):
+    """Implementation of the `/puzzle edit` command
+
+    As dispatched from the puzzle() function.
+    """
+
+    channel_id = body['channel_id'][0]
+    trigger_id = body['trigger_id'][0]
+
+    puzzle = puzzle_for_channel(turb, channel_id)
+
+    if not puzzle:
+        return bot_reply("Sorry, this does not appear to be a puzzle channel.")
+
+    return edit_puzzle(turb, puzzle, trigger_id)
+
+    return lambda_ok
+
+def edit_puzzle_button(turb, payload):
     """Handler for the action of user pressing an edit_puzzle button"""
 
     action_id = payload['actions'][0]['action_id']
@@ -92,7 +110,18 @@ def edit_puzzle(turb, payload):
                       headers = {"Content-type": "application/json"})
         return bot_reply("Error: Puzzle not found.")
 
-    round_options = hunt_rounds(turb, hunt_id)
+    return edit_puzzle(turb, puzzle, trigger_id)
+
+actions['button']['edit_puzzle'] = edit_puzzle_button
+
+def edit_puzzle(turb, puzzle, trigger_id):
+    """Common code for implementing an edit puzzle dialog
+
+    This implementation is common whether the edit operation was invoked
+    by a button (edit_puzzle_button) or a command (edit_puzzle_command).
+    """
+
+    round_options = hunt_rounds(turb, puzzle['hunt_id'])
 
     if len(round_options):
         round_options_block = [
@@ -116,9 +145,9 @@ def edit_puzzle(turb, payload):
     view = {
         "type": "modal",
         "private_metadata": json.dumps({
-            "hunt_id": hunt_id,
+            "hunt_id": puzzle['hunt_id'],
             "SK": puzzle["SK"],
-            "puzzle_id": puzzle_id,
+            "puzzle_id": puzzle['puzzle_id'],
             "channel_id": puzzle["channel_id"],
             "channel_url": puzzle["channel_url"],
             "sheet_url": puzzle["sheet_url"],
@@ -158,8 +187,6 @@ def edit_puzzle(turb, payload):
 
     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
 
@@ -179,6 +206,7 @@ def edit_puzzle_submission(turb, payload, metadata):
     puzzle['sheet_url'] = meta['sheet_url']
 
     state = payload['view']['state']['values']
+    user_id = payload['user']['id']
 
     puzzle['name'] = state['name']['name']['value']
     url = state['url']['url']['value']
@@ -238,6 +266,27 @@ def edit_puzzle_submission(turb, payload, metadata):
     # Update the puzzle in the database
     turb.table.put_item(Item=puzzle)
 
+    # Inform the puzzle channel about the edit
+    edit_message = "Puzzle edited by <@{}>".format(user_id)
+    blocks = ([section_block(text_block(edit_message+":\n"))] +
+              puzzle_blocks(puzzle, include_rounds=True))
+    slack_send_message(
+        turb.slack_client, puzzle['channel_id'],
+        edit_message, blocks=blocks)
+
+    # Also inform the hunt if the puzzle's solved status changed
+    if puzzle['status'] != old_puzzle['status']:
+        hunt = find_hunt_for_hunt_id(turb, puzzle['hunt_id'])
+        if puzzle['status'] == 'solved':
+            message = "Puzzle <{}|{}> has been solved!".format(
+                puzzle['channel_url'],
+                puzzle['name'])
+        else:
+            message = "Oops. Puzzle <{}|{}> has been marked unsolved!".format(
+                puzzle['channel_url'],
+                puzzle['name'])
+        slack_send_message(turb.slack_client, hunt['channel_id'], message)
+
     # We need to set the channel topic if any of puzzle name, url,
     # state, status, or solution, has changed. Let's just do that
     # unconditionally here.
@@ -551,6 +600,8 @@ def puzzle(turb, body, args):
 
         /puzzle new: Bring up a dialog to create a new puzzle
 
+        /puzzle edit: Edit the puzzle for the current channel
+
     Or with no argument at all:
 
         /puzzle: Print details of the current puzzle (if in a puzzle channel)
@@ -559,9 +610,14 @@ def puzzle(turb, body, args):
     if args == 'new':
         return new_puzzle(turb, body)
 
+    if args == 'edit':
+        return edit_puzzle_command(turb, body)
+
     if len(args):
         return bot_reply("Unknown syntax for `/puzzle` command. " +
-                         "Use `/puzzle new` to create a new puzzle.")
+                         "Valid commands are: `/puzzle`, `/puzzle edit`, " +
+                         "and `/puzzle new` to display, edit, or create " +
+                         "a puzzle.")
 
     # For no arguments we print the current puzzle as a reply
     channel_id = body['channel_id'][0]
@@ -581,7 +637,7 @@ def puzzle(turb, body, args):
                 "Sorry, this channel doesn't appear to be a hunt or a puzzle "
                 + "channel, so the `/puzzle` command cannot work here.")
 
-    blocks = puzzle_blocks(puzzle)
+    blocks = puzzle_blocks(puzzle, include_rounds=True)
 
     requests.post(response_url,
                   json = {'blocks': blocks},