Browse Source

Broke the templates out into actual template files, added an embedded iframe that auto refreshes to keep the list updated

Kirk Trombley 5 years ago
parent
commit
cc87c602b3
3 changed files with 132 additions and 100 deletions
  1. 19 100
      app.py
  2. 45 0
      templates/embedded_body.html
  3. 68 0
      templates/main_page.html

+ 19 - 100
app.py

@@ -5,9 +5,10 @@ from collections import defaultdict
 from datetime import timedelta
 
 import toml
-from flask import Flask, jsonify, render_template_string
+from flask import Flask, jsonify, render_template
 
 IDLE_TIMEOUT = timedelta(minutes=5)
+REFRESH_RATE = 60 # seconds
 
 app = Flask(__name__)
 
@@ -21,14 +22,10 @@ def parse_ts_response(response):
     return [{k: v for k, v in pr} for pr in pairs]
 
 
+def query_ts(host, port, username, password):
+    login = f"login {username} {password}\n".encode("utf-8")
 
-def get_users():
-    with open("secret.toml") as infile:
-        cfg = toml.load(infile)
-
-    login = ("login %s %s\n" % (cfg["user"], cfg["pass"])).encode("utf-8")
-
-    with Telnet(cfg["host"], cfg["port"], 5) as tn:
+    with Telnet(host, port, 5) as tn:
         print("connection")
         print(tn.read_until(b"\n").decode("utf-8"))
         print(tn.read_until(b"\n").decode("utf-8"))
@@ -83,6 +80,14 @@ def get_users():
         print("after quit")
         print(tn.read_until(b"\n").decode("utf-8"))
 
+    return client_info, channels
+
+
+def get_users():
+    with open("secret.toml") as infile:
+        cfg = toml.load(infile)
+
+    client_info, channels = query_ts(cfg["host"], cfg["port"], cfg["user"], cfg["pass"])
 
     users = []
     channel_users = defaultdict(list)
@@ -113,98 +118,12 @@ def get_status():
 
 @app.route("/page")
 def get_status_page():
-    # JS adapted from
-    # https://stackoverflow.com/questions/6152522/how-can-i-make-a-paragraph-bounce-around-in-a-div
-    return render_template_string("""
-        <!doctype html>
-        <title>Teamspeak Server Status</title>
-        <style>
-        body {
-            margin: 0px 0px 0px 0px;
-            padding: 0px 0px 0px 0px;
-            font-family: verdana, arial, helvetica, sans-serif;
-            color: #ccc;
-            background-color: #333;
-        }
-        h1 {
-            font-size: 24px;
-            line-height: 44px;
-            font-weight: bold;
-            margin-top: 0;
-            margin-bottom: 0;
-        }
-        h2 {
-            font-size: 18px;
-            line-height: 20px;
-            margin-top: 0;
-            margin-left: 15px;
-            margin-bottom: -10px;
-        }
-        #bounceBox {
-            position: absolute;
-            top: 0;
-            right: 0;
-            bottom: 0;
-            left: 0;
-        }
-        #bouncer {
-            position: absolute;
-        }
-        </style>
-        <script>
-            let vx = 3;
-            let vy = 2;
-            const buffer = 5;
-
-            const hitLR = (el, bounding) => {
-                if (el.offsetLeft <= buffer && vx < 0) {
-                    vx = -1 * vx;
-                }
-                if ((el.offsetLeft + el.offsetWidth) >= (bounding.offsetWidth - buffer)) {
-                    vx = -1 * vx;
-                }
-                if (el.offsetTop <= buffer && vy < 0) {
-                    vy = -1 * vy;
-                }
-                if ((el.offsetTop + el.offsetHeight) >= (bounding.offsetHeight - buffer)) {
-                    vy = -1 * vy;
-                }
-            }
-
-            const mover = (el, bounding) => {
-                hitLR(el, bounding);
-                el.style.left = el.offsetLeft + vx + 'px';
-                el.style.top = el.offsetTop + vy + 'px';
-                setTimeout(function() {
-                    mover(el, bounding);
-                }, 30);
-            }
-
-            setTimeout(() => mover(
-                document.getElementById("bouncer"),
-                document.getElementById("bounceBox")
-            ), 30);
-        </script>
-        <body>
-            <div id="bounceBox">
-                <div id="bouncer">
-                    <h1>TeamSpeak Server Status</h1>
-                    {% if users|length == 0 %}
-                    No one in teamspeak!
-                    {% else %}
-                        {% for channel, people in users.items() %}
-                            <h2>{{ channel }}</h2>
-                            <ul>
-                            {% for user in people %}
-                                <li>{{ user }}</li>
-                            {% endfor %}
-                            </ul>
-                        {% endfor %}
-                    {% endif %}
-                </div>
-            </div>
-        </body>
-    """, users=get_users()[1])
+    return render_template("main_page.html")
+
+
+@app.route("/page_body")
+def get_page_body():
+    return render_template("embedded_body.html", users=get_users()[1], refresh_rate=REFRESH_RATE)
 
 
 if __name__ == "__main__":

