Files
singular-particular-space/ToolsnToys/Meshagora/meshagora.py
JL Kruger 5422131782 Initial commit — Singular Particular Space v1
Homepage (site/index.html): integration-v14 promoted, Writings section
integrated with 33 pieces clustered by type (stories/essays/miscellany),
Writings welcome lightbox, content frame at 98% opacity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 12:09:22 +02:00

1416 lines
51 KiB
Python

import os
import io
import re
import socket
import sqlite3
import subprocess
import functools
from flask import Flask, request, session, redirect, url_for, Response
from markupsafe import escape
# ---------------------------------------------------------------------------
# 1. EMOJI POOL + KEY GENERATOR
# ---------------------------------------------------------------------------
EMOJI_POOL = [
"😀","😂","😍","😎","😭","😡","🥰","🤔","😴","🤯",
"🎉","🔥","💀","👻","🌙","","🌈","🍎","🍕","🎸",
"🐶","🐱","🐸","🦊","🐺","🐻","🦁","🐯","🦋","🐙",
"🌺","🍀","🌊","","🏆","🎯","🔑","💎","🛸","🎭",
"🌋","🧊","🍄","🦄","🔮","🗝️","🧲","🎪",
]
def generate_emoji_key(length):
return "".join(EMOJI_POOL[b % len(EMOJI_POOL)] for b in os.urandom(length))
# ---------------------------------------------------------------------------
# 2. MODULE-LEVEL STATE
# ---------------------------------------------------------------------------
ADMIN_POST_KEY = generate_emoji_key(4)
TRUSTED_POST_KEY = generate_emoji_key(2)
DEFAULT_POST_KEY = generate_emoji_key(2)
QR_VISIBLE = True
def get_all_local_ips():
"""Return list of (ip, iface_name) for all non-loopback IPv4 interfaces."""
results = []
# Method 1: ifconfig (net-tools) — uses socket ioctl, no netlink needed.
# Works in Termux. Install with: pkg install net-tools
try:
out = subprocess.run(
['ifconfig'], capture_output=True, text=True, timeout=3
).stdout
current_iface = None
for line in out.splitlines():
# New-style: "wlan0: flags=..." Old-style: "wlan0 Link encap:..."
m = re.match(r'^(\S+?)(?::\s+flags=|\s+Link)', line)
if m:
current_iface = m.group(1).rstrip(':')
# New-style: "inet 192.x.x.x" Old-style: "inet addr:192.x.x.x"
m = re.search(r'inet\s+(?:addr:)?(\d+\.\d+\.\d+\.\d+)', line)
if m and current_iface:
ip = m.group(1)
if not ip.startswith('127.'):
results.append((ip, current_iface))
if results:
return results
except Exception:
pass
# Method 2: ip addr (iproute2) — works on desktop Linux, but requires
# netlink socket permissions not available in Termux by default.
try:
out = subprocess.run(
['ip', 'addr'], capture_output=True, text=True, timeout=3
).stdout
current_iface = None
for line in out.splitlines():
m = re.match(r'^\d+:\s+(\S+?)[@:]', line)
if m:
current_iface = m.group(1)
m = re.match(r'^\s+inet\s+(\d+\.\d+\.\d+\.\d+)/', line)
if m and current_iface:
ip = m.group(1)
if not ip.startswith('127.'):
results.append((ip, current_iface))
except Exception:
pass
return results
def get_hotspot_ip():
ips = get_all_local_ips()
for ip, _ in ips:
if ip.startswith('192.168.') or ip.startswith('10.42.'):
return ip
return ips[0][0] if ips else '127.0.0.1'
def generate_qr_bytes(url):
try:
import qrcode
img = qrcode.make(url)
buf = io.BytesIO()
img.save(buf, format="PNG")
return buf.getvalue()
except Exception:
return b""
HOTSPOT_IP = get_hotspot_ip()
JOIN_URL = f"http://{HOTSPOT_IP}:5000/join"
QR_IMAGE_BYTES = generate_qr_bytes(JOIN_URL)
# ---------------------------------------------------------------------------
# 3. FLASK APP
# ---------------------------------------------------------------------------
app = Flask(__name__)
app.secret_key = os.urandom(32)
# ---------------------------------------------------------------------------
# 4. SQLITE
# ---------------------------------------------------------------------------
DB_CONN = sqlite3.connect(":memory:", check_same_thread=False)
DB_CONN.row_factory = sqlite3.Row
def init_db():
cur = DB_CONN.cursor()
cur.executescript("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
session_label TEXT NOT NULL,
username TEXT NOT NULL,
profile_notes TEXT DEFAULT '',
notes_visible INTEGER DEFAULT 1,
post_tier TEXT DEFAULT 'DEFAULT',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS keys (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id),
key_type TEXT NOT NULL,
emoji_code TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS handshakes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
from_user_id INTEGER NOT NULL REFERENCES users(id),
to_user_id INTEGER NOT NULL REFERENCES users(id),
submitted_code TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author_id INTEGER NOT NULL REFERENCES users(id),
content TEXT NOT NULL,
score INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS votes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
post_id INTEGER NOT NULL REFERENCES posts(id),
user_id INTEGER NOT NULL REFERENCES users(id),
direction INTEGER NOT NULL,
weight INTEGER NOT NULL,
UNIQUE(post_id, user_id)
);
CREATE TABLE IF NOT EXISTS reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
post_id INTEGER NOT NULL REFERENCES posts(id),
reporter_id INTEGER NOT NULL REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(post_id, reporter_id)
);
CREATE TABLE IF NOT EXISTS notifications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id),
message TEXT NOT NULL,
read INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
""")
DB_CONN.commit()
init_db()
# ---------------------------------------------------------------------------
# 5. CSS
# ---------------------------------------------------------------------------
BASE_CSS = """
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: #0a0a0f;
color: #c8c8d8;
font-family: 'Courier New', Courier, monospace;
font-size: 15px;
min-height: 100vh;
padding: 8px;
}
a { color: #cc44ff; text-decoration: none; }
a:hover { text-decoration: underline; }
h1, h2, h3 { color: #ff44cc; letter-spacing: 1px; margin-bottom: 8px; }
h1 { font-size: 1.3em; border-bottom: 2px solid #cc44ff; padding-bottom: 4px; margin-bottom: 12px; }
h2 { font-size: 1.1em; }
h3 { font-size: 1em; color: #cc44ff; }
.container { max-width: 600px; margin: 0 auto; }
.card {
border: 1px solid #442255;
background: #0f0f1a;
padding: 12px;
margin-bottom: 10px;
}
.card.pinned-top { border-color: #ff44cc; border-width: 2px; }
.card.pinned-bottom { border-color: #334; border-width: 2px; }
.post-meta { font-size: 0.8em; color: #886699; margin-bottom: 6px; }
.post-content { margin-bottom: 10px; word-break: break-word; line-height: 1.5; }
.spoiler {
background: #330033; color: #330033; cursor: pointer;
padding: 4px; border: 1px solid #660066; user-select: none;
}
.spoiler.revealed { background: transparent; color: inherit; }
.btn {
display: inline-block;
min-height: 48px;
min-width: 48px;
padding: 10px 16px;
border: 1px solid #cc44ff;
background: #1a0a2e;
color: #cc44ff;
cursor: pointer;
font-family: inherit;
font-size: 0.9em;
vertical-align: middle;
text-align: center;
line-height: 1.2;
}
.btn:hover { background: #2a1040; }
.btn.active { background: #440066; color: #ff88ff; }
.btn.danger { border-color: #ff4444; color: #ff4444; background: #1a0a0a; }
.btn.danger:hover { background: #2a0a0a; }
.btn.small { min-height: 36px; padding: 6px 10px; font-size: 0.8em; }
input[type=text], input[type=password], textarea {
background: #0a0a1a;
border: 1px solid #442255;
color: #c8c8d8;
font-family: inherit;
font-size: 0.95em;
padding: 10px;
width: 100%;
min-height: 48px;
margin-bottom: 8px;
}
textarea { min-height: 80px; resize: vertical; }
input[type=text]:focus, input[type=password]:focus, textarea:focus {
outline: none;
border-color: #cc44ff;
}
.form-row { margin-bottom: 10px; }
label { display: block; color: #886699; margin-bottom: 4px; font-size: 0.85em; }
.banner {
border: 1px solid #ff44cc;
background: #1a0020;
padding: 12px;
margin-bottom: 12px;
color: #ff88ff;
}
.banner.error { border-color: #ff4444; background: #1a0000; color: #ff8888; }
.banner.info { border-color: #4488ff; background: #00001a; color: #88aaff; }
.nav {
display: flex;
gap: 4px;
flex-wrap: wrap;
margin-bottom: 16px;
border-bottom: 1px solid #332244;
padding-bottom: 8px;
}
.score { color: #ffcc44; font-weight: bold; }
.score.neg { color: #ff4444; }
.emoji-picker { margin-bottom: 8px; }
.emoji-grid {
display: flex;
flex-wrap: wrap;
gap: 2px;
background: #0f0f1a;
border: 1px solid #332244;
padding: 6px;
max-height: 160px;
overflow-y: auto;
}
.emoji-btn {
font-size: 1.4em;
min-width: 44px;
min-height: 44px;
background: #1a0a2e;
border: 1px solid #332244;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.emoji-btn:hover { background: #2a1040; }
.emoji-display {
font-size: 1.4em;
background: #0a0a1a;
border: 1px solid #442255;
padding: 6px 10px;
min-height: 48px;
display: inline-block;
min-width: 80px;
vertical-align: middle;
letter-spacing: 2px;
}
.tier-admin { color: #ff44cc; }
.tier-trusted { color: #44ccff; }
.tier-default { color: #c8c8d8; }
.tier-restricted { color: #ff4444; }
table { width: 100%; border-collapse: collapse; margin-bottom: 12px; font-size: 0.85em; }
th { background: #1a0a2e; color: #cc44ff; padding: 6px; border: 1px solid #332244; text-align: left; }
td { padding: 6px; border: 1px solid #221133; vertical-align: top; word-break: break-word; }
tr:nth-child(even) td { background: #0d0d18; }
.section { margin-bottom: 20px; }
.friends-toggle { margin-bottom: 12px; }
"""
# ---------------------------------------------------------------------------
# 6. BASE PAGE
# ---------------------------------------------------------------------------
def base_page(title, content, current_user=None):
notif_html = ""
if current_user:
notifs = DB_CONN.execute(
"SELECT message FROM notifications WHERE user_id=? AND read=0 ORDER BY created_at",
(current_user["id"],)
).fetchall()
if notifs:
msgs = "".join(f"<div>{escape(n['message'])}</div>" for n in notifs)
notif_html = f'<div class="banner">{msgs}</div>'
DB_CONN.execute("UPDATE notifications SET read=1 WHERE user_id=? AND read=0", (current_user["id"],))
DB_CONN.commit()
user_info = ""
if current_user:
tier = current_user["post_tier"]
tier_class = f"tier-{tier.lower()}"
label = escape(current_user["session_label"])
user_info = f'<span class="{tier_class}">[{label} · {tier}]</span>'
return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{escape(title)} — MESHAGORA</title>
<style>{BASE_CSS}</style>
</head>
<body>
<div class="container">
<h1>&#9670; MESHAGORA</h1>
<div class="nav">
<a class="btn small" href="/">The Square</a>
<a class="btn small" href="/profile">Profile</a>
<a class="btn small" href="/admin">Admin</a>
{user_info}
</div>
{notif_html}
{content}
</div>
<script>
function appendEmoji(fieldId, displayId, emoji, maxLen) {{
var hidden = document.getElementById(fieldId);
var display = document.getElementById(displayId);
var arr = Array.from(hidden.value);
if (arr.length < maxLen) {{
hidden.value += emoji;
display.textContent = hidden.value;
}}
}}
function clearEmoji(fieldId, displayId) {{
document.getElementById(fieldId).value = '';
document.getElementById(displayId).textContent = '';
}}
</script>
</body>
</html>"""
# ---------------------------------------------------------------------------
# 7. EMOJI PICKER WIDGET
# ---------------------------------------------------------------------------
def emoji_picker(field_name, field_id, max_len=2, current_val=""):
display_id = field_id + "_display"
grid = ""
for em in EMOJI_POOL:
grid += f'<button type="button" class="emoji-btn" onclick="appendEmoji(\'{field_id}\',\'{display_id}\',\'{em}\',{max_len})">{em}</button>'
return f"""
<div class="emoji-picker">
<input type="hidden" name="{field_name}" id="{field_id}" value="{escape(current_val)}">
<div style="margin-bottom:4px;display:flex;align-items:center;gap:8px;">
<span class="emoji-display" id="{display_id}">{escape(current_val)}</span>
<button type="button" class="btn small danger" onclick="clearEmoji('{field_id}','{display_id}')">CLEAR</button>
</div>
<div class="emoji-grid">{grid}</div>
</div>"""
# ---------------------------------------------------------------------------
# 8. HELPER FUNCTIONS
# ---------------------------------------------------------------------------
def get_current_user():
uid = session.get("user_id")
if not uid:
return None
return DB_CONN.execute("SELECT * FROM users WHERE id=?", (uid,)).fetchone()
def get_friend_key(user_id):
row = DB_CONN.execute(
"SELECT emoji_code FROM keys WHERE user_id=? AND key_type='FRIEND'", (user_id,)
).fetchone()
return row["emoji_code"] if row else ""
def get_profile_key(user_id):
row = DB_CONN.execute(
"SELECT emoji_code FROM keys WHERE user_id=? AND key_type='PROFILE'", (user_id,)
).fetchone()
return row["emoji_code"] if row else ""
def are_friends(a_id, b_id):
a_key = get_friend_key(a_id)
b_key = get_friend_key(b_id)
code_ab = a_key + b_key
code_ba = b_key + a_key
ab = DB_CONN.execute(
"SELECT id FROM handshakes WHERE from_user_id=? AND to_user_id=? AND submitted_code=?",
(a_id, b_id, code_ab)
).fetchone()
ba = DB_CONN.execute(
"SELECT id FROM handshakes WHERE from_user_id=? AND to_user_id=? AND submitted_code=?",
(b_id, a_id, code_ba)
).fetchone()
return ab is not None and ba is not None
def get_friends(user_id):
all_users = DB_CONN.execute("SELECT id FROM users WHERE id != ?", (user_id,)).fetchall()
return [u["id"] for u in all_users if are_friends(user_id, u["id"])]
def restrict_user(user_id):
global DEFAULT_POST_KEY
DB_CONN.execute("UPDATE users SET post_tier='RESTRICTED' WHERE id=?", (user_id,))
DB_CONN.commit()
DEFAULT_POST_KEY = generate_emoji_key(2)
def check_auto_restrict(author_id):
author = DB_CONN.execute("SELECT * FROM users WHERE id=?", (author_id,)).fetchone()
if not author or author["post_tier"] == "RESTRICTED":
return
total_users = DB_CONN.execute("SELECT COUNT(*) FROM users").fetchone()[0]
if total_users <= 1:
return
unique_reporters = DB_CONN.execute(
"""SELECT COUNT(DISTINCT r.reporter_id) FROM reports r
JOIN posts p ON r.post_id = p.id
WHERE p.author_id = ? AND r.reporter_id != ?""",
(author_id, author_id)
).fetchone()[0]
threshold = (total_users - 1) * 0.51
if unique_reporters >= threshold:
restrict_user(author_id)
def order_feed(posts):
if not posts:
return []
if len(posts) == 1:
return list(posts)
posts = list(posts)
max_score = max(p["score"] for p in posts)
min_score = min(p["score"] for p in posts)
# Find top pinned (highest score, most recent tiebreak)
top_candidates = [p for p in posts if p["score"] == max_score]
top_pin = max(top_candidates, key=lambda p: p["created_at"])
# Find bottom pinned (lowest score, most recent tiebreak) — must be different from top
remaining = [p for p in posts if p["id"] != top_pin["id"]]
if not remaining:
return [top_pin]
bot_min = min(p["score"] for p in remaining)
# Only pin bottom separately if it's actually different score from top or there are multiple posts
bot_candidates = [p for p in remaining if p["score"] == bot_min]
bot_pin = max(bot_candidates, key=lambda p: p["created_at"])
middle = [p for p in remaining if p["id"] != bot_pin["id"]]
middle.sort(key=lambda p: p["created_at"], reverse=True)
if len(posts) == 2:
return [top_pin, bot_pin]
return [top_pin] + middle + [bot_pin]
def require_admin(f):
@functools.wraps(f)
def decorated(*args, **kwargs):
if not session.get("admin_authed"):
return redirect(url_for("admin"))
return f(*args, **kwargs)
return decorated
def vote_weight(tier):
return {"ADMIN": 1, "TRUSTED": 2, "DEFAULT": 1, "RESTRICTED": 0}.get(tier, 0)
def tier_badge(tier):
cls = f"tier-{tier.lower()}"
return f'<span class="{cls}">[{escape(tier)}]</span>'
def has_reported(post_id, user_id):
return DB_CONN.execute(
"SELECT id FROM reports WHERE post_id=? AND reporter_id=?", (post_id, user_id)
).fetchone() is not None
def report_count(post_id):
return DB_CONN.execute(
"SELECT COUNT(*) FROM reports WHERE post_id=?", (post_id,)
).fetchone()[0]
def user_vote(post_id, user_id):
row = DB_CONN.execute(
"SELECT direction FROM votes WHERE post_id=? AND user_id=?", (post_id, user_id)
).fetchone()
return row["direction"] if row else None
# ---------------------------------------------------------------------------
# 9. ROUTES
# ---------------------------------------------------------------------------
@app.route("/join", methods=["GET", "POST"])
def join():
if session.get("user_id"):
return redirect(url_for("square"))
error = ""
if request.method == "POST":
username = request.form.get("username", "").strip()
profile_key = request.form.get("profile_key", "")
friend_key = request.form.get("friend_key", "")
if not username:
error = "Username required."
elif len(profile_key) < 2:
error = "Profile Key must be 2 emoji."
elif len(friend_key) < 2:
error = "Friend Key must be 2 emoji."
else:
existing = DB_CONN.execute("SELECT id FROM users WHERE username=?", (username,)).fetchone()
if existing:
error = "Username taken."
else:
cur = DB_CONN.execute(
"INSERT INTO users (session_label, username) VALUES (?, ?)",
("?", username)
)
DB_CONN.commit()
uid = cur.lastrowid
label = f"Anon #{uid}"
DB_CONN.execute("UPDATE users SET session_label=? WHERE id=?", (label, uid))
DB_CONN.execute(
"INSERT INTO keys (user_id, key_type, emoji_code) VALUES (?, 'PROFILE', ?)",
(uid, profile_key)
)
DB_CONN.execute(
"INSERT INTO keys (user_id, key_type, emoji_code) VALUES (?, 'FRIEND', ?)",
(uid, friend_key)
)
DB_CONN.commit()
session["user_id"] = uid
session["show_default_key"] = True
return redirect(url_for("square"))
error_html = f'<div class="banner error">{escape(error)}</div>' if error else ""
content = f"""
{error_html}
<div class="card">
<h2>JOIN THE SQUARE</h2>
<p style="color:#886699;font-size:0.85em;margin-bottom:12px;">Choose a secret username. Pick two emoji keys.</p>
<form method="POST">
<div class="form-row">
<label>USERNAME (secret — share only with friends)</label>
<input type="text" name="username" placeholder="e.g. CoolPenguin42" autocomplete="off" autocorrect="off" autocapitalize="off">
</div>
<div class="form-row">
<label>PROFILE KEY (2 emoji — protects your notes)</label>
{emoji_picker("profile_key", "pk_field", max_len=2)}
</div>
<div class="form-row">
<label>FRIEND KEY (2 emoji — for handshakes)</label>
{emoji_picker("friend_key", "fk_field", max_len=2)}
</div>
<button type="submit" class="btn" style="width:100%;min-height:56px;">JOIN</button>
</form>
</div>
"""
return base_page("Join", content)
@app.route("/", methods=["GET", "POST"])
def square():
user = get_current_user()
if not user:
return redirect(url_for("join"))
error = ""
success = ""
# Show default key on first join
if session.pop("show_default_key", False):
success = f"Welcome, {escape(user['session_label'])}! Default Post Key: {DEFAULT_POST_KEY}"
if request.method == "POST":
content = request.form.get("content", "").strip()
post_key = request.form.get("post_key", "")
tier = user["post_tier"]
valid_key = False
if tier == "ADMIN":
valid_key = (post_key == ADMIN_POST_KEY)
elif tier == "TRUSTED":
valid_key = (post_key == TRUSTED_POST_KEY)
elif tier == "DEFAULT":
valid_key = (post_key == DEFAULT_POST_KEY)
elif tier == "RESTRICTED":
admin_key = request.form.get("admin_key", "")
valid_key = (admin_key == ADMIN_POST_KEY)
if not content:
error = "Post content required."
elif not valid_key:
error = "Post key incorrect."
else:
DB_CONN.execute(
"INSERT INTO posts (author_id, content) VALUES (?, ?)",
(user["id"], content)
)
DB_CONN.commit()
return redirect(url_for("square"))
friends_only = request.args.get("friends_only") == "1"
friend_ids = get_friends(user["id"])
if friends_only:
if not friend_ids:
raw_posts = []
else:
placeholders = ",".join("?" * len(friend_ids))
raw_posts = DB_CONN.execute(
f"SELECT * FROM posts WHERE author_id IN ({placeholders}) ORDER BY created_at DESC",
friend_ids
).fetchall()
else:
raw_posts = DB_CONN.execute(
"SELECT * FROM posts ORDER BY created_at DESC"
).fetchall()
ordered = order_feed(raw_posts)
posts_html = ""
for i, post in enumerate(ordered):
author = DB_CONN.execute("SELECT * FROM users WHERE id=?", (post["author_id"],)).fetchone()
is_friend = post["author_id"] in friend_ids
is_own = post["author_id"] == user["id"]
display_name = escape(author["username"]) if (is_friend or is_own) else escape(author["session_label"])
pin_class = ""
if i == 0 and len(ordered) > 1:
pin_class = " pinned-top"
elif i == len(ordered) - 1 and len(ordered) > 1:
pin_class = " pinned-bottom"
rcount = report_count(post["id"])
already_reported = has_reported(post["id"], user["id"])
my_vote = user_vote(post["id"], user["id"])
score_val = post["score"]
score_cls = "score neg" if score_val < 0 else "score"
content_escaped = escape(post["content"])
if rcount > 0:
content_html = f'<span class="spoiler" onclick="this.classList.toggle(\'revealed\')">[REPORTED — click to reveal] {content_escaped}</span>'
else:
content_html = str(content_escaped)
up_active = "active" if my_vote == 1 else ""
down_active = "active" if my_vote == -1 else ""
report_btn = ""
if not is_own:
if already_reported:
report_btn = '<span class="btn small" style="opacity:0.4;cursor:default;">reported</span>'
else:
report_btn = f'''<form method="POST" action="/report" style="display:inline">
<input type="hidden" name="post_id" value="{post['id']}">
<input type="hidden" name="friends_only" value="{'1' if friends_only else '0'}">
<button type="submit" class="btn small danger">report</button>
</form>'''
posts_html += f"""
<div class="card{pin_class}">
<div class="post-meta">{display_name} · <span class="{score_cls}">{score_val:+d}</span></div>
<div class="post-content">{content_html}</div>
<div style="display:flex;gap:4px;flex-wrap:wrap;align-items:center;">
<form method="POST" action="/vote" style="display:inline">
<input type="hidden" name="post_id" value="{post['id']}">
<input type="hidden" name="direction" value="1">
<input type="hidden" name="friends_only" value="{'1' if friends_only else '0'}">
<button type="submit" class="btn small {up_active}">&#9650; up</button>
</form>
<form method="POST" action="/vote" style="display:inline">
<input type="hidden" name="post_id" value="{post['id']}">
<input type="hidden" name="direction" value="-1">
<input type="hidden" name="friends_only" value="{'1' if friends_only else '0'}">
<button type="submit" class="btn small {down_active}">&#9660; down</button>
</form>
{report_btn}
</div>
</div>"""
if not posts_html:
posts_html = '<div class="card"><p style="color:#886699;">No posts yet.</p></div>'
tier = user["post_tier"]
if tier == "ADMIN":
key_label = "Admin Post Key (4 emoji)"
key_picker = emoji_picker("post_key", "postkey_field", max_len=4)
extra_field = ""
elif tier == "TRUSTED":
key_label = "Trusted Post Key (2 emoji)"
key_picker = emoji_picker("post_key", "postkey_field", max_len=2)
extra_field = ""
elif tier == "DEFAULT":
key_label = "Default Post Key (2 emoji)"
key_picker = emoji_picker("post_key", "postkey_field", max_len=2)
extra_field = ""
else: # RESTRICTED
key_label = "Admin Co-Sign Key (4 emoji — admin must approve)"
key_picker = emoji_picker("admin_key", "postkey_field", max_len=4)
extra_field = '<input type="hidden" name="post_key" value="">'
fo_toggle_url = url_for("square") + ("" if friends_only else "?friends_only=1")
fo_label = "&#9733; Friends Only (ON)" if friends_only else "&#9733; Friends Only (OFF)"
fo_active = "active" if friends_only else ""
success_html = f'<div class="banner">{escape(success)}</div>' if success else ""
error_html = f'<div class="banner error">{escape(error)}</div>' if error else ""
content = f"""
{success_html}{error_html}
<div class="friends-toggle">
<a href="{fo_toggle_url}" class="btn {fo_active}">{fo_label}</a>
</div>
<div class="card">
<h2>POST TO THE SQUARE</h2>
<form method="POST">
{extra_field}
<div class="form-row">
<textarea name="content" placeholder="What's on your mind?" rows="3"></textarea>
</div>
<div class="form-row">
<label>{escape(key_label)}</label>
{key_picker}
</div>
<button type="submit" class="btn" style="width:100%;min-height:56px;">POST</button>
</form>
</div>
<div class="section">
<h2>{'FRIENDS FEED' if friends_only else 'THE SQUARE'}</h2>
{posts_html}
</div>
"""
return base_page("The Square", content, current_user=user)
@app.route("/vote", methods=["POST"])
def vote():
user = get_current_user()
if not user:
return redirect(url_for("join"))
post_id = int(request.form.get("post_id", 0))
direction = int(request.form.get("direction", 1))
friends_only = request.form.get("friends_only", "0")
if direction not in (1, -1):
return redirect(url_for("square"))
weight = vote_weight(user["post_tier"])
existing = DB_CONN.execute(
"SELECT id, direction FROM votes WHERE post_id=? AND user_id=?",
(post_id, user["id"])
).fetchone()
if existing:
if existing["direction"] == direction:
DB_CONN.execute("DELETE FROM votes WHERE post_id=? AND user_id=?", (post_id, user["id"]))
else:
DB_CONN.execute(
"UPDATE votes SET direction=?, weight=? WHERE post_id=? AND user_id=?",
(direction, weight, post_id, user["id"])
)
else:
DB_CONN.execute(
"INSERT INTO votes (post_id, user_id, direction, weight) VALUES (?, ?, ?, ?)",
(post_id, user["id"], direction, weight)
)
DB_CONN.execute(
"UPDATE posts SET score=(SELECT COALESCE(SUM(direction*weight),0) FROM votes WHERE post_id=?) WHERE id=?",
(post_id, post_id)
)
DB_CONN.commit()
redirect_url = url_for("square") + ("?friends_only=1" if friends_only == "1" else "")
return redirect(redirect_url)
@app.route("/report", methods=["POST"])
def report():
user = get_current_user()
if not user:
return redirect(url_for("join"))
post_id = int(request.form.get("post_id", 0))
post = DB_CONN.execute("SELECT * FROM posts WHERE id=?", (post_id,)).fetchone()
if not post:
return redirect(url_for("square"))
if post["author_id"] == user["id"]:
return redirect(url_for("square"))
try:
DB_CONN.execute(
"INSERT INTO reports (post_id, reporter_id) VALUES (?, ?)",
(post_id, user["id"])
)
DB_CONN.execute(
"INSERT INTO notifications (user_id, message) VALUES (?, ?)",
(post["author_id"], "One of your posts has been reported.")
)
DB_CONN.commit()
except sqlite3.IntegrityError:
pass
check_auto_restrict(post["author_id"])
return redirect(url_for("square"))
@app.route("/profile", methods=["GET", "POST"])
def profile():
user = get_current_user()
if not user:
return redirect(url_for("join"))
message = ""
error = ""
# Consume handshake message from redirect
hs_msg = session.pop("handshake_msg", None)
if hs_msg:
kind, text = hs_msg
if kind == "error":
error = text
else:
message = text
if request.method == "POST":
action = request.form.get("action", "")
prof_key_submitted = request.form.get("profile_key_input", "")
stored_key = get_profile_key(user["id"])
if action == "edit_notes":
notes = request.form.get("notes", "")
if prof_key_submitted != stored_key:
error = "Profile Key incorrect."
else:
DB_CONN.execute("UPDATE users SET profile_notes=? WHERE id=?", (notes, user["id"]))
DB_CONN.commit()
message = "Notes saved."
user = get_current_user()
elif action == "toggle_visibility":
if prof_key_submitted != stored_key:
error = "Profile Key incorrect."
else:
new_vis = 0 if user["notes_visible"] else 1
DB_CONN.execute("UPDATE users SET notes_visible=? WHERE id=?", (new_vis, user["id"]))
DB_CONN.commit()
message = "Visibility updated."
user = get_current_user()
# Reload user
user = get_current_user()
friend_key_val = get_friend_key(user["id"])
profile_key_val = get_profile_key(user["id"])
# Confirmed friends
friend_ids = get_friends(user["id"])
friends_html = ""
if friend_ids:
for fid in friend_ids:
fr = DB_CONN.execute("SELECT session_label, username FROM users WHERE id=?", (fid,)).fetchone()
friends_html += f'<div class="card" style="padding:8px;">{escape(fr["username"])} ({escape(fr["session_label"])})</div>'
else:
friends_html = '<p style="color:#886699;">No confirmed friends yet.</p>'
# All users for handshake dropdown (excluding self)
all_users = DB_CONN.execute(
"SELECT id, username, session_label FROM users WHERE id != ? ORDER BY session_label",
(user["id"],)
).fetchall()
user_options = "".join(
f'<option value="{escape(u["username"])}">{escape(u["username"])}</option>'
for u in all_users
)
vis_label = "PUBLIC" if user["notes_visible"] else "PRIVATE"
message_html = f'<div class="banner">{escape(message)}</div>' if message else ""
error_html = f'<div class="banner error">{escape(error)}</div>' if error else ""
content = f"""
{message_html}{error_html}
<div class="card section">
<h2>YOUR IDENTITY</h2>
<table>
<tr><th>Session Label</th><td>{escape(user['session_label'])}</td></tr>
<tr><th>Username</th><td>{escape(user['username'])}</td></tr>
<tr><th>Tier</th><td>{tier_badge(user['post_tier'])}</td></tr>
<tr><th>Friend Key</th><td style="font-size:1.4em;letter-spacing:2px;">{escape(friend_key_val)}</td></tr>
<tr><th>Profile Key</th><td style="font-size:1.4em;letter-spacing:2px;">{escape(profile_key_val)}</td></tr>
</table>
</div>
<div class="card section">
<h2>YOUR NOTES <span style="font-size:0.8em;color:#886699;">[{vis_label}]</span></h2>
<form method="POST">
<input type="hidden" name="action" value="edit_notes">
<textarea name="notes" rows="4">{escape(user['profile_notes'])}</textarea>
<label>Profile Key (to save)</label>
{emoji_picker("profile_key_input", "pk_edit_field", max_len=2)}
<button type="submit" class="btn" style="width:100%;">SAVE NOTES</button>
</form>
<form method="POST" style="margin-top:8px;">
<input type="hidden" name="action" value="toggle_visibility">
<label>Profile Key (to toggle visibility)</label>
{emoji_picker("profile_key_input", "pk_toggle_field", max_len=2)}
<button type="submit" class="btn" style="width:100%;">TOGGLE VISIBILITY (now: {vis_label})</button>
</form>
</div>
<div class="card section">
<h2>CONFIRMED FRIENDS</h2>
{friends_html}
</div>
<div class="card section">
<h2>HANDSHAKE</h2>
<p style="color:#886699;font-size:0.85em;margin-bottom:10px;">Exchange usernames and Friend Keys in person, then submit here.</p>
<form method="POST" action="/handshake">
<div class="form-row">
<label>THEIR USERNAME</label>
<select name="target_username" style="background:#0a0a1a;border:1px solid #442255;color:#c8c8d8;font-family:inherit;font-size:0.95em;padding:10px;width:100%;min-height:48px;">
<option value="">-- select --</option>
{user_options}
</select>
</div>
<div class="form-row">
<label>YOUR FRIEND KEY (2 emoji)</label>
{emoji_picker("my_friend_key", "hs_my_field", max_len=2)}
</div>
<div class="form-row">
<label>THEIR FRIEND KEY (2 emoji)</label>
{emoji_picker("their_friend_key", "hs_their_field", max_len=2)}
</div>
<button type="submit" class="btn" style="width:100%;min-height:56px;">SUBMIT HANDSHAKE</button>
</form>
</div>
"""
return base_page("Profile", content, current_user=user)
@app.route("/handshake", methods=["POST"])
def handshake():
user = get_current_user()
if not user:
return redirect(url_for("join"))
target_username = request.form.get("target_username", "")
my_friend_key = request.form.get("my_friend_key", "")
their_friend_key = request.form.get("their_friend_key", "")
target = DB_CONN.execute("SELECT * FROM users WHERE username=?", (target_username,)).fetchone()
valid = (
target is not None
and target["id"] != user["id"]
and my_friend_key == get_friend_key(user["id"])
and their_friend_key == get_friend_key(target["id"])
)
if not valid:
session["handshake_msg"] = ("error", "One or both keys are incorrect.")
return redirect(url_for("profile"))
submitted_code = my_friend_key + their_friend_key
try:
DB_CONN.execute(
"INSERT INTO handshakes (from_user_id, to_user_id, submitted_code) VALUES (?, ?, ?)",
(user["id"], target["id"], submitted_code)
)
DB_CONN.commit()
except sqlite3.IntegrityError:
pass
if are_friends(user["id"], target["id"]):
session["handshake_msg"] = ("success", f"Friendship confirmed with {target['username']}!")
else:
session["handshake_msg"] = ("info", f"Your side submitted. Waiting for {escape(target['session_label'])} to complete the handshake.")
return redirect(url_for("profile"))
@app.route("/admin", methods=["GET", "POST"])
def admin():
error = ""
if request.method == "POST" and not session.get("admin_authed"):
submitted = request.form.get("admin_key", "")
if submitted == ADMIN_POST_KEY:
session["admin_authed"] = True
else:
error = "Incorrect Admin Key."
if not session.get("admin_authed"):
error_html = f'<div class="banner error">{escape(error)}</div>' if error else ""
content = f"""
{error_html}
<div class="card">
<h2>ADMIN LOGIN</h2>
<form method="POST">
<div class="form-row">
<label>Admin Post Key (4 emoji)</label>
{emoji_picker("admin_key", "admin_login_key", max_len=4)}
</div>
<button type="submit" class="btn" style="width:100%;min-height:56px;">LOGIN</button>
</form>
</div>"""
return base_page("Admin Login", content)
# Full admin panel
users = DB_CONN.execute("SELECT * FROM users ORDER BY id").fetchall()
posts = DB_CONN.execute("SELECT * FROM posts ORDER BY id DESC").fetchall()
votes = DB_CONN.execute("SELECT * FROM votes ORDER BY id DESC LIMIT 50").fetchall()
reports_all = DB_CONN.execute("SELECT * FROM reports ORDER BY id DESC LIMIT 50").fetchall()
keys_all = DB_CONN.execute("SELECT * FROM keys ORDER BY id").fetchall()
users_html = ""
for u in users:
tier = u["post_tier"]
users_html += f"""
<tr>
<td>{escape(u['session_label'])}</td>
<td>{escape(u['username'])}</td>
<td>{tier_badge(tier)}</td>
<td style="white-space:nowrap;">
<form method="POST" action="/admin/action" style="display:inline">
<input type="hidden" name="target_id" value="{u['id']}">
<input type="hidden" name="action" value="restrict">
<button class="btn small danger">Restrict</button>
</form>
<form method="POST" action="/admin/action" style="display:inline">
<input type="hidden" name="target_id" value="{u['id']}">
<input type="hidden" name="action" value="unrestrict">
<button class="btn small">Unrestrict</button>
</form>
<form method="POST" action="/admin/action" style="display:inline">
<input type="hidden" name="target_id" value="{u['id']}">
<input type="hidden" name="action" value="promote_trusted">
<button class="btn small">Promote</button>
</form>
<form method="POST" action="/admin/action" style="display:inline">
<input type="hidden" name="target_id" value="{u['id']}">
<input type="hidden" name="action" value="demote_default">
<button class="btn small">Demote</button>
</form>
</td>
</tr>"""
qr_btn_label = "HIDE QR" if QR_VISIBLE else "SHOW QR"
qr_img_html = f'<img src="/qr" style="border:2px solid #cc44ff;max-width:200px;display:block;margin:8px 0;" alt="QR">' if QR_VISIBLE else ""
posts_html = "".join(
f"<tr><td>{p['id']}</td><td>{escape(p['content'][:60])}</td><td>{p['author_id']}</td><td>{p['score']}</td></tr>"
for p in posts
)
votes_html = "".join(
f"<tr><td>{v['id']}</td><td>{v['post_id']}</td><td>{v['user_id']}</td><td>{v['direction']}</td><td>{v['weight']}</td></tr>"
for v in votes
)
reports_html = "".join(
f"<tr><td>{r['id']}</td><td>{r['post_id']}</td><td>{r['reporter_id']}</td></tr>"
for r in reports_all
)
keys_html = "".join(
f"<tr><td>{k['id']}</td><td>{k['user_id']}</td><td>{k['key_type']}</td><td style='font-size:1.3em;letter-spacing:2px;'>{escape(k['emoji_code'])}</td></tr>"
for k in keys_all
)
content = f"""
<div class="card section">
<h2>CURRENT KEYS</h2>
<table>
<tr><th>Admin Post Key</th><td style="font-size:1.5em;letter-spacing:3px;">{escape(ADMIN_POST_KEY)}</td></tr>
<tr><th>Trusted Post Key</th><td style="font-size:1.5em;letter-spacing:3px;">{escape(TRUSTED_POST_KEY)}</td></tr>
<tr><th>Default Post Key</th><td style="font-size:1.5em;letter-spacing:3px;color:#ff44cc;">{escape(DEFAULT_POST_KEY)}</td></tr>
</table>
<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;">
<form method="POST" action="/admin/action">
<input type="hidden" name="action" value="rotate_default_key">
<button class="btn danger">ROTATE DEFAULT KEY</button>
</form>
<form method="POST" action="/admin/action">
<input type="hidden" name="action" value="toggle_qr">
<button class="btn">{qr_btn_label}</button>
</form>
<form method="POST" action="/admin/action">
<input type="hidden" name="action" value="flood_attack">
<button class="btn danger">FLOOD ATTACK</button>
</form>
</div>
{qr_img_html}
</div>
<div class="card section">
<h2>USERS</h2>
<table>
<tr><th>Label</th><th>Username</th><th>Tier</th><th>Actions</th></tr>
{users_html}
</table>
</div>
<div class="card section">
<h2>RAW DB — POSTS</h2>
<table>
<tr><th>id</th><th>content</th><th>author</th><th>score</th></tr>
{posts_html}
</table>
</div>
<div class="card section">
<h2>RAW DB — VOTES (last 50)</h2>
<table>
<tr><th>id</th><th>post</th><th>user</th><th>dir</th><th>wt</th></tr>
{votes_html}
</table>
</div>
<div class="card section">
<h2>RAW DB — REPORTS (last 50)</h2>
<table>
<tr><th>id</th><th>post</th><th>reporter</th></tr>
{reports_html}
</table>
</div>
<div class="card section">
<h2>RAW DB — KEYS</h2>
<table>
<tr><th>id</th><th>user</th><th>type</th><th>code</th></tr>
{keys_html}
</table>
</div>
"""
# ── Platform View ────────────────────────────────────────────────────────
doxx_rows = DB_CONN.execute("""
SELECT u.id, u.session_label, u.username, u.post_tier,
COUNT(DISTINCT p.id) AS post_count,
COALESCE(SUM(p.score), 0) AS net_score
FROM users u
LEFT JOIN posts p ON p.author_id = u.id
GROUP BY u.id
ORDER BY u.id
""").fetchall()
hs_rows = DB_CONN.execute("""
SELECT h.from_user_id, h.to_user_id,
u1.session_label AS from_label,
u2.session_label AS to_label,
u1.username AS from_name,
u2.username AS to_name
FROM handshakes h
JOIN users u1 ON h.from_user_id = u1.id
JOIN users u2 ON h.to_user_id = u2.id
ORDER BY h.id
""").fetchall()
# Build directed-pair set once; check both directions for CONFIRMED
hs_pairs = {(r["from_user_id"], r["to_user_id"]) for r in hs_rows}
seen_pairs = set()
graph_rows = []
for r in hs_rows:
a, b = r["from_user_id"], r["to_user_id"]
key = (min(a, b), max(a, b))
if key in seen_pairs:
continue
seen_pairs.add(key)
confirmed = (a, b) in hs_pairs and (b, a) in hs_pairs
graph_rows.append((r, confirmed))
def is_friends_pair(id_a, id_b):
return (id_a, id_b) in hs_pairs and (id_b, id_a) in hs_pairs
vote_corr = DB_CONN.execute("""
SELECT v.user_id AS voter_id,
uv.session_label AS voter_label,
uv.username AS voter_name,
p.author_id,
ua.session_label AS author_label,
ua.username AS author_name,
SUM(v.direction * v.weight) AS net
FROM votes v
JOIN posts p ON v.post_id = p.id
JOIN users uv ON v.user_id = uv.id
JOIN users ua ON p.author_id = ua.id
WHERE v.user_id != p.author_id
GROUP BY v.user_id, p.author_id
ORDER BY ABS(SUM(v.direction * v.weight)) DESC
""").fetchall()
report_corr = DB_CONN.execute("""
SELECT r.reporter_id,
ur.session_label AS reporter_label,
ur.username AS reporter_name,
p.author_id,
ua.session_label AS author_label,
ua.username AS author_name,
COUNT(*) AS count
FROM reports r
JOIN posts p ON r.post_id = p.id
JOIN users ur ON r.reporter_id = ur.id
JOIN users ua ON p.author_id = ua.id
WHERE r.reporter_id != p.author_id
GROUP BY r.reporter_id, p.author_id
ORDER BY COUNT(*) DESC
""").fetchall()
# Build HTML for Panel 1
doxx_html = ""
for r in doxx_rows:
net = r["net_score"]
net_cls = "neg" if net < 0 else ""
doxx_html += f"""<tr>
<td>{escape(r['session_label'])}</td>
<td>{escape(r['username'])}</td>
<td>{tier_badge(r['post_tier'])}</td>
<td>{r['post_count']}</td>
<td class="score {net_cls}">{net:+d}</td>
</tr>"""
# Build HTML for Panel 2
graph_html = ""
for r, confirmed in graph_rows:
status_color = "#44ccff" if confirmed else "#886699"
status_text = "CONFIRMED" if confirmed else "PENDING"
graph_html += f"""<tr>
<td>{escape(r['from_label'])} · {escape(r['from_name'])}</td>
<td>{escape(r['to_label'])} · {escape(r['to_name'])}</td>
<td style="color:{status_color};font-weight:bold;">{status_text}</td>
</tr>"""
# Build HTML for Panel 3 — votes
vote_corr_html = ""
for r in vote_corr:
net = r["net"]
net_cls = "neg" if net < 0 else ""
friends_badge = ' <span style="color:#44ccff;font-size:0.8em;">[FRIENDS]</span>' \
if is_friends_pair(r["voter_id"], r["author_id"]) else ""
vote_corr_html += f"""<tr>
<td>{escape(r['voter_label'])} · {escape(r['voter_name'])}</td>
<td>{escape(r['author_label'])} · {escape(r['author_name'])}</td>
<td class="score {net_cls}">{net:+d}</td>
<td>{friends_badge}</td>
</tr>"""
# Build HTML for Panel 3 — reports
report_corr_html = ""
for r in report_corr:
friends_badge = ' <span style="color:#44ccff;font-size:0.8em;">[FRIENDS]</span>' \
if is_friends_pair(r["reporter_id"], r["author_id"]) else ""
count_cls = "tier-restricted" if r["count"] >= 3 else "tier-default"
report_corr_html += f"""<tr>
<td>{escape(r['reporter_label'])} · {escape(r['reporter_name'])}</td>
<td>{escape(r['author_label'])} · {escape(r['author_name'])}</td>
<td class="{count_cls}">{r['count']}</td>
<td>{friends_badge}</td>
</tr>"""
platform_view_html = f"""
<h2 style="color:#ff44cc;border-top:2px solid #cc44ff;padding-top:12px;margin-top:8px;">
&#9672; WHAT THE PLATFORM SEES
</h2>
<div class="card section">
<h2>DEANONYMIZATION &mdash; WHO IS WHO</h2>
<table>
<tr><th>Session Label</th><th>Username</th><th>Tier</th><th>Posts</th><th>Net Score</th></tr>
{doxx_html}
</table>
</div>
<div class="card section">
<h2>SOCIAL GRAPH &mdash; ALL CONNECTIONS</h2>
<table>
<tr><th>User A</th><th>User B</th><th>Status</th></tr>
{graph_html}
</table>
</div>
<div class="card section">
<h2>BEHAVIORAL CORRELATIONS &mdash; WHAT THE PLATFORM INFERS</h2>
<h3 style="color:#c8c8d8;margin-top:8px;">Votes</h3>
<table>
<tr><th>Voter</th><th>Author</th><th>Net Vote</th><th>Friends?</th></tr>
{vote_corr_html}
</table>
<h3 style="color:#c8c8d8;margin-top:16px;">Reports</h3>
<table>
<tr><th>Reporter</th><th>Author</th><th>Count</th><th>Friends?</th></tr>
{report_corr_html}
</table>
</div>
"""
content += platform_view_html
return base_page("Admin Panel", content)
@app.route("/admin/action", methods=["POST"])
@require_admin
def admin_action():
global DEFAULT_POST_KEY, QR_VISIBLE, QR_IMAGE_BYTES
action = request.form.get("action", "")
target_id = request.form.get("target_id", None)
if action == "restrict" and target_id:
restrict_user(int(target_id))
elif action == "unrestrict" and target_id:
DB_CONN.execute("UPDATE users SET post_tier='DEFAULT' WHERE id=?", (int(target_id),))
DB_CONN.commit()
elif action == "promote_trusted" and target_id:
DB_CONN.execute("UPDATE users SET post_tier='TRUSTED' WHERE id=?", (int(target_id),))
DB_CONN.commit()
elif action == "demote_default" and target_id:
DB_CONN.execute("UPDATE users SET post_tier='DEFAULT' WHERE id=?", (int(target_id),))
DB_CONN.commit()
elif action == "rotate_default_key":
DEFAULT_POST_KEY = generate_emoji_key(2)
elif action == "toggle_qr":
QR_VISIBLE = not QR_VISIBLE
elif action == "flood_attack":
for i in range(5):
bot_name = f"Bot_{os.urandom(2).hex()}"
cur = DB_CONN.execute(
"INSERT INTO users (session_label, username, post_tier) VALUES (?, ?, 'DEFAULT')",
("?", bot_name)
)
DB_CONN.commit()
bot_id = cur.lastrowid
bot_label = f"Anon #{bot_id}"
DB_CONN.execute("UPDATE users SET session_label=? WHERE id=?", (bot_label, bot_id))
flood_msgs = [
"SYSTEM NOTICE: All users must re-register.",
"FREE COINS click here [link removed by admin]",
"Did you know? Your data is being collected.",
"ALERT: Someone knows your real name.",
"Join the resistance. Ask me how.",
]
DB_CONN.execute(
"INSERT INTO posts (author_id, content) VALUES (?, ?)",
(bot_id, flood_msgs[i % len(flood_msgs)])
)
pk = generate_emoji_key(2)
fk = generate_emoji_key(2)
DB_CONN.execute("INSERT INTO keys (user_id, key_type, emoji_code) VALUES (?, 'PROFILE', ?)", (bot_id, pk))
DB_CONN.execute("INSERT INTO keys (user_id, key_type, emoji_code) VALUES (?, 'FRIEND', ?)", (bot_id, fk))
DB_CONN.commit()
return redirect(url_for("admin"))
@app.route("/qr")
def qr():
if not QR_VISIBLE:
return Response("Not found", status=404)
return Response(QR_IMAGE_BYTES, mimetype="image/png")
# ---------------------------------------------------------------------------
# 10. ENTRY POINT
# ---------------------------------------------------------------------------
if __name__ == "__main__":
all_ips = get_all_local_ips()
print("=" * 50)
print("MESHAGORA v2.3 — SOCIAL SANDBOX")
print(f"Admin Post Key : {ADMIN_POST_KEY}")
print(f"Trusted Post Key : {TRUSTED_POST_KEY}")
print(f"Default Post Key : {DEFAULT_POST_KEY}")
print("-" * 50)
if all_ips:
first = True
for ip, iface in all_ips:
label = "Join URL :" if first else "Also try :"
first = False
print(f"{label} http://{ip}:5000/join ({iface})")
else:
print(f"Join URL : {JOIN_URL} (detection failed)")
print(f"QR code : http://{HOTSPOT_IP}:5000/qr")
print("If no URL works, run: ifconfig | grep inet")
print("=" * 50)
app.run(host="0.0.0.0", port=5000, debug=False, threaded=False)