]> git.cworth.org Git - turbot/commitdiff
Farm blocks-creation code out to various supporting files
authorCarl Worth <cworth@cworth.org>
Tue, 5 Jan 2021 02:41:07 +0000 (18:41 -0800)
committerCarl Worth <cworth@cworth.org>
Tue, 5 Jan 2021 02:41:07 +0000 (18:41 -0800)
The code will be easier to manage with separate hunt, round, puzzle,
and channel.py files each responsible for maintaining their own
functionality. We don't yet have any classes in any of these files,
(just functions that look things up in the database and that generate
Slack blocks), but we may end up doing classes later, (particularly if
we start wanting methods to update a single attribute in the database
for a given item, etc.).

turbot/channel.py [new file with mode: 0644]
turbot/events.py
turbot/hunt.py
turbot/puzzle.py
turbot/round.py [new file with mode: 0644]

diff --git a/turbot/channel.py b/turbot/channel.py
new file mode 100644 (file)
index 0000000..1c9d412
--- /dev/null
@@ -0,0 +1,4 @@
+def channel_url(channel_id):
+    """Given a channel ID, return the URL for that channel."""
+
+    return "https://halibutthatbass.slack.com/archives/{}".format(channel_id)
index 70f18a602676652139ed26b33a2c9d3126ebbafa..bf4154ffafce8124388c80442ec0fbe630821e06 100644 (file)
@@ -1,9 +1,10 @@
 from turbot.blocks import (
     section_block, text_block, button_block, actions_block, divider_block
 )
+from turbot.hunt import hunt_blocks, find_hunt_for_hunt_id
 from turbot.sheets import sheets_create, sheets_create_for_puzzle
 from turbot.slack import slack_send_message, slack_channel_members
-from turbot.hunt import find_hunt_for_hunt_id
+from turbot.channel import channel_url
 from boto3.dynamodb.conditions import Key
 
 TURBOT_USER_ID = 'U01B9QM4P9R'
@@ -13,106 +14,6 @@ events = {}
 lambda_success = {'statusCode': 200}
 lambda_error = {'statusCode': 400}
 
-def channel_url(channel_id):
-    return "https://halibutthatbass.slack.com/archives/{}".format(channel_id)
-
-def puzzle_block(puzzle):
-    name = puzzle['name']
-    status = puzzle['status']
-    solution = puzzle['solution']
-    channel_id = puzzle['channel_id']
-    url = puzzle.get('url', None)
-    sheet_url = puzzle.get('sheet_url', None)
-    state = puzzle.get('state', None)
-    status_emoji = ''
-    solution_str = ''
-
-    if status == 'solved':
-        status_emoji = ":ballot_box_with_check:"
-    else:
-        status_emoji = ":white_square:"
-
-    if len(solution):
-        solution_str = "*`" + '`, `'.join(solution) + "`*"
-
-    links = []
-    if url:
-        links.append("<{}|Puzzle>".format(url))
-    if sheet_url:
-        links.append("<{}|Sheet>".format(sheet_url))
-
-    state_str = ''
-    if state:
-        state_str = "\n{}".format(state)
-
-    puzzle_text = "{}{} <{}|{}> ({}){}".format(
-        status_emoji, solution_str,
-        channel_url(channel_id), name,
-        ', '.join(links), state_str
-    )
-
-    return section_block(text_block(puzzle_text))
-
-def round_blocks(round, puzzles):
-
-    round_text = "*Round: {}*".format(round)
-
-    blocks = [
-        section_block(text_block(round_text)),
-    ]
-
-    for puzzle in puzzles:
-        if 'rounds' not in puzzle:
-            continue
-        if round not in puzzle['rounds']:
-            continue
-        blocks.append(puzzle_block(puzzle))
-
-    return blocks
-
-def hunt_details_blocks(turb, hunt):
-    name = hunt['name']
-    hunt_id = hunt['hunt_id']
-    channel_id = hunt['channel_id']
-
-    response = turb.table.query(
-        KeyConditionExpression=(
-            Key('hunt_id').eq(hunt_id) &
-            Key('SK').begins_with('puzzle-')
-        )
-    )
-    puzzles = response['Items']
-
-    # Compute the set of rounds across all puzzles
-    rounds = set()
-    for puzzle in puzzles:
-        if 'rounds' not in puzzle:
-            continue
-        for round in puzzle['rounds']:
-            rounds.add(round)
-
-    hunt_text = "*<{}|{}>*".format(channel_url(channel_id), name)
-
-    blocks = [
-        section_block(text_block(hunt_text)),
-    ]
-
-    # Construct blocks for each round
-    for round in rounds:
-        blocks += round_blocks(round, puzzles)
-
-    # Also blocks for any puzzles not in any round
-    stray_puzzles = [puzzle for puzzle in puzzles if 'rounds' not in puzzle]
-    if len(stray_puzzles):
-        stray_text = "*Puzzles with no asigned round*"
-        blocks.append(section_block(text_block(stray_text)))
-        for puzzle in stray_puzzles:
-            blocks.append(puzzle_block(puzzle))
-
-    blocks.append(divider_block())
-
-    return blocks
-
 def hunt_link_block(turb, hunt):
 
     name = hunt['name']
@@ -144,7 +45,7 @@ def home(turb, user_id):
             continue
         if user_id in slack_channel_members(turb.slack_client,
                                             hunt['channel_id']):
-            my_hunt_blocks += hunt_details_blocks(turb, hunt)
+            my_hunt_blocks += hunt_blocks(turb, hunt)
         else:
             available_hunt_blocks.append(hunt_link_block(turb, hunt))
 
