From 1a25c050cec714ee5056d656f5e09ee880d7d57f Mon Sep 17 00:00:00 2001
From: johannes walcher <johannes.walcher@stusta.de>
Date: Sat, 4 Aug 2018 16:53:18 +0200
Subject: [PATCH] added haspa_web as module for deployment on nibbler

---
 haspa_web/.gitignore                 |   1 +
 haspa_web/__init__.py                |   0
 haspa_web/__main__.py                |  19 +++++
 haspa_web/haspa.py                   |  59 +++++++++++++++
 haspa_web/html/.keep                 |   0
 haspa_web/templates/current.json.tpl |   4 +
 haspa_web/templates/index.html.tpl   | 105 +++++++++++++++++++++++++++
 haspa_web/test.py                    |  32 ++++++++
 8 files changed, 220 insertions(+)
 create mode 100644 haspa_web/.gitignore
 create mode 100644 haspa_web/__init__.py
 create mode 100644 haspa_web/__main__.py
 create mode 100644 haspa_web/haspa.py
 create mode 100644 haspa_web/html/.keep
 create mode 100644 haspa_web/templates/current.json.tpl
 create mode 100644 haspa_web/templates/index.html.tpl
 create mode 100644 haspa_web/test.py

diff --git a/haspa_web/.gitignore b/haspa_web/.gitignore
new file mode 100644
index 0000000..35b5e99
--- /dev/null
+++ b/haspa_web/.gitignore
@@ -0,0 +1 @@
+/html
diff --git a/haspa_web/__init__.py b/haspa_web/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/haspa_web/__main__.py b/haspa_web/__main__.py
new file mode 100644
index 0000000..6d7a99d
--- /dev/null
+++ b/haspa_web/__main__.py
@@ -0,0 +1,19 @@
+import asyncio
+from haspa_web.haspa import HaspaWeb
+
+def main():
+    """
+    Actually start the shit
+    """
+    loop = asyncio.get_event_loop()
+    haspaweb = HaspaWeb()
+    loop.set_debug(True)
+    try:
+        loop.run_forever()
+    except KeyboardInterrupt:
+        pass
+
+    loop.run_until_complete(haspaweb.teardown())
+
+if __name__ == "__main__":
+    main()
diff --git a/haspa_web/haspa.py b/haspa_web/haspa.py
new file mode 100644
index 0000000..e2bf9cf
--- /dev/null
+++ b/haspa_web/haspa.py
@@ -0,0 +1,59 @@
+import asyncio
+import time
+from pathlib import Path
+
+from hauptbahnhof import Hauptbahnhof
+
+class HaspaWeb:
+    """
+    Recreate the haspa website to represent the current haspa state
+    """
+
+    def __init__(self, loop=None):
+        if not loop:
+            loop = asyncio.get_event_loop()
+
+        self.loop = loop
+        self.hbf = Hauptbahnhof(loop)
+        self.hbf.subscribe('/haspa/status', self.command_state)
+
+        prism_path = Path(__file__).resolve().parent
+        self.config = {}
+        self.config['TEMPLATE_PATH'] = prism_path / "templates"
+        self.config['OUTPUT_PATH'] = prism_path / "html"
+
+    async def teardown(self):
+        """ Clean it up """
+        await self.hbf.teardown()
+
+    async def command_state(self, client, message, _):
+        """ After the state has changed, do something! """
+        del client
+        print(message)
+        if 'haspa' in message:
+            if message['haspa'] in ['open', 'offen', 'auf']:
+                self.set_state(message['haspa'], True)
+            elif message['haspa'] in ['close', 'zu', 'closed']:
+                self.set_state(message['haspa'], False)
+            else:
+                print("Haspa state undetermined: ", message['haspa'])
+
+    def set_state(self, state, is_open):
+        """
+        Export the current haspa state to the website
+
+        The templates and the update procedure have been designed by pt, I do not want to
+        Change any old and glorious routines!
+        """
+        for template in self.config['TEMPLATE_PATH'].glob('*.tpl'):
+            print("Updating templates")
+            outfile = self.config['OUTPUT_PATH'] / template.stem
+
+            with open(str(template), 'r') as orig:
+                content = orig.read()
+                content = content.replace('#state#',
+                                          "offen" if is_open else "geschlossen")
+                content = content.replace('#last_update#',
+                                          time.strftime("%a, %d %b %Y %H:%M:%S"))
+                with open(str(outfile), 'w') as new:
+                    new.write(content)
diff --git a/haspa_web/html/.keep b/haspa_web/html/.keep
new file mode 100644
index 0000000..e69de29
diff --git a/haspa_web/templates/current.json.tpl b/haspa_web/templates/current.json.tpl
new file mode 100644
index 0000000..b1b01ce
--- /dev/null
+++ b/haspa_web/templates/current.json.tpl
@@ -0,0 +1,4 @@
+{
+"state": "#state#",
+"last_update": "#last_update#"
+}
diff --git a/haspa_web/templates/index.html.tpl b/haspa_web/templates/index.html.tpl
new file mode 100644
index 0000000..1c027f0
--- /dev/null
+++ b/haspa_web/templates/index.html.tpl
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Hackerspace: #state#</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
+    <style>
+      /* latin */
+      @font-face {
+        font-family: 'Josefin Slab';
+        font-style: normal;
+        font-weight: 100;
+        src: local('Josefin Slab Thin'), local('JosefinSlab-Thin'), url(css/josefinslab-thin.woff2) format('woff2'), url(css/josefinslab-thin.woff) format('woff');
+        unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
+      }
+      /* latin */
+      @font-face {
+        font-family: 'Josefin Slab';
+        font-style: normal;
+        font-weight: 400;
+        src: local('Josefin Slab'), local('JosefinSlab'), url(css/josefinslab.woff2) format('woff2'), url(css/josefinslab.woff) format('woff');
+        unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
+      }
+
+      * {
+        transition: all 0.3s ease;
+      }
+
+      html, body {
+        height: 100%;
+        width: 100%;
+        margin: 0;
+        padding: 0;
+        font-family: "Josefin Slab", serif;
+        font-weight: 100;
+      }
+
+      body {
+	position: relative;
+      }
+
+      body.offen {
+        background: #55ee33;
+      }
+      body.geschlossen {
+        background: #ee5555;
+      }
+
+      div {
+        position: absolute;
+	top: 50%;
+	left: 50%;
+	transform: translate(-50%, -50%);
+      }
+
+      .offen div:before {
+        content: "Offen";
+        font-size: 25vw;
+      }
+      .geschlossen div:before {
+        content: "Geschlossen";
+        font-size: 15vw;
+      }
+
+      span {
+        position: absolute;
+        bottom: 0.5em;
+        left: 0;
+        right: 0;
+        text-align: center;
+        font-weight: 500;
+      }
+    </style>
+  </head>
+  <body class="#state#">
+    <div>
+    </div>
+    <span id="last_update">
+        Letzte Aktualisierung: #last_update#
+    </span>
+
+    <script>
+      function fetchJSONFile(path, callback) {
+          var httpRequest = new XMLHttpRequest();
+          httpRequest.onreadystatechange = function() {
+              if (httpRequest.readyState === 4) {
+                  if (httpRequest.status === 200) {
+                      var data = JSON.parse(httpRequest.responseText);
+                      if (callback) callback(data);
+                  }
+              }
+          };
+          httpRequest.open('GET', path);
+          httpRequest.send();
+      }
+
+      setInterval(function() {
+        fetchJSONFile('current.json?time=' + Math.floor(Date.now() / 1000), function(data){
+          document.body.className = data.state;
+          document.getElementById('last_update').innerHTML = 'Letzte Aktualisierung: ' + data.last_update;
+        });
+      }, 4200);
+    </script>
+  </body>
+</html>
diff --git a/haspa_web/test.py b/haspa_web/test.py
new file mode 100644
index 0000000..635dd0b
--- /dev/null
+++ b/haspa_web/test.py
@@ -0,0 +1,32 @@
+import asyncio
+from hauptbahnhof import Hauptbahnhof
+
+from haspa_web.haspa import HaspaWeb
+
+async def test(loop):
+    testbf = Hauptbahnhof(loop=loop)
+    await asyncio.sleep(2)
+    # Now everythin should be set up
+
+    await testbf.publish("/haspa/status", {'haspa':"offen"})
+
+    # The module is not sending any status back
+    try:
+        await testbf.teardown()
+    except asyncio.CancelledError:
+        pass
+
+def main():
+    loop = asyncio.get_event_loop()
+    lib = HaspaWeb(loop=loop)
+
+    result = loop.run_until_complete(test(loop))
+    loop.run_until_complete(lib.teardown())
+
+    if result:
+        exit(0)
+    else:
+        exit(1)
+
+if __name__=="__main__":
+    main()
-- 
GitLab