{"action":"created","comment":{"url":"https://api.github.com/repos/dirtbags/moth/pulls/comments/84173756","pull_request_review_id":4966965,"id":84173756,"diff_hunk":"@@ -0,0 +1,124 @@\n+#!/usr/bin/env python3\n+\n+import argparse\n+import base64\n+import glob\n+import hashlib\n+import hmac\n+import io\n+import json\n+import os\n+import markdown\n+import random\n+import sys\n+import zipfile\n+\n+import puzzles\n+\n+def write_kv_pairs(ziphandle, filename, kv):\n+    \"\"\" Write out a sorted map to file\n+    :param ziphandle: a zipfile object\n+    :param filename: The filename to write within the zipfile object\n+    :param kv:  the map to write out\n+    :return:\n+    \"\"\"\n+    filehandle = io.StringIO()\n+    for key in sorted(kv.keys()):\n+        if type(kv[key])  == type([]):\n+            for val in kv[key]:\n+                filehandle.write(\"%s: %s%s\" % (key, val, os.linesep))\n+        else:\n+            filehandle.write(\"%s: %s%s\" % (key, kv[key], os.linesep))\n+    filehandle.seek(0)\n+    ziphandle.writestr(filename, filehandle.read())\n+   \n+if __name__ == '__main__':        \n+    parser = argparse.ArgumentParser(description='Build a category package')\n+    parser.add_argument('seed', help='contest seed')\n+    parser.add_argument('categorydirs', nargs='+', help='Directory of category source')\n+    parser.add_argument('outdir', help='Output directory')\n+    args = parser.parse_args()\n+\n+    for categorydir in args.categorydirs:\n+        puzzles_dict = {}\n+        secrets = {}\n+\n+        categoryname = os.path.basename(categorydir.strip(os.sep))\n+        \n+        # build category seed\n+        category_seed = hashlib.new('sha1')\n+        category_seed.update(categoryname.encode('utf-8'))\n+        category_seed.update(args.seed.encode('utf-8'))\n+        category_seed = category_seed.hexdigest()\n+\n+        # create zipfile\n+        zipfilename = os.path.join(args.outdir, \"%s.zip\" % categoryname)\n+        if os.path.exists(zipfilename):\n+    # assume blank state for now\n+            pass\n+    #        # open and gather some state\n+    #        zf = zipfile.ZipFile(zipfilename, 'a')\n+        else:\n+            # create and read in state\n+            zf = zipfile.ZipFile(zipfilename, 'w')\n+\n+        # read in category details (will be pflarr in future)\n+        for categorypath in glob.glob(os.path.join(categorydir, \"*\", \"puzzle.moth\")):\n+            points = categorypath.split(os.sep)[-2] # directory before '/puzzle.moth'\n+            categorypath = os.path.dirname(categorypath)\n+            print(categorypath)\n+            try:\n+                points = int(points)\n+            except:\n+                print(\"Failed to identify points on: %s\" % categorypath, file=sys.stderr)\n+                continue\n+            puzzle = puzzles.Puzzle(category_seed, categorypath)\n+            puzzles_dict[points] = puzzle\n+\n+        # build mapping, answers, and summary\n+        mapping = {}\n+        answers = {}\n+        summary = {}\n+        for points in sorted(puzzles_dict):\n+            puzzle = puzzles_dict[points]\n+            hashmap = hashlib.sha1(args.seed.encode('utf-8'))\n+            hashmap.update(categoryname.encode('utf-8'))\n+            hashmap.update(str(points).encode('utf-8'))\n+            mapping[points] = hashmap.hexdigest()\n+            answers[points] = puzzle['answer']\n+            if len(puzzle['summary']) > 0:\n+                summary[points] = puzzle['summary']\n+\n+        # write mapping, answers, and summary\n+        write_kv_pairs(zf, os.path.join(categoryname, 'map.txt'), mapping)\n+        write_kv_pairs(zf, os.path.join(categoryname, 'answers.txt'), answers)\n+        write_kv_pairs(zf, os.path.join(categoryname, 'summary.txt'), summary)\n+\n+        # write out puzzles\n+        for points in sorted(puzzles_dict):\n+            puzzle = puzzles_dict[points]\n+            puzzlebody = [json.dumps(puzzle.publish())]\n+            puzzledir = os.path.join(categoryname, 'content', mapping[points])\n+            # build/write json\n+\n+            # write associated files\n+            assoc_files = []\n+            for fobj in puzzle['files']:\n+                if fobj.visible == True:\n+                    assoc_files.append(fobj.name)\n+                zf.writestr(os.path.join(puzzledir, fobj.name), \\\n+                                    fobj.handle.read())\n+\n+\n+            if len(assoc_files) > 0:\n+                puzzlebody.append(\"\")\n+                puzzlebody.append(\"## Associated Files:\")\n+                for f in assoc_files:\n+                    puzzlebody.append(f)","path":"package-puzzles","position":117,"original_position":117,"commit_id":"cf922f32170701e4b5afdfd2c7d7eb9c7b14e65b","original_commit_id":"cf922f32170701e4b5afdfd2c7d7eb9c7b14e65b","user":{"login":"nealey","id":423780,"avatar_url":"https://avatars.githubusercontent.com/u/423780?v=3","gravatar_id":"","url":"https://api.github.com/users/nealey","html_url":"https://github.com/nealey","followers_url":"https://api.github.com/users/nealey/followers","following_url":"https://api.github.com/users/nealey/following{/other_user}","gists_url":"https://api.github.com/users/nealey/gists{/gist_id}","starred_url":"https://api.github.com/users/nealey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nealey/subscriptions","organizations_url":"https://api.github.com/users/nealey/orgs","repos_url":"https://api.github.com/users/nealey/repos","events_url":"https://api.github.com/users/nealey/events{/privacy}","received_events_url":"https://api.github.com/users/nealey/received_events","type":"User","site_admin":false},"body":"Just want to write down somewhere that we've decided \"associated files\" needs to go in the json object for the puzzle, not in the body.","created_at":"2016-10-19T21:43:00Z","updated_at":"2016-10-19T21:43:26Z","html_url":"https://github.com/dirtbags/moth/pull/7#discussion_r84173756","pull_request_url":"https://api.github.com/repos/dirtbags/moth/pulls/7","_links":{"self":{"href":"https://api.github.com/repos/dirtbags/moth/pulls/comments/84173756"},"html":{"href":"https://github.com/dirtbags/moth/pull/7#discussion_r84173756"},"pull_request":{"href":"https://api.github.com/repos/dirtbags/moth/pulls/7"}}},"pull_request":{"url":"https://api.github.com/repos/dirtbags/moth/pulls/7","id":89915772,"html_url":"https://github.com/dirtbags/moth/pull/7","diff_url":"https://github.com/dirtbags/moth/pull/7.diff","patch_url":"https://github.com/dirtbags/moth/pull/7.patch","issue_url":"https://api.github.com/repos/dirtbags/moth/issues/7","number":7,"state":"open","locked":false,"title":"Slackish dev","user":{"login":"slackish","id":3422163,"avatar_url":"https://avatars.githubusercontent.com/u/3422163?v=3","gravatar_id":"","url":"https://api.github.com/users/slackish","html_url":"https://github.com/slackish","followers_url":"https://api.github.com/users/slackish/followers","following_url":"https://api.github.com/users/slackish/following{/other_user}","gists_url":"https://api.github.com/users/slackish/gists{/gist_id}","starred_url":"https://api.github.com/users/slackish/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/slackish/subscriptions","organizations_url":"https://api.github.com/users/slackish/orgs","repos_url":"https://api.github.com/users/slackish/repos","events_url":"https://api.github.com/users/slackish/events{/privacy}","received_events_url":"https://api.github.com/users/slackish/received_events","type":"User","site_admin":false},"body":"Ehh, some stuff.  It's not clean, but would appreciate some feedback.","created_at":"2016-10-18T23:12:49Z","updated_at":"2016-10-19T21:43:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"384dd9a3342b9bdec7ef8dbaabd0cd78dae91b23","assignee":{"login":"pflarr","id":50597,"avatar_url":"https://avatars.githubusercontent.com/u/50597?v=3","gravatar_id":"","url":"https://api.github.com/users/pflarr","html_url":"https://github.com/pflarr","followers_url":"https://api.github.com/users/pflarr/followers","following_url":"https://api.github.com/users/pflarr/following{/other_user}","gists_url":"https://api.github.com/users/pflarr/gists{/gist_id}","starred_url":"https://api.github.com/users/pflarr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pflarr/subscriptions","organizations_url":"https://api.github.com/users/pflarr/orgs","repos_url":"https://api.github.com/users/pflarr/repos","events_url":"https://api.github.com/users/pflarr/events{/privacy}","received_events_url":"https://api.github.com/users/pflarr/received_events","type":"User","site_admin":false},"assignees":[{"login":"pflarr","id":50597,"avatar_url":"https://avatars.githubusercontent.com/u/50597?v=3","gravatar_id":"","url":"https://api.github.com/users/pflarr","html_url":"https://github.com/pflarr","followers_url":"https://api.github.com/users/pflarr/followers","following_url":"https://api.github.com/users/pflarr/following{/other_user}","gists_url":"https://api.github.com/users/pflarr/gists{/gist_id}","starred_url":"https://api.github.com/users/pflarr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pflarr/subscriptions","organizations_url":"https://api.github.com/users/pflarr/orgs","repos_url":"https://api.github.com/users/pflarr/repos","events_url":"https://api.github.com/users/pflarr/events{/privacy}","received_events_url":"https://api.github.com/users/pflarr/received_events","type":"User","site_admin":false},{"login":"nealey","id":423780,"avatar_url":"https://avatars.githubusercontent.com/u/423780?v=3","gravatar_id":"","url":"https://api.github.com/users/nealey","html_url":"https://github.com/nealey","followers_url":"https://api.github.com/users/nealey/followers","following_url":"https://api.github.com/users/nealey/following{/other_user}","gists_url":"https://api.github.com/users/nealey/gists{/gist_id}","starred_url":"https://api.github.com/users/nealey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nealey/subscriptions","organizations_url":"https://api.github.com/users/nealey/orgs","repos_url":"https://api.github.com/users/nealey/repos","events_url":"https://api.github.com/users/nealey/events{/privacy}","received_events_url":"https://api.github.com/users/nealey/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/dirtbags/moth/pulls/7/commits","review_comments_url":"https://api.github.com/repos/dirtbags/moth/pulls/7/comments","review_comment_url":"https://api.github.com/repos/dirtbags/moth/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dirtbags/moth/issues/7/comments","statuses_url":"https://api.github.com/repos/dirtbags/moth/statuses/cf922f32170701e4b5afdfd2c7d7eb9c7b14e65b","head":{"label":"dirtbags:slackish-dev","ref":"slackish-dev","sha":"cf922f32170701e4b5afdfd2c7d7eb9c7b14e65b","user":{"login":"dirtbags","id":17075665,"avatar_url":"https://avatars.githubusercontent.com/u/17075665?v=3","gravatar_id":"","url":"https://api.github.com/users/dirtbags","html_url":"https://github.com/dirtbags","followers_url":"https://api.github.com/users/dirtbags/followers","following_url":"https://api.github.com/users/dirtbags/following{/other_user}","gists_url":"https://api.github.com/users/dirtbags/gists{/gist_id}","starred_url":"https://api.github.com/users/dirtbags/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dirtbags/subscriptions","organizations_url":"https://api.github.com/users/dirtbags/orgs","repos_url":"https://api.github.com/users/dirtbags/repos","events_url":"https://api.github.com/users/dirtbags/events{/privacy}","received_events_url":"https://api.github.com/users/dirtbags/received_events","type":"Organization","site_admin":false},"repo":{"id":50253683,"name":"moth","full_name":"dirtbags/moth","owner":{"login":"dirtbags","id":17075665,"avatar_url":"https://avatars.githubusercontent.com/u/17075665?v=3","gravatar_id":"","url":"https://api.github.com/users/dirtbags","html_url":"https://github.com/dirtbags","followers_url":"https://api.github.com/users/dirtbags/followers","following_url":"https://api.github.com/users/dirtbags/following{/other_user}","gists_url":"https://api.github.com/users/dirtbags/gists{/gist_id}","starred_url":"https://api.github.com/users/dirtbags/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dirtbags/subscriptions","organizations_url":"https://api.github.com/users/dirtbags/orgs","repos_url":"https://api.github.com/users/dirtbags/repos","events_url":"https://api.github.com/users/dirtbags/events{/privacy}","received_events_url":"https://api.github.com/users/dirtbags/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dirtbags/moth","description":"Monarch Of The Hill - base infrastructure for computer-based puzzle contests","fork":false,"url":"https://api.github.com/repos/dirtbags/moth","forks_url":"https://api.github.com/repos/dirtbags/moth/forks","keys_url":"https://api.github.com/repos/dirtbags/moth/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dirtbags/moth/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dirtbags/moth/teams","hooks_url":"https://api.github.com/repos/dirtbags/moth/hooks","issue_events_url":"https://api.github.com/repos/dirtbags/moth/issues/events{/number}","events_url":"https://api.github.com/repos/dirtbags/moth/events","assignees_url":"https://api.github.com/repos/dirtbags/moth/assignees{/user}","branches_url":"https://api.github.com/repos/dirtbags/moth/branches{/branch}","tags_url":"https://api.github.com/repos/dirtbags/moth/tags","blobs_url":"https://api.github.com/repos/dirtbags/moth/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dirtbags/moth/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dirtbags/moth/git/refs{/sha}","trees_url":"https://api.github.com/repos/dirtbags/moth/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dirtbags/moth/statuses/{sha}","languages_url":"https://api.github.com/repos/dirtbags/moth/languages","stargazers_url":"https://api.github.com/repos/dirtbags/moth/stargazers","contributors_url":"https://api.github.com/repos/dirtbags/moth/contributors","subscribers_url":"https://api.github.com/repos/dirtbags/moth/subscribers","subscription_url":"https://api.github.com/repos/dirtbags/moth/subscription","commits_url":"https://api.github.com/repos/dirtbags/moth/commits{/sha}","git_commits_url":"https://api.github.com/repos/dirtbags/moth/git/commits{/sha}","comments_url":"https://api.github.com/repos/dirtbags/moth/comments{/number}","issue_comment_url":"https://api.github.com/repos/dirtbags/moth/issues/comments{/number}","contents_url":"https://api.github.com/repos/dirtbags/moth/contents/{+path}","compare_url":"https://api.github.com/repos/dirtbags/moth/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dirtbags/moth/merges","archive_url":"https://api.github.com/repos/dirtbags/moth/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dirtbags/moth/downloads","issues_url":"https://api.github.com/repos/dirtbags/moth/issues{/number}","pulls_url":"https://api.github.com/repos/dirtbags/moth/pulls{/number}","milestones_url":"https://api.github.com/repos/dirtbags/moth/milestones{/number}","notifications_url":"https://api.github.com/repos/dirtbags/moth/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dirtbags/moth/labels{/name}","releases_url":"https://api.github.com/repos/dirtbags/moth/releases{/id}","deployments_url":"https://api.github.com/repos/dirtbags/moth/deployments","created_at":"2016-01-23T19:08:29Z","updated_at":"2016-10-15T04:26:52Z","pushed_at":"2016-10-19T21:33:32Z","git_url":"git://github.com/dirtbags/moth.git","ssh_url":"git@github.com:dirtbags/moth.git","clone_url":"https://github.com/dirtbags/moth.git","svn_url":"https://github.com/dirtbags/moth","homepage":null,"size":58864,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":8,"mirror_url":null,"open_issues_count":1,"forks":8,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"dirtbags:master","ref":"master","sha":"2a7853dba9a55da91ce9426f0d281575887ee8bf","user":{"login":"dirtbags","id":17075665,"avatar_url":"https://avatars.githubusercontent.com/u/17075665?v=3","gravatar_id":"","url":"https://api.github.com/users/dirtbags","html_url":"https://github.com/dirtbags","followers_url":"https://api.github.com/users/dirtbags/followers","following_url":"https://api.github.com/users/dirtbags/following{/other_user}","gists_url":"https://api.github.com/users/dirtbags/gists{/gist_id}","starred_url":"https://api.github.com/users/dirtbags/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dirtbags/subscriptions","organizations_url":"https://api.github.com/users/dirtbags/orgs","repos_url":"https://api.github.com/users/dirtbags/repos","events_url":"https://api.github.com/users/dirtbags/events{/privacy}","received_events_url":"https://api.github.com/users/dirtbags/received_events","type":"Organization","site_admin":false},"repo":{"id":50253683,"name":"moth","full_name":"dirtbags/moth","owner":{"login":"dirtbags","id":17075665,"avatar_url":"https://avatars.githubusercontent.com/u/17075665?v=3","gravatar_id":"","url":"https://api.github.com/users/dirtbags","html_url":"https://github.com/dirtbags","followers_url":"https://api.github.com/users/dirtbags/followers","following_url":"https://api.github.com/users/dirtbags/following{/other_user}","gists_url":"https://api.github.com/users/dirtbags/gists{/gist_id}","starred_url":"https://api.github.com/users/dirtbags/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dirtbags/subscriptions","organizations_url":"https://api.github.com/users/dirtbags/orgs","repos_url":"https://api.github.com/users/dirtbags/repos","events_url":"https://api.github.com/users/dirtbags/events{/privacy}","received_events_url":"https://api.github.com/users/dirtbags/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dirtbags/moth","description":"Monarch Of The Hill - base infrastructure for computer-based puzzle contests","fork":false,"url":"https://api.github.com/repos/dirtbags/moth","forks_url":"https://api.github.com/repos/dirtbags/moth/forks","keys_url":"https://api.github.com/repos/dirtbags/moth/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dirtbags/moth/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dirtbags/moth/teams","hooks_url":"https://api.github.com/repos/dirtbags/moth/hooks","issue_events_url":"https://api.github.com/repos/dirtbags/moth/issues/events{/number}","events_url":"https://api.github.com/repos/dirtbags/moth/events","assignees_url":"https://api.github.com/repos/dirtbags/moth/assignees{/user}","branches_url":"https://api.github.com/repos/dirtbags/moth/branches{/branch}","tags_url":"https://api.github.com/repos/dirtbags/moth/tags","blobs_url":"https://api.github.com/repos/dirtbags/moth/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dirtbags/moth/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dirtbags/moth/git/refs{/sha}","trees_url":"https://api.github.com/repos/dirtbags/moth/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dirtbags/moth/statuses/{sha}","languages_url":"https://api.github.com/repos/dirtbags/moth/languages","stargazers_url":"https://api.github.com/repos/dirtbags/moth/stargazers","contributors_url":"https://api.github.com/repos/dirtbags/moth/contributors","subscribers_url":"https://api.github.com/repos/dirtbags/moth/subscribers","subscription_url":"https://api.github.com/repos/dirtbags/moth/subscription","commits_url":"https://api.github.com/repos/dirtbags/moth/commits{/sha}","git_commits_url":"https://api.github.com/repos/dirtbags/moth/git/commits{/sha}","comments_url":"https://api.github.com/repos/dirtbags/moth/comments{/number}","issue_comment_url":"https://api.github.com/repos/dirtbags/moth/issues/comments{/number}","contents_url":"https://api.github.com/repos/dirtbags/moth/contents/{+path}","compare_url":"https://api.github.com/repos/dirtbags/moth/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dirtbags/moth/merges","archive_url":"https://api.github.com/repos/dirtbags/moth/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dirtbags/moth/downloads","issues_url":"https://api.github.com/repos/dirtbags/moth/issues{/number}","pulls_url":"https://api.github.com/repos/dirtbags/moth/pulls{/number}","milestones_url":"https://api.github.com/repos/dirtbags/moth/milestones{/number}","notifications_url":"https://api.github.com/repos/dirtbags/moth/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dirtbags/moth/labels{/name}","releases_url":"https://api.github.com/repos/dirtbags/moth/releases{/id}","deployments_url":"https://api.github.com/repos/dirtbags/moth/deployments","created_at":"2016-01-23T19:08:29Z","updated_at":"2016-10-15T04:26:52Z","pushed_at":"2016-10-19T21:33:32Z","git_url":"git://github.com/dirtbags/moth.git","ssh_url":"git@github.com:dirtbags/moth.git","clone_url":"https://github.com/dirtbags/moth.git","svn_url":"https://github.com/dirtbags/moth","homepage":null,"size":58864,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":8,"mirror_url":null,"open_issues_count":1,"forks":8,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dirtbags/moth/pulls/7"},"html":{"href":"https://github.com/dirtbags/moth/pull/7"},"issue":{"href":"https://api.github.com/repos/dirtbags/moth/issues/7"},"comments":{"href":"https://api.github.com/repos/dirtbags/moth/issues/7/comments"},"review_comments":{"href":"https://api.github.com/repos/dirtbags/moth/pulls/7/comments"},"review_comment":{"href":"https://api.github.com/repos/dirtbags/moth/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dirtbags/moth/pulls/7/commits"},"statuses":{"href":"https://api.github.com/repos/dirtbags/moth/statuses/cf922f32170701e4b5afdfd2c7d7eb9c7b14e65b"}}}}
{"actor":{"display_login":"nealey"}}