X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=turbot%2Finteraction.py;h=955fae5b776f15db7222e7a5e3a0cbe81ec4f0c0;hb=c7213abc1b0c3fcb276284dbd9ba23bb44b5f67a;hp=417066aba650324fd3ff0199311552f94bb16214;hpb=4ed02dad3ef9127fd1146753e93334b6c33389de;p=turbot diff --git a/turbot/interaction.py b/turbot/interaction.py index 417066a..955fae5 100644 --- a/turbot/interaction.py +++ b/turbot/interaction.py @@ -3,7 +3,13 @@ from turbot.blocks import ( 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, find_puzzle_for_puzzle_id +from turbot.puzzle import ( + find_puzzle_for_url, + find_puzzle_for_puzzle_id, + puzzle_update_channel_and_sheet, + puzzle_id_from_name, + puzzle_blocks +) import turbot.rot import turbot.sheets import turbot.slack @@ -224,20 +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. - - # XXX: What we really want here is a single function that sets the - # channel name, the channel topic, and the sheet name. That single - # function should be called anywhere there is code changing any of - # these things. This function could then also accept an optional - # "old_puzzle" argument and avoid changing any of those things - # that are unnecessary. - set_channel_topic(turb, puzzle) + puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=old_puzzle) return lambda_ok @@ -543,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] @@ -590,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) @@ -626,7 +677,7 @@ def puzzle_submission(turb, payload, metadata): "Error: A puzzle with this URL already exists.") # Create a Slack-channel-safe puzzle_id - puzzle_id = re.sub(r'[^a-zA-Z0-9_]', '', name).lower() + puzzle_id = puzzle_id_from_name(name) # Create a channel for the puzzle hunt_dash_channel = "{}-{}".format(hunt_id, puzzle_id) @@ -676,41 +727,6 @@ def puzzle_submission(turb, payload, metadata): return lambda_ok -# XXX: This duplicates functionality eith events.py:set_channel_description -def set_channel_topic(turb, puzzle): - channel_id = puzzle['channel_id'] - name = puzzle['name'] - url = puzzle.get('url', None) - sheet_url = puzzle.get('sheet_url', None) - state = puzzle.get('state', None) - status = puzzle['status'] - - description = '' - - if status == 'solved': - description += "SOLVED: `{}` ".format('`, `'.join(puzzle['solution'])) - - description += name - - links = [] - if url: - links.append("<{}|Puzzle>".format(url)) - if sheet_url: - links.append("<{}|Sheet>".format(sheet_url)) - - if len(links): - description += "({})".format(', '.join(links)) - - if state: - description += " {}".format(state) - - # Slack only allows 250 characters for a topic - if len(description) > 250: - description = description[:247] + "..." - - turb.slack_client.conversations_setTopic(channel=channel_id, - topic=description) - def state(turb, body, args): """Implementation of the /state command @@ -719,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) - set_channel_topic(turb, puzzle) + puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=old_puzzle) return lambda_ok @@ -743,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) @@ -774,19 +796,7 @@ def solved(turb, body, args): ) # And update the puzzle's description - set_channel_topic(turb, puzzle) - - # And rename the sheet to suffix with "-SOLVED" - turbot.sheets.renameSheet(turb, puzzle['sheet_url'], - puzzle['name'] + "-SOLVED") - - # Finally, rename the Slack channel to add the suffix '-solved' - channel_name = "{}-{}-solved".format( - puzzle['hunt_id'], - puzzle['puzzle_id']) - turb.slack_client.conversations_rename( - channel=puzzle['channel_id'], - name=channel_name) + puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=old_puzzle) return lambda_ok