index 87e47fa1324cf603423bdcbebff6c65b1f78056a..77c179771a17cd7e01eed6f5d3230bf554a225b6 100644 (file)
@@ -1,3 +1,9 @@
+from turbot.blocks import section_block, text_block, divider_block
+from turbot.round import round_blocks
+from turbot.puzzle import puzzle_block
+from turbot.channel import channel_url
+from boto3.dynamodb.conditions import Key
+
 def find_hunt_for_hunt_id(turb, hunt_id):
     """Given a hunt ID find the database item for that hunt
 
@@ -16,3 +22,54 @@ def find_hunt_for_hunt_id(turb, hunt_id):
         return response['Item']
     else:
         return None
+
+def hunt_blocks(turb, hunt):
+    """Generate Slack blocks for a hunt
+
+    The hunt argument should be a dictionary as returned from the
+    database. The return value can be used in a Slack command
+    expecting blocks to provide all the details of a hunt, (puzzles,
+    their state, solution, links to channels and sheets, etc.).
+    """
+
+    name = hunt['name']
+    hunt_id = hunt['hunt_id']
+    channel_id = hunt['channel_id']
+
+    response = turb.table.query(
+        KeyConditionExpression=(
+            Key('hunt_id').eq(hunt_id) &
+            Key('SK').begins_with('puzzle-')
+        )
+    )
+    puzzles = response['Items']
+
+    # Compute the set of rounds across all puzzles
+    rounds = set()
+    for puzzle in puzzles:
+        if 'rounds' not in puzzle:
+            continue
+        for round in puzzle['rounds']:
+            rounds.add(round)
+
+    hunt_text = "*<{}|{}>*".format(channel_url(channel_id), name)
+
+    blocks = [
+        section_block(text_block(hunt_text)),
+    ]
+
+    # Construct blocks for each round
+    for round in rounds:
+        blocks += round_blocks(round, puzzles)
+
+    # Also blocks for any puzzles not in any round
+    stray_puzzles = [puzzle for puzzle in puzzles if 'rounds' not in puzzle]
+    if len(stray_puzzles):
+        stray_text = "*Puzzles with no asigned round*"
+        blocks.append(section_block(text_block(stray_text)))
+        for puzzle in stray_puzzles:
+            blocks.append(puzzle_block(puzzle))
+
+    blocks.append(divider_block())
+
+    return blocks
index 9f9b1c600b4002a5afa661cdf1d4c9b930639fd0..810c97e5e671c977bab712b79acd4ddf973e5516 100644 (file)
@@ -1,3 +1,5 @@
+from turbot.blocks import section_block, text_block
+from turbot.channel import channel_url
 from boto3.dynamodb.conditions import Key
 
 def find_puzzle_for_url(turb, hunt_id, url):
@@ -20,3 +22,48 @@ def find_puzzle_for_url(turb, hunt_id, url):
         return None
 
     return response['Items'][0]
+
+def puzzle_block(puzzle):
+    """Generate Slack blocks for a puzzle
+
+    The puzzle argument should be a dictionary as returned from the
+    database. The return value can be used in a Slack command
+    expecting blocks to provide all the details of a puzzle, (its
+    state, solution, links to channel and sheet, etc.).
+    """
+
+    name = puzzle['name']
+    status = puzzle['status']
+    solution = puzzle['solution']
+    channel_id = puzzle['channel_id']
+    url = puzzle.get('url', None)
+    sheet_url = puzzle.get('sheet_url', None)
+    state = puzzle.get('state', None)
+    status_emoji = ''
+    solution_str = ''
+
+    if status == 'solved':
+        status_emoji = ":ballot_box_with_check:"
+    else:
+        status_emoji = ":white_square:"
+
+    if len(solution):
+        solution_str = "*`" + '`, `'.join(solution) + "`*"
+
+    links = []
+    if url:
+        links.append("<{}|Puzzle>".format(url))
+    if sheet_url:
+        links.append("<{}|Sheet>".format(sheet_url))
+
+    state_str = ''
+    if state:
+        state_str = "\n{}".format(state)
+
+    puzzle_text = "{}{} <{}|{}> ({}){}".format(
+        status_emoji, solution_str,
+        channel_url(channel_id), name,
+        ', '.join(links), state_str
+    )
+
+    return section_block(text_block(puzzle_text))
diff --git a/turbot/round.py b/turbot/round.py
new file mode 100644 (file)
index 0000000..3c4042b
--- /dev/null
@@ -0,0 +1,31 @@
+from turbot.puzzle import puzzle_block
+from turbot.blocks import section_block, text_block
+
+def round_blocks(round, puzzles):
+    """Generate Slack blocks for a round
+
+    The 'round' argument should be the name of a round as it appears
+    in the datbase. The `puzzles` argument should be a list of
+    puzzles. The results will include only puzzles which have 'round'
+    in their 'rounds' attribute.
+
+    The return value is a list of bocks that can be used in any Slack
+    command acceepting blocks. It will provide all the details of the
+    puzzles in the given round, (their state, solutions, links to
+    channels and sheets, etc.).
+    """
+
+    round_text = "*Round: {}*".format(round)
+
+    blocks = [
+        section_block(text_block(round_text)),
+    ]
+
+    for puzzle in puzzles:
+        if 'rounds' not in puzzle:
+            continue
+        if round not in puzzle['rounds']:
+            continue
+        blocks.append(puzzle_block(puzzle))
+
+    return blocks