import re
import requests
from botocore.exceptions import ClientError
+from turbot.slack import slack_send_message
actions = {}
commands = {}
if 'Item' in response:
return (response['Item'], table)
else:
- return None
+ return (None, None)
def channel_is_puzzle(turb, channel_id, channel_name):
"""Given a channel ID/name return the database item for the puzzle
Returns a tuple of (hunt_name, hunt_id) or (None, None)."""
- (hunt, hunts_table) = channel_is_hunt(turb, channel_id)
+ (hunt, _) = channel_is_hunt(turb, channel_id)
if hunt:
return (hunt['hunt_id'], hunt['name'])
# puzzle channel with a hunt-id prefix.
hunt_id = channel_name.split('-')[0]
+ hunts_table = turb.db.Table("hunts")
+
response = hunts_table.scan(
FilterExpression='hunt_id = :hunt_id',
ExpressionAttributeValues={':hunt_id': hunt_id}
)
- if 'Items' in response:
+ if 'Items' in response and len(response['Items']):
item = response['Items'][0]
return (item['hunt_id'], item['name'])
"blocks": [
section_block(text_block("*For {}*".format(hunt_name))),
input_block("Puzzle name", "name", "Name of the puzzle"),
- input_block("Puzzle ID", "puzzle_id",
- "Used as part of channel name "
- + "(no spaces nor punctuation)"),
input_block("Puzzle URL", "url", "External URL of puzzle",
optional=True)
]
state = payload['view']['state']['values']
name = state['name']['name']['value']
- puzzle_id = state['puzzle_id']['puzzle_id']['value']
url = state['url']['url']['value']
- # Validate that the puzzle_id contains no invalid characters
- if not re.match(valid_id_re, puzzle_id):
- return submission_error("puzzle_id",
- "Puzzle ID can only contain lowercase letters,"
- + " numbers, and underscores")
+ # 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)
response = turb.slack_client.conversations_create(
name=hunt_dash_channel)
except SlackApiError as e:
- return submission_error("puzzle_id",
- "Error creating Slack channel: {}"
- .format(e.response['error']))
+ return submission_error(
+ "name",
+ "Error creating Slack channel {}: {}"
+ .format(hunt_dash_channel, e.response['error']))
puzzle_channel_id = response['channel']['id']
# XXX: This duplicates functionality eith events.py:set_channel_description
def set_channel_topic(turb, puzzle):
channel_id = puzzle['channel_id']
- description = puzzle['name']
+ 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:
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)
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))
+
+ # And update the puzzle's description
+ set_channel_topic(turb, puzzle)
+
return lambda_ok
commands["/solved"] = solved