X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=turbot%2Fpuzzle.py;h=b7afc8a0beb57eb5daea281cc6e36673d873c8d2;hb=c7213abc1b0c3fcb276284dbd9ba23bb44b5f67a;hp=81e0630f88c08416097ec55aa972ccde18387164;hpb=4b3efe6fde2dd926f5b54eb357ed732e9e04d9e0;p=turbot diff --git a/turbot/puzzle.py b/turbot/puzzle.py index 81e0630..b7afc8a 100644 --- a/turbot/puzzle.py +++ b/turbot/puzzle.py @@ -3,8 +3,28 @@ from turbot.blocks import ( ) from turbot.channel import channel_url from boto3.dynamodb.conditions import Key +import turbot.sheets import re +def find_puzzle_for_puzzle_id(turb, hunt_id, puzzle_id): + """Given a hunt_id and puzzle_id, return that puzzle + + Returns None if no puzzle with the given hunt_id and puzzle_id + exists in the database, otherwise a dictionary with all fields + from the puzzle's row in the database. + """ + + response = turb.table.get_item( + Key={ + 'hunt_id': hunt_id, + 'SK': 'puzzle-{}'.format(puzzle_id) + }) + + if 'Item' in response: + return response['Item'] + else: + return None + def find_puzzle_for_url(turb, hunt_id, url): """Given a hunt_id and URL, return the puzzle with that URL @@ -26,7 +46,7 @@ def find_puzzle_for_url(turb, hunt_id, url): return response['Items'][0] -def puzzle_blocks(puzzle): +def puzzle_blocks(puzzle, include_rounds=False): """Generate Slack blocks for a puzzle The puzzle argument should be a dictionary as returned from the @@ -63,10 +83,19 @@ def puzzle_blocks(puzzle): if state: state_str = "\n{}".format(state) - puzzle_text = "{}{} <{}|{}> ({}){}".format( + rounds_str = '' + if include_rounds and 'rounds' in puzzle: + rounds = puzzle['rounds'] + rounds_str = " in round{}: {}".format( + "s" if len(rounds) > 1 else "", + ", ".join(rounds) + ) + + puzzle_text = "{}{} <{}|{}> ({}){}{}".format( status_emoji, solution_str, channel_url(channel_id), name, - ', '.join(links), state_str + ', '.join(links), rounds_str, + state_str ) # Combining hunt ID and puzzle ID together here is safe because @@ -129,3 +158,101 @@ def puzzle_matches_all(puzzle, patterns): return False return True + +def puzzle_id_from_name(name): + return re.sub(r'[^a-zA-Z0-9_]', '', name).lower() + +def puzzle_channel_topic(puzzle): + """Compute the channel topic for a puzzle""" + + topic = '' + + if puzzle['status'] == 'solved': + topic += "SOLVED: `{}` ".format('`, `'.join(puzzle['solution'])) + + topic += puzzle['name'] + + links = [] + + url = puzzle.get('url', None) + if url: + links.append("<{}|Puzzle>".format(url)) + + sheet_url = puzzle.get('sheet_url', None) + if sheet_url: + links.append("<{}|Sheet>".format(sheet_url)) + + if len(links): + topic += "({})".format(', '.join(links)) + + state = puzzle.get('state', None) + if state: + topic += " {}".format(state) + + return topic + +def puzzle_channel_name(puzzle): + """Compute the channel name for a puzzle""" + + # Note: We don't use puzzle['hunt_id'] here because we're keeping + # that as a persistent identifier in the database. Instead we + # create a new ID-like identifier from the current name. + channel_name = "{}-{}".format( + puzzle['hunt_id'], + puzzle_id_from_name(puzzle['name']) + ) + + if puzzle['status'] == 'solved': + channel_name += "-solved" + + return channel_name + +def puzzle_sheet_name(puzzle): + """Compute the sheet name for a puzzle""" + + sheet_name = puzzle['name'] + if puzzle['status'] == 'solved': + sheet_name += " - Solved {}".format(", ".join(puzzle['solution'])) + + return sheet_name + +def puzzle_update_channel_and_sheet(turb, puzzle, old_puzzle=None): + + channel_id = puzzle['channel_id'] + + # Compute the channel topic and set it if it has changed + channel_topic = puzzle_channel_topic(puzzle) + + old_channel_topic = None + if old_puzzle: + old_channel_topic = puzzle_channel_topic(old_puzzle) + + if channel_topic != old_channel_topic: + # Slack only allows 250 characters for a topic + if len(channel_topic) > 250: + channel_topic = channel_topic[:247] + "..." + turb.slack_client.conversations_setTopic(channel=channel_id, + topic=channel_topic) + + # Compute the sheet name and set it if it has changed + sheet_name = puzzle_sheet_name(puzzle) + + old_sheet_name = None + if old_puzzle: + old_sheet_name = puzzle_sheet_name(old_puzzle) + + if sheet_name != old_sheet_name: + turbot.sheets.renameSheet(turb, puzzle['sheet_url'], sheet_name) + + # Compute the Slack channel name and set it if it has changed + channel_name = puzzle_channel_name(puzzle) + + old_channel_name = None + if old_puzzle: + old_channel_name = puzzle_channel_name(old_puzzle) + + if channel_name != old_channel_name: + turb.slack_client.conversations_rename( + channel=channel_id, + name=channel_name + )