X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=turbot%2Finteraction.py;h=d87d27ac1a6827a9da4f6392245e96328440de6e;hb=940e3c1f51b16916d997e84a9464fa8674244b85;hp=8cba346a2122a96c1e2bd9740f78977fd597db7c;hpb=f0ed5cb2f865d8c44c1bd8ac382e50c39357df46;p=turbot diff --git a/turbot/interaction.py b/turbot/interaction.py index 8cba346..d87d27a 100644 --- a/turbot/interaction.py +++ b/turbot/interaction.py @@ -10,7 +10,9 @@ from turbot.hunt import ( from turbot.puzzle import ( find_puzzle_for_url, find_puzzle_for_sort_key, + find_puzzle_for_puzzle_id, puzzle_update_channel_and_sheet, + puzzle_channel_name, puzzle_id_from_name, puzzle_blocks, puzzle_sort_key, @@ -572,7 +574,8 @@ def new_hunt_submission(turb, payload, metadata): {'AttributeName': 'SK', 'AttributeType': 'S'}, {'AttributeName': 'channel_id', 'AttributeType': 'S'}, {'AttributeName': 'is_hunt', 'AttributeType': 'S'}, - {'AttributeName': 'url', 'AttributeType': 'S'} + {'AttributeName': 'url', 'AttributeType': 'S'}, + {'AttributeName': 'puzzle_id', 'AttributeType': 'S'} ], ProvisionedThroughput={ 'ReadCapacityUnits': 5, @@ -616,6 +619,16 @@ def new_hunt_submission(turb, payload, metadata): 'Projection': { 'ProjectionType': 'ALL' } + }, + { + 'IndexName': 'puzzle_id_index', + 'KeySchema': [ + {'AttributeName': 'hunt_id', 'KeyType': 'HASH'}, + {'AttributeName': 'puzzle_id', 'KeyType': 'RANGE'}, + ], + 'Projection': { + 'ProjectionType': 'ALL' + } } ] ) @@ -915,13 +928,20 @@ def new_puzzle(turb, body): return bot_reply("Sorry, this channel doesn't appear to " + "be a hunt or puzzle channel") + # We used puzzle (if available) to select the initial round(s) + puzzle = puzzle_for_channel(turb, channel_id) + initial_rounds = None + if puzzle: + initial_rounds=puzzle.get("rounds", None) + round_options = hunt_rounds(turb, hunt['hunt_id']) if len(round_options): round_options_block = [ multi_select_block("Round(s)", "rounds", "Existing round(s) this puzzle belongs to", - round_options) + round_options, + initial_options=initial_rounds) ] else: round_options_block = [] @@ -967,12 +987,18 @@ def new_puzzle_submission(turb, payload, metadata): hunt_id = meta['hunt_id'] state = payload['view']['state']['values'] - name = state['name']['name']['value'] + + # And start loading data into a puzzle dict + puzzle = {} + puzzle['hunt_id'] = hunt_id + puzzle['name'] = state['name']['name']['value'] url = state['url']['url']['value'] + if url: + puzzle['url'] = url if state['meta']['meta']['selected_options']: - puzzle_type = 'meta' + puzzle['type'] = 'meta' else: - puzzle_type = 'plain' + puzzle['type'] = 'plain' if 'rounds' in state: rounds = [option['value'] for option in state['rounds']['rounds']['selected_options']] @@ -980,8 +1006,17 @@ def new_puzzle_submission(turb, payload, metadata): rounds = [] new_rounds = state['new_rounds']['new_rounds']['value'] + # Create a Slack-channel-safe puzzle_id + puzzle['puzzle_id'] = puzzle_id_from_name(puzzle['name']) + # Before doing anything, reject this puzzle if a puzzle already - # exists with the same URL. + # exists with the same puzzle_id or url + existing = find_puzzle_for_puzzle_id(turb, hunt_id, puzzle['puzzle_id']) + if existing: + return submission_error( + "name", + "Error: This name collides with an existing puzzle.") + if url: existing = find_puzzle_for_url(turb, hunt_id, url) if existing: @@ -989,23 +1024,6 @@ def new_puzzle_submission(turb, payload, metadata): "url", "Error: A puzzle with this URL already exists.") - # Create a Slack-channel-safe puzzle_id - puzzle_id = puzzle_id_from_name(name) - - # 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'])) - - channel_id = response['channel']['id'] - # Add any new rounds to the database if new_rounds: for round in new_rounds.split(','): @@ -1022,21 +1040,26 @@ def new_puzzle_submission(turb, payload, metadata): } ) - # Construct a puzzle dict - puzzle = { - "hunt_id": hunt_id, - "puzzle_id": puzzle_id, - "channel_id": channel_id, - "solution": [], - "status": 'unsolved', - "name": name, - "type": puzzle_type - } - if url: - puzzle['url'] = url if rounds: puzzle['rounds'] = rounds + puzzle['solution'] = [] + puzzle['status'] = 'unsolved' + + # Create a channel for the puzzle + channel_name = puzzle_channel_name(puzzle) + + try: + response = turb.slack_client.conversations_create( + name=channel_name) + except SlackApiError as e: + return submission_error( + "name", + "Error creating Slack channel {}: {}" + .format(channel_name, e.response['error'])) + + puzzle['channel_id'] = response['channel']['id'] + # Finally, compute the appropriate sort key puzzle["SK"] = puzzle_sort_key(puzzle) @@ -1335,7 +1358,6 @@ def help_command(turb, body, args): Displays help on how to use Turbot. """ - channel_name = body['channel_name'][0] channel_id = body['channel_id'][0] response_url = body['response_url'][0] user_id = body['user_id'][0] @@ -1349,15 +1371,19 @@ def help_command(turb, body, args): to_try = "In response to <@{}> asking `/help me`:\n\n{}\n".format( user_id, have_you_tried()) - # If this is a direct message then there's not a usable channel_id - # and we have to use the response_url instead - if channel_name == "directmessage": + # We'll try first to reply directly to the channel (for the benefit + # of anyone else in the same channel that might be stuck too. + # + # But if this doesn't work, (direct message or private channel), + # then we can instead reply with an ephemeral message by using + # the response_url. + try: + turb.slack_client.chat_postMessage( + channel=channel_id, text=to_try) + except SlackApiError: requests.post(response_url, json = {"text": to_try}, headers = {"Content-type": "application/json"}) - else: - turb.slack_client.chat_postMessage( - channel=channel_id, text=to_try) return lambda_ok help_string = turbot_help(args)