Files
off/server.py

133 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Simple web server: one button to turn off all kids' devices."""
import json
from http.server import HTTPServer, BaseHTTPRequestHandler
from devices import shutdown_all
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/" or self.path == "/index.html":
self.send_response(200)
self.send_header("Content-Type", "text/html; charset=utf-8")
self.end_headers()
self.wfile.write(HTML.encode())
else:
self.send_error(404)
def do_POST(self):
if self.path == "/run":
try:
actions = shutdown_all()
status = "ok"
except Exception as e:
actions = [{"icon": "", "title": "Error", "detail": str(e)}]
status = "error"
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"status": status, "actions": actions}).encode())
else:
self.send_error(404)
def log_message(self, format, *args):
pass
HTML = """\
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kids Devices — OFF</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: system-ui, sans-serif;
display: flex; justify-content: center; align-items: center;
min-height: 100vh; background: #1a1a2e; color: #eee;
}
.card {
text-align: center; padding: 3rem; border-radius: 16px;
background: #16213e; box-shadow: 0 8px 32px rgba(0,0,0,.4);
max-width: 420px; width: 90%;
}
h1 { font-size: 1.5rem; margin-bottom: .5rem; }
p { color: #aaa; margin-bottom: 2rem; font-size: .9rem; }
button {
background: #e94560; color: #fff; border: none;
padding: 1rem 2.5rem; font-size: 1.2rem; font-weight: 700;
border-radius: 8px; cursor: pointer; transition: .2s;
}
button:hover { background: #c73650; }
button:disabled { opacity: .5; cursor: wait; }
#output {
margin-top: 1.5rem; text-align: left; display: none;
}
.action-item {
display: flex; align-items: flex-start; gap: .75rem;
padding: .75rem 1rem; margin-bottom: .5rem;
border-radius: 8px; background: #0f3460;
}
.action-item .icon { font-size: 1.3rem; flex-shrink: 0; }
.action-item .info { flex: 1; }
.action-item .title { font-weight: 600; font-size: .95rem; }
.action-item .detail { color: #aaa; font-size: .82rem; margin-top: .15rem; }
</style>
</head>
<body>
<div class="card">
<h1>📺 Kids Devices</h1>
<p>TV + Gabi's computer + Gaja's computer</p>
<button id="btn" onclick="run()">TURN OFF</button>
<div id="output"></div>
</div>
<script>
async function run() {
const btn = document.getElementById('btn');
const out = document.getElementById('output');
btn.disabled = true;
btn.textContent = '';
out.style.display = 'block';
out.innerHTML = '<div class="action-item"><span class="icon">⏳</span><div class="info"><div class="title">Running…</div></div></div>';
try {
const res = await fetch('https://noom.cc/off/run', { method: 'POST' });
const data = await res.json();
if (data.actions && data.actions.length) {
out.innerHTML = data.actions.map(a =>
`<div class="action-item">
<span class="icon">${a.icon}</span>
<div class="info">
<div class="title">${a.title}</div>
<div class="detail">${a.detail}</div>
</div>
</div>`
).join('');
} else {
out.textContent = 'No actions taken.';
}
} catch(e) {
out.innerHTML = `<div class="action-item">
<span class="icon">❌</span>
<div class="info"><div class="title">Error</div><div class="detail">${e.message}</div></div>
</div>`;
}
btn.disabled = false;
btn.textContent = 'TURN OFF';
}
</script>
</body>
</html>
"""
if __name__ == "__main__":
port = int(__import__("os").environ.get("PORT", "10000"))
server = HTTPServer(("0.0.0.0", port), Handler)
print(f"🚀 Open http://localhost:{port}")
server.serve_forever()