]> git.cworth.org Git - turbot-web/blobdiff - html_generator.py
Abstract out the filename_from_name function
[turbot-web] / html_generator.py
index 9b1b1147bb966012b97aeef4331aefb0899fa27a..c16f033552cb80094befa995b04645fa1d612ba6 100644 (file)
@@ -14,20 +14,31 @@ that would be great
 
 Requires sorttable.js, which should be included
 """
-from turbot.channel import channel_url
+import boto3
 from boto3.dynamodb.conditions import Key
+import re
 
 website = "https://halibut.cworth.org/"
 #change this if we're using AWS or some other subdomain instead
 
-def find_hunt_for_hunt_id(turb, hunt_id):
+def filename_from_name(name):
+    """Returns a string derived from name, but with all spaces and slashes
+       replaced with underscores, (for making a clean filename)"""
+    return re.sub(r'[ /]', '_', name)
+
+def channel_url(channel_id):
+    """Given a channel ID, return the URL for that channel."""
+
+    return "https://halibutthatbass.slack.com/archives/{}".format(channel_id)
+
+def find_hunt_for_hunt_id(table, hunt_id):
     """Given a hunt ID find the database item for that hunt
 
     Returns None if hunt ID is not found, otherwise a
     dictionary with all fields from the hunt's row in the table,
     (channel_id, active, hunt_id, name, url, sheet_url, etc.).
     """
-    response = turb.table.get_item(
+    response = table.get_item(
         Key={
             'hunt_id': hunt_id,
             'SK': 'hunt-{}'.format(hunt_id)
@@ -38,10 +49,10 @@ def find_hunt_for_hunt_id(turb, hunt_id):
     else:
         return None
 
-def hunt_puzzles_for_hunt_id(turb, hunt_id):
+def hunt_puzzles_for_hunt_id(table, hunt_id):
     """Return all puzzles that belong to the given hunt_id"""
 
-    response = turb.table.query(
+    response = table.query(
         KeyConditionExpression=(
             Key('hunt_id').eq(hunt_id) &
             Key('SK').begins_with('puzzle-')
@@ -59,15 +70,17 @@ def link(lin, text):
     #internal links, doesn't open new tab
     return '<a href="{}">{}</a>'.format(lin, text)
 
-def hunt_info(turb, hunt):
+def hunt_info(table, hunt_id):
     """
     Retrieves list of rounds, puzzles for the given hunt
     """
+
+    hunt = find_hunt_for_hunt_id(table, hunt_id)
+
     name = hunt["name"]
-    hunt_id = hunt["hunt_id"]
     channel_id = hunt["channel_id"]
 
-    puzzles = hunt_puzzles_for_hunt_id(turb, hunt_id)
+    puzzles = hunt_puzzles_for_hunt_id(table, hunt_id)
 
     rounds = set()
     for puzzle in puzzles:
@@ -159,7 +172,7 @@ def overview(puzzles, rounds):
         expanding += [
         '  <div id="b{}" class="containerTab {}" style="display:none;">\n'.format(i, status),
         '    <span onclick="this.parentElement.style.display=\'none\'" class="closebtn">x</span>\n',
-        '    <h2>{}</h2>\n'.format(link(website + "_".join(rnd.split()) + "_round.html", rnd)),
+        '    <h2>{}</h2>\n'.format(link(website + filename_from_name(rnd) + "_round.html", rnd)),
         '    <table class="sortable">\n',
         '      <tr>\n',
         '        <th><u>Puzzle</u></th>\n',
@@ -173,12 +186,12 @@ def overview(puzzles, rounds):
                 meta = ''
             if puzzle['status'] == 'solved':
                 expanding += ['      <tr class=\'solved\';>\n',
-                '        <td>{}</td>\n'.format(link(website + "_".join(puzzle['name'].split()) + ".html", puzzle['name']+meta)),
+                '        <td>{}</td>\n'.format(link(website + filename_from_name(puzzle['name']) + ".html", puzzle['name']+meta)),
                 '        <td>{}</td>\n'.format(puzzle['solution']),
                 '      </tr>\n']
             else:
                 expanding += ['      <tr class=\'unsolved\';>\n',
-                '        <td><b>{}</b></td>\n'.format(link(website + "_".join(puzzle['name'].split()) + ".html", puzzle['name']+meta)),
+                '        <td><b>{}</b></td>\n'.format(link(website + filename_from_name(puzzle['name']) + ".html", puzzle['name']+meta)),
                 '        <td></td>\n',
                 '      </tr>\n']
         expanding.append('    </table>\n')
@@ -238,22 +251,22 @@ def round_overview(rnd, puzzles):
         if puzzle['status'] == 'solved':
             puzzle_list += [ '                    <tr>\n',
              '                        <td>{}</td>\n'.format(elink(slack_url, puzzle['name']+meta)),
-             '                        <td>{}</td>\n'.format(elink(puzzle['url'], 'Puzzle')),
+             '                        <td>{}</td>\n'.format(elink(puzzle.get('url',''), 'Puzzle')),
              '                        <td>{}</td>\n'.format(elink(puzzle['sheet_url'], 'Sheet')),
-             '                        <td>{}</td>\n'.format(link(website + "_".join(puzzle['name'].split()) + '.html', 'Overview')),
+             '                        <td>{}</td>\n'.format(link(website + filename_from_name(puzzle['name']) + '.html', 'Overview')),
              '                        <td>{}</td>\n'.format(puzzle['solution']),
             # '                        <td></td>\n',
-             '                        <td>{}</td>\n'.format("".join(puzzle['tags'])),
+             '                        <td>{}</td>\n'.format("".join(puzzle.get('tags',[]))),
              '                    </tr>\n']
         else:
             puzzle_list += [ '                    <tr>\n',
              '                        <td><b>{}</b></td>\n'.format(elink(slack_url, puzzle['name']+meta)),
-             '                        <td>{}</td>\n'.format(elink(puzzle['url'], 'Puzzle')),
+             '                        <td>{}</td>\n'.format(elink(puzzle.get('url',''), 'Puzzle')),
              '                        <td>{}</td>\n'.format(elink(puzzle['sheet_url'], 'Sheet')),
-             '                        <td>{}</td>\n'.format(link(website + "_".join(puzzle['name'].split()) + '.html', 'Overview')),
+             '                        <td>{}</td>\n'.format(link(website + filename_from_name(puzzle['name']) + '.html', 'Overview')),
              '                        <td></td>\n',
             # '                        <td></td>\n',
-             '                        <td>{}</td>\n'.format(" ".join(puzzle['tags'])),
+             '                        <td>{}</td>\n'.format(" ".join(puzzle.get('tags',[]))),
              '                    </tr>\n']
     end = ['                </tbody>\n',
     '            </table>\n',
@@ -261,7 +274,7 @@ def round_overview(rnd, puzzles):
     '    </body>\n',
     '</html>\n']
     html = start + puzzle_list + end
-    file = "{}_round.html".format('_'.join(rnd.split()))
+    file = "{}_round.html".format(filename_from_name(rnd))
     f = open(file, "w")
     for line in html:
         f.write(line)
@@ -277,7 +290,10 @@ def puzzle_overview(puzzle):
     else:
         meta = ''
     slack_url = channel_url(puzzle['channel_id'])
-    round_url = [link(website + "_".join(rnd.split()) + "_round.html", rnd) for rnd in puzzle['rounds']]
+    if 'rounds' in puzzle:
+        round_url = [link(website + filename_from_name(rnd) + "_round.html", rnd) for rnd in puzzle['rounds']]
+    else:
+        round_url = ''
     if puzzle['status'] == 'solved':
         solution = puzzle['solution']
         status = 'solved'
@@ -300,7 +316,7 @@ def puzzle_overview(puzzle):
      '        <table class="center">\n',
      '            <tr>\n',
      '                <td>{}</td>\n'.format(elink(slack_url, 'Channel')), #slack channel
-     '                <td>{}</td>\n'.format(elink(puzzle['url'], 'Puzzle')),
+     '                <td>{}</td>\n'.format(elink(puzzle.get('url',''), 'Puzzle')),
      '                <td>{}</td>\n'.format(elink(puzzle['sheet_url'], 'Sheet')),
      '                <td>Additional Resources</td>\n',
      '            </tr>\n',
@@ -308,7 +324,7 @@ def puzzle_overview(puzzle):
      '        <table class="center">\n',
      '            <tr>\n',
      '                <td>Round(s): {}</td>\n'.format(" ".join(round_url)), #round page on our site
-     '                <td>Tags: {}</td>\n'.format(" ".join(puzzle['tags'])), #add tags
+     '                <td>Tags: {}</td>\n'.format(" ".join(puzzle.get('tags',[]))), #add tags
      '            </tr>\n',
      '            <tr>\n',
      '                <td>Answer: {}</td>\n'.format(solution),
@@ -319,8 +335,7 @@ def puzzle_overview(puzzle):
      '\n',
      '</body>\n',
      '</html>\n']
-    underscored = "_".join(name.split())
-    file = "{}.html".format(underscored)
+    file = "{}.html".format(filename_from_name(name))
     f = open(file, "w")
     for line in html:
         f.write(line)
@@ -369,17 +384,20 @@ def puzzle_lists(puzzles, filt):
         else:
             meta = ''
         slack_url = channel_url(puzzle['channel_id'])
-        round_url = link(website + "_".join(rnd.split()) + "_round.html", puzzle['rounds'][0])
+        if 'rounds' in puzzle:
+            round_url = link(website + filename_from_name(rnd) + "_round.html", puzzle['rounds'][0])
+        else:
+            round_url = ''
         #assuming one round per puzzle for now
 
         solved_code += ['                    <tr>\n',
          '                        <td>{}</td>\n'.format(elink(slack_url, puzzle['name']+meta)),
-         '                        <td>{}</td>\n'.format(elink(puzzle['url'], 'Puzzle')),
+         '                        <td>{}</td>\n'.format(elink(puzzle.get('url',''), 'Puzzle')),
          '                        <td>{}</td>\n'.format(elink(puzzle['sheet_url'], 'Sheet')),
-         '                        <td>{}</td>\n'.format(link(website + "_".join(puzzle['name'].split()) + '.html', 'Overview')),
+         '                        <td>{}</td>\n'.format(link(website + filename_from_name(puzzle['name']) + '.html', 'Overview')),
          '                        <td>{}</td>\n'.format(puzzle['solution']),
          '                        <td>{}</td>\n'.format(round_url),
-         '                        <td>{}</td>\n'.format("".join(puzzle['tags'])),
+         '                        <td>{}</td>\n'.format("".join(puzzle.get('tags',[]))),
          '                    </tr>\n']
     for puzzle in unsolved_puzzles:
         if puzzle['type'] == 'meta':
@@ -387,17 +405,20 @@ def puzzle_lists(puzzles, filt):
         else:
             meta = ''
         slack_url = channel_url(puzzle['channel_id'])
-        round_url = link(website + "_".join(rnd.split()) + "_round.html", puzzle['rounds'][0])
+        if 'rounds' in puzzle:
+            round_url = link(website + filename_from_name(rnd) + "_round.html", puzzle['rounds'][0])
+        else:
+            round_url = ''
         #assuming one round per puzzle for now
 
         unsolved_code += ['                    <tr>\n',
          '                        <td>{}</td>\n'.format(elink(slack_url, puzzle['name']+meta)),
-         '                        <td>{}</td>\n'.format(elink(puzzle['url'], 'Puzzle')),
+         '                        <td>{}</td>\n'.format(elink(puzzle.get('url',''), 'Puzzle')),
          '                        <td>{}</td>\n'.format(elink(puzzle['sheet_url'], 'Sheet')),
-         '                        <td>{}</td>\n'.format(link(website + "_".join(puzzle['name'].split()) + '.html', 'Overview')),
+         '                        <td>{}</td>\n'.format(link(website + filename_from_name(puzzle['name']) + '.html', 'Overview')),
          '                        <td></td>\n',
          '                        <td>{}</td>\n'.format(round_url),
-         '                        <td>{}</td>\n'.format("".join(puzzle['tags'])),
+         '                        <td>{}</td>\n'.format("".join(puzzle.get('tags',[]))),
          '                    </tr>\n']
     end = ['                </tbody>\n',
     '            </table>\n',
@@ -424,10 +445,11 @@ def puzzle_lists(puzzles, filt):
         f.close()
     return None
 
+# Initialize AWS resources to talk to database
+db = boto3.resource('dynamodb')
+table = db.Table("turbot")
+puzzles, rounds = hunt_info(table, "mh2021")
 
-
-puzzles, rounds = hunt_info(turb, hunt)
-#I am not sure where these come from
 overview(puzzles, rounds)
 for rnd in rounds:
     round_overview(rnd, puzzles)