]> git.cworth.org Git - turbot/blobdiff - turbot/interaction.py
Add display of round(s) in /puzzle output
[turbot] / turbot / interaction.py
index 0b2f30eec9324c9ba8689a266d9f3ad683e2fd78..955fae5b776f15db7222e7a5e3a0cbe81ec4f0c0 100644 (file)
@@ -7,7 +7,8 @@ from turbot.puzzle import (
     find_puzzle_for_url,
     find_puzzle_for_puzzle_id,
     puzzle_update_channel_and_sheet,
-    puzzle_id_from_name
+    puzzle_id_from_name,
+    puzzle_blocks
 )
 import turbot.rot
 import turbot.sheets
@@ -229,13 +230,18 @@ def edit_puzzle_submission(turb, payload, metadata):
                 }
             )
 
+    # Get old puzzle from the database (to determine what's changed)
+    old_puzzle = find_puzzle_for_puzzle_id(turb,
+                                           puzzle['hunt_id'],
+                                           puzzle['puzzle_id'])
+
     # Update the puzzle in the database
     turb.table.put_item(Item=puzzle)
 
     # 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.
-    puzzle_update_channel_and_sheet(turb, puzzle)
+    puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=old_puzzle)
 
     return lambda_ok
 
@@ -541,8 +547,56 @@ def hunt_rounds(turb, hunt_id):
 def puzzle(turb, body, args):
     """Implementation of the /puzzle command
 
-    The args string is currently ignored (this command will bring up
-    a modal dialog for user input instead)."""
+    The args string can be a sub-command:
+
+        /puzzle new: Bring up a dialog to create a new puzzle
+
+    Or with no argument at all:
+
+        /puzzle: Print details of the current puzzle (if in a puzzle channel)
+    """
+
+    if args == 'new':
+        return new_puzzle(turb, body)
+
+    if len(args):
+        return bot_reply("Unknown syntax for `/puzzle` command. " +
+                         "Use `/puzzle new` to create a new puzzle.")
+
+    # For no arguments we print the current puzzle as a reply
+    channel_id = body['channel_id'][0]
+    response_url = body['response_url'][0]
+
+    puzzle = puzzle_for_channel(turb, channel_id)
+
+    if not puzzle:
+        hunt = hunt_for_channel(turb, channel_id)
+        if hunt:
+            return bot_reply(
+                "This is not a puzzle channel, but is a hunt channel. "
+                + "If you want to create a new puzzle for this hunt, use "
+                + "`/puzzle new`.")
+        else:
+            return bot_reply(
+                "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, include_rounds=True)
+
+    requests.post(response_url,
+                  json = {'blocks': blocks},
+                  headers = {'Content-type': 'application/json'}
+                  )
+
+    return lambda_ok
+
+commands["/puzzle"] = puzzle
+
+def new_puzzle(turb, body):
+    """Implementation of the "/puzzle new" command
+
+    This brings up a dialog box for creating a new puzzle.
+    """
 
     channel_id = body['channel_id'][0]
     trigger_id = body['trigger_id'][0]
@@ -588,17 +642,16 @@ def puzzle(turb, body, args):
                                           view=view)
 
     if (result['ok']):
-        submission_handlers[result['view']['id']] = puzzle_submission
+        submission_handlers[result['view']['id']] = new_puzzle_submission
 
     return lambda_ok
 
-commands["/puzzle"] = puzzle
-
-def puzzle_submission(turb, payload, metadata):
+def new_puzzle_submission(turb, payload, metadata):
     """Handler for the user submitting the new puzzle modal
 
-    This is the modal view presented to the user by the puzzle function
-    above."""
+    This is the modal view presented to the user by the new_puzzle
+    function above.
+    """
 
     # First, read all the various data from the request
     meta = json.loads(metadata)
@@ -682,17 +735,20 @@ def state(turb, body, args):
 
     channel_id = body['channel_id'][0]
 
-    puzzle = puzzle_for_channel(turb, channel_id)
+    old_puzzle = puzzle_for_channel(turb, channel_id)
 
-    if not puzzle:
+    if not old_puzzle:
         return bot_reply(
             "Sorry, the /state command only works in a puzzle channel")
 
-    # Set the state field in the database
+    # Make a copy of the puzzle object
+    puzzle = old_puzzle.copy()
+
+    # Update the puzzle in the database
     puzzle['state'] = args
     turb.table.put_item(Item=puzzle)
 
-    puzzle_update_channel_and_sheet(turb, puzzle)
+    puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=old_puzzle)
 
     return lambda_ok
 
@@ -706,15 +762,18 @@ def solved(turb, body, args):
     channel_id = body['channel_id'][0]
     user_name = body['user_name'][0]
 
-    puzzle = puzzle_for_channel(turb, channel_id)
+    old_puzzle = puzzle_for_channel(turb, channel_id)
 
-    if not puzzle:
+    if not old_puzzle:
         return bot_reply("Sorry, this is not a puzzle channel.")
 
     if not args:
         return bot_reply(
             "Error, no solution provided. Usage: `/solved SOLUTION HERE`")
 
+    # Make a copy of the puzzle object
+    puzzle = old_puzzle.copy()
+
     # Set the status and solution fields in the database
     puzzle['status'] = 'solved'
     puzzle['solution'].append(args)
@@ -737,7 +796,7 @@ def solved(turb, body, args):
     )
 
     # And update the puzzle's description
-    puzzle_update_channel_and_sheet(turb, puzzle)
+    puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=old_puzzle)
 
     return lambda_ok