gap-fixes: favicon.svg, og.png social card, header account/balance chip, operator reply form in /admin
This commit is contained in:
63
app.py
63
app.py
@@ -109,6 +109,8 @@ BASE = """<!doctype html><html lang=en><head><meta charset=utf-8><meta name=view
|
||||
<meta property="og:title" content="DARK0RBITS — The Operator's Toolbox">
|
||||
<meta property="og:description" content="No-KYC network toolbox for humans and AI agents. BTC only. 12 tools, every one with a JSON API.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:image" content="https://dark0rbits.thetempleofdoom.com/og.png">
|
||||
<link rel="icon" href="/favicon.svg">
|
||||
<meta property="og:url" content="https://dark0rbits.thetempleofdoom.com">
|
||||
<meta name=robots content="index,follow">
|
||||
<meta name=theme-color content="#070a13">
|
||||
@@ -191,7 +193,7 @@ li{text-align:left;margin:.2rem 0}
|
||||
<a href=/inbox class={{o(inbox)}}>INBOX</a><a href=/passport class={{o(passport)}}>PASSPORT</a>
|
||||
<a href=/pass class={{o(pass)}}>PASS</a><a href=/keys class={{o(keys)}}>KEYS</a><a href=/tools class={{o(tools)}}>TOOLS</a>
|
||||
</div>
|
||||
<button class=burger id=burger onclick="drw()">☰</button>
|
||||
<div id="acct">{{acct}}</div><button class=burger id=burger onclick="drw()">☰</button>
|
||||
</div></header>
|
||||
<div class=drawer id=drawer>
|
||||
<div class=dhead><span class=logo style=font-size:.85rem>DARK0RBITS — MAP</span><button class=burger onclick="drw()">✕</button></div>
|
||||
@@ -277,8 +279,20 @@ def kv(pairs):
|
||||
|
||||
def page(sec, body):
|
||||
n1, n2 = NEBULAS.get(sec, ("rgba(120,85,255,.16)", "rgba(0,190,255,.10)"))
|
||||
uid = current_user_id()
|
||||
acct = ""
|
||||
if uid:
|
||||
try:
|
||||
con = db()
|
||||
u = con.execute("SELECT username FROM users WHERE id=?", (uid,)).fetchone()
|
||||
bal = get_balance(uid)
|
||||
pas = has_pass(uid)
|
||||
acct = ('<a href=/keys style="color:var(--acc2);text-decoration:none;font-size:.72rem">' +
|
||||
("★ PASS · " if pas else "") + "$" + f"{bal/100:.2f}" + " · " + esc(u["username"]) + "</a>")
|
||||
except Exception:
|
||||
acct = ""
|
||||
return render_template_string(BASE, body=body, bmac=BMAC, o=lambda s: "on" if s == sec else "",
|
||||
n1=n1, n2=n2)
|
||||
n1=n1, n2=n2, acct=acct)
|
||||
|
||||
def how(steps):
|
||||
lis = "".join(f"<li>{esc(s)}</li>" for s in steps)
|
||||
@@ -1535,6 +1549,17 @@ def passport():
|
||||
<div class=card style=color:var(--dim)>API: GET /api/passport (cookie auth) → badge JSON. Embed in your agent's llms.txt / tool card.</div>"""
|
||||
return page("home", body)
|
||||
|
||||
@app.route("/admin/reply", methods=["POST"])
|
||||
def admin_reply():
|
||||
if not request.cookies.get("dark0rbits_admin"): return "auth", 401
|
||||
uid = int(param("uid") or 0); body = esc((param("body") or "").strip()[:4000])
|
||||
if uid and body:
|
||||
con = db()
|
||||
con.execute("INSERT INTO messages(user_id,sender,body,created) VALUES(?,?,?,?)", (uid, "operator", body, int(time.time())))
|
||||
con.commit()
|
||||
resp = Response(status=302); resp.headers["Location"] = "/admin"
|
||||
return resp
|
||||
|
||||
@app.route("/api/passport")
|
||||
def api_passport():
|
||||
uid = current_user_id()
|
||||
@@ -1693,9 +1718,15 @@ def admin():
|
||||
msgs_html = "".join(f'<div class=msg><div class=who>{esc(m["username"])} · {time.strftime("%b %d %H:%M", time.localtime(m["created"]))}</div>{m["body"]}</div>' for m in msgs) or '<div style=color:var(--dim)>empty</div>'
|
||||
opens = con.execute("SELECT te.*, tr.filename FROM track_events te JOIN trackables tr ON tr.id=te.trackable_id ORDER BY te.id DESC LIMIT 30").fetchall()
|
||||
opens_html = "".join(f"<tr><td>{esc(o['filename'])}</td><td>{esc(o['ip'])}</td><td>{esc(o['ua'][:50])}</td><td>{time.strftime('%b %d %H:%M', time.localtime(o['ts']))}</td></tr>" for o in opens)
|
||||
reply_to = param("reply") or ""
|
||||
reply_html = ""
|
||||
if reply_to:
|
||||
r = con.execute("SELECT username FROM users WHERE id=?", (reply_to,)).fetchone()
|
||||
if r: reply_html = f'<div class=card><b>Reply to {esc(r["username"])}</b><form method=post action=/admin/reply><input type=hidden name=uid value="{esc(reply_to)}"><textarea name=body rows=2 style="width:100%"></textarea><button style=margin-top:.4rem>Send reply</button></form></div>'
|
||||
return page("track", f"""
|
||||
<h1>OPERATOR <span>CONSOLE</span></h1>
|
||||
<div class=card><b>All customer messages</b>{msgs_html}</div>
|
||||
<div class=card><b>Reply</b><form method=get><input name=reply placeholder="user id to reply to" style=width:60%><button>Load</button></form></div>{reply_html}
|
||||
<div class=card><b>File open events</b><table><tr><th>File</th><th>IP</th><th>Device</th><th>When</th></tr>{opens_html}</table></div>""")
|
||||
|
||||
# ---------- INDEX (hacker landing) ----------
|
||||
@@ -1739,6 +1770,34 @@ No KYC. No email required. No Stripe. BTC only. Agents welcome.
|
||||
For humans: click a card. That's it.</div>"""
|
||||
return page("home", body)
|
||||
|
||||
@app.route("/favicon.svg")
|
||||
def favicon():
|
||||
svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="7" fill="#070a13"/><circle cx="16" cy="16" r="5" fill="#a78bfa"/><circle cx="16" cy="16" r="9.5" fill="none" stroke="#6fd6ff" stroke-width="1.3" stroke-dasharray="4 3"/><circle cx="25.5" cy="8" r="1.6" fill="#ffc94d"/></svg>'
|
||||
return Response(svg, mimetype="image/svg+xml")
|
||||
|
||||
@app.route("/og.png")
|
||||
def og_img():
|
||||
from PIL import Image, ImageDraw
|
||||
im = Image.new("RGB", (1200, 630), (7, 10, 19))
|
||||
dr = ImageDraw.Draw(im)
|
||||
for i in range(260):
|
||||
import random as _r
|
||||
_r.seed(i)
|
||||
x, y = _r.randint(0, 1199), _r.randint(0, 629)
|
||||
dr.ellipse([x, y, x+2, y+2], fill=(200+i%55, 210, 255))
|
||||
dr.ellipse([480, 190, 720, 430], outline=(167, 139, 250), width=4)
|
||||
dr.ellipse([455, 165, 745, 455], outline=(111, 214, 255), width=2)
|
||||
try:
|
||||
from PIL import ImageFont
|
||||
f = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono-Bold.ttf", 84)
|
||||
f2 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 26)
|
||||
except Exception:
|
||||
f = f2 = None
|
||||
dr.text((600, 290), "DARK0RBITS", fill=(255, 201, 77), anchor="mm", font=f)
|
||||
dr.text((600, 390), "no-KYC network toolbox · BTC only · agents welcome", fill=(147, 160, 194), anchor="mm", font=f2)
|
||||
buf = io.BytesIO(); im.save(buf, "PNG")
|
||||
return Response(buf.getvalue(), mimetype="image/png")
|
||||
|
||||
@app.route("/health")
|
||||
def health(): return jsonify({"ok": True, "service": "dark0rbits", "version": "2.0"})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user