+ 45 - 0
templates/embedded_body.html

@@ -0,0 +1,45 @@
+<!-- This page is used as an iframe in the main page -->
+<!-- This allows it to auto-refresh without interrupting the bouncing -->
+<meta http-equiv="refresh" content="{{ refresh_rate }}">
+<style>
+    h1 {
+        font-size: 24px;
+        line-height: 44px;
+        font-weight: bold;
+        margin-top: 0;
+        margin-bottom: 0;
+    }
+    h2 {
+        font-size: 18px;
+        line-height: 20px;
+        margin-top: 0;
+        margin-left: 15px;
+        margin-bottom: -10px;
+    }
+</style>
+<script type="text/javascript">
+    // Inherits the styling from the page embedding this
+    window.onload = function() {
+        if (parent) {
+            var oHead = document.getElementsByTagName("head")[0];
+            var arrStyleSheets = parent.document.getElementsByTagName("style");
+            for (var i = 0; i < arrStyleSheets.length; i++)
+                oHead.appendChild(arrStyleSheets[i].cloneNode(true));
+        }
+    }
+</script>
+<body>
+    <h1>TeamSpeak Server Status</h1>
+    {% if users|length == 0 %}
+    No one in teamspeak!
+    {% else %}
+        {% for channel, people in users.items() %}
+            <h2>{{ channel }}</h2>
+            <ul>
+            {% for user in people %}
+                <li>{{ user }}</li>
+            {% endfor %}
+            </ul>
+        {% endfor %}
+    {% endif %}
+</body>

+ 68 - 0
templates/main_page.html

@@ -0,0 +1,68 @@
+<!doctype html>
+<title>Teamspeak Server Status</title>
+<style>
+    body {
+        margin: 0px 0px 0px 0px;
+        padding: 0px 0px 0px 0px;
+        font-family: verdana, arial, helvetica, sans-serif;
+        color: #ccc;
+        background-color: #333;
+    }
+    #bounceBox {
+        position: absolute;
+        top: 0;
+        right: 0;
+        bottom: 0;
+        left: 0;
+    }
+    #bouncer {
+        position: absolute;
+    }
+</style>
+<script>
+    // JS adapted from
+    // https://stackoverflow.com/questions/6152522/how-can-i-make-a-paragraph-bounce-around-in-a-div
+    let vx = 3;
+    let vy = 2;
+    const buffer = 5;
+
+    const hitLR = (el, bounding) => {
+        if (el.offsetLeft <= buffer && vx < 0) {
+            vx = -1 * vx;
+        }
+        if ((el.offsetLeft + el.offsetWidth) >= (bounding.offsetWidth - buffer)) {
+            vx = -1 * vx;
+        }
+        if (el.offsetTop <= buffer && vy < 0) {
+            vy = -1 * vy;
+        }
+        if ((el.offsetTop + el.offsetHeight) >= (bounding.offsetHeight - buffer)) {
+            vy = -1 * vy;
+        }
+    }
+
+    const mover = (el, bounding) => {
+        hitLR(el, bounding);
+        el.style.left = el.offsetLeft + vx + 'px';
+        el.style.top = el.offsetTop + vy + 'px';
+        setTimeout(function() {
+            mover(el, bounding);
+        }, 30);
+    }
+
+    setTimeout(() => mover(
+        document.getElementById("bouncer"),
+        document.getElementById("bounceBox")
+    ), 30);
+
+    // makes the iframe have the appropriate height
+    const resizeIframe = (obj) => {
+        obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
+        obj.style.width = obj.contentWindow.document.body.scrollWidth + 'px';
+    }
+</script>
+<body>
+    <div id="bounceBox">
+        <iframe id="bouncer" frameborder="0" src="{{ url_for('get_page_body') }}" scrolling="no" onload="resizeIframe(this)"></iframe>
+    </div>
+</body>