+ result = turb.slack_client.views_open(trigger_id=trigger_id,
+ view=view)
+
+ if (result['ok']):
+ submission_handlers[result['view']['id']] = puzzle_submission
+
+ return lambda_ok
+
+commands["/puzzle"] = puzzle
+
+def 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."""
+
+ meta = json.loads(metadata)
+ hunt_id = meta['hunt_id']
+
+ state = payload['view']['state']['values']
+ name = state['name']['name']['value']
+ url = state['url']['url']['value']
+
+ # Create a Slack-channel-safe puzzle_id
+ puzzle_id = re.sub(r'[^a-zA-Z0-9_]', '', name).lower()
+
+ # Create a channel for the puzzle
+ hunt_dash_channel = "{}-{}".format(hunt_id, puzzle_id)
+
+ try:
+ response = turb.slack_client.conversations_create(
+ name=hunt_dash_channel)
+ except SlackApiError as e:
+ return submission_error(
+ "name",
+ "Error creating Slack channel {}: {}"
+ .format(hunt_dash_channel, e.response['error']))
+
+ puzzle_channel_id = response['channel']['id']
+
+ # Insert the newly-created puzzle into the database
+ table = turb.db.Table(hunt_id)
+ table.put_item(
+ Item={
+ "channel_id": puzzle_channel_id,
+ "solution": [],
+ "status": 'unsolved',
+ "hunt_id": hunt_id,
+ "name": name,
+ "puzzle_id": puzzle_id,
+ "url": url,
+ }
+ )
+
+ 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)
+
+ turb.slack_client.conversations_setTopic(channel=channel_id,
+ topic=description)
+
+def state(turb, body, args):
+ """Implementation of the /state command
+
+ The args string should be a brief sentence describing where things
+ stand or what's needed."""
+
+ channel_id = body['channel_id'][0]
+ channel_name = body['channel_name'][0]
+
+ (puzzle, table) = channel_is_puzzle(turb, channel_id, channel_name)
+
+ if not puzzle:
+ return bot_reply("Sorry, this is not a puzzle channel.")
+
+ # Set the state field in the database
+ puzzle['state'] = args
+ table.put_item(Item=puzzle)
+
+ set_channel_topic(turb, puzzle)
+
+ return lambda_ok
+
+commands["/state"] = state
+
+def solved(turb, body, args):
+ """Implementation of the /solved command
+
+ The args string should be a confirmed solution."""
+
+ channel_id = body['channel_id'][0]
+ channel_name = body['channel_name'][0]
+ user_name = body['user_name'][0]
+
+ (puzzle, table) = channel_is_puzzle(turb, channel_id, channel_name)
+
+ if not puzzle:
+ return bot_reply("Sorry, this is not a puzzle channel.")
+
+ # Set the status and solution fields in the database
+ puzzle['status'] = 'solved'
+ puzzle['solution'].append(args)
+ table.put_item(Item=puzzle)
+
+ # Report the solution to the puzzle's channel
+ slack_send_message(
+ turb.slack_client, channel_id,
+ "Puzzle mark solved by {}: `{}`".format(user_name, args))
+
+ # Also report the solution to the hunt channel
+ (hunt, _) = get_table_item(turb, "hunts", "hunt_id", puzzle['hunt_id'])
+ slack_send_message(
+ turb.slack_client, hunt['channel_id'],
+ "Puzzle '<{}|{}>' has been solved!".format(
+ puzzle['channel_url'],
+ puzzle['name'])
+ )
+
+ # And update the puzzle's description
+ set_channel_topic(turb, puzzle)
+
+ # And rename the sheet to prefix with "SOLVED: "
+ turbot.sheets.renameSheet(turb, puzzle['sheet_url'], 'SOLVED: ' + puzzle['name'])
+
+ # 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)
+
+ return lambda_ok
+
+commands["/solved"] = solved