"""Supernova — a cinematic galaxy-themed SMM reseller panel.
Customers deposit Bitcoin (BTCPay) into the operator's wallet, then buy social
media engagement (followers/likes/views) which the operator fulfils through the
upstream SMM panel API. The operator pockets the markup.
"""
import os
import json
import time
import sqlite3
import hashlib
import secrets
import hmac
from functools import wraps
import requests
from flask import (Flask, request, session, redirect, url_for, render_template,
jsonify, abort, flash)
from panel_client import PanelClient
# --------------------------------------------------------------------------
# CONFIG
# --------------------------------------------------------------------------
SMM_API_KEY = os.environ.get("SMM_API_KEY", "7f8a4e57d3568202aa18efe91b48c9c8")
MARKUP_PCT = float(os.environ.get("MARKUP_PCT", "100")) # 100% = 2x wholesale
# BTCPay Server (Greenfield)
BTCPAY_URL = os.environ.get("BTCPAY_URL", "https://10.30.20.140")
BTCPAY_API_KEY = os.environ.get("BTCPAY_API_KEY", "")
BTCPAY_STORE_ID = os.environ.get("BTCPAY_STORE_ID", "")
BTCPAY_WEBHOOK_SECRET = os.environ.get("BTCPAY_WEBHOOK_SECRET", "")
BTCPAY_PUBLIC = os.environ.get("BTCPAY_PUBLIC", "https://btcpay.thetempleofdoom.com")
SITE_URL = os.environ.get("SITE_URL", "https://supernova.thetempleofdoom.com")
DB_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "supernova.db")
SERVICE_CACHE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "services.json")
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY", secrets.token_hex(32))
panel = PanelClient(SMM_API_KEY)
# --------------------------------------------------------------------------
# DB
# --------------------------------------------------------------------------
def db():
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
return conn
def init_db():
c = db()
c.executescript("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
balance REAL NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
service_id INTEGER NOT NULL,
service_name TEXT NOT NULL,
link TEXT NOT NULL,
quantity INTEGER NOT NULL,
cost REAL NOT NULL,
panel_order_id INTEGER,
status TEXT NOT NULL DEFAULT 'pending',
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS deposits (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
amount REAL NOT NULL,
invoice_id TEXT,
status TEXT NOT NULL DEFAULT 'pending',
created_at INTEGER NOT NULL
);
""")
c.commit()
c.close()
# --------------------------------------------------------------------------
# Auth
# --------------------------------------------------------------------------
def hash_password(pw, salt=None):
salt = salt or secrets.token_hex(16)
dk = hashlib.pbkdf2_hmac("sha256", pw.encode(), salt.encode(), 200_000)
return f"{salt}${dk.hex()}"
def verify_password(pw, stored):
salt, _ = stored.split("$", 1)
return hmac.compare_digest(hash_password(pw, salt), stored)
def current_user():
uid = session.get("uid")
if not uid:
return None
c = db()
u = c.execute("SELECT * FROM users WHERE id=?", (uid,)).fetchone()
c.close()
return u
def login_required(f):
@wraps(f)
def wrap(*a, **kw):
if not current_user():
return redirect(url_for("login", next=request.path))
return f(*a, **kw)
return wrap
# --------------------------------------------------------------------------
# Service cache (avoid hitting the panel API every page load)
# --------------------------------------------------------------------------
def get_services(force=False):
if not force and os.path.exists(SERVICE_CACHE):
if time.time() - os.path.getmtime(SERVICE_CACHE) < 900: # 15 min TTL
with open(SERVICE_CACHE) as f:
return json.load(f)
svcs = panel.services()
with open(SERVICE_CACHE, "w") as f:
json.dump(svcs, f)
return svcs
def wholesale_cost(rate, quantity):
return float(rate) * quantity / 1000.0
def retail_price(rate, quantity):
return wholesale_cost(rate, quantity) * (1 + MARKUP_PCT / 100.0)
# --------------------------------------------------------------------------
# BTCPay
# --------------------------------------------------------------------------
def btcpay_headers():
return {"Authorization": f"token {BTCPAY_API_KEY}",
"Content-Type": "application/json"}
def create_invoice(amount_usd, order_id, buyer_email):
# price in USD; BTCPay converts to BTC at its rate
payload = {
"amount": str(round(amount_usd, 2)),
"currency": "USD",
"checkout": {"redirectURL": SITE_URL + "/dashboard"},
"metadata": {"orderId": str(order_id),
"buyerEmail": buyer_email},
}
r = requests.post(f"{BTCPAY_URL}/api/v1/stores/{BTCPAY_STORE_ID}/invoices",
headers=btcpay_headers(), json=payload, timeout=20, verify=False)
r.raise_for_status()
inv = r.json()
# rewrite checkoutLink from LAN IP to public host (customer-facing)
link = inv.get("checkoutLink", "")
if link and link.startswith(BTCPAY_URL):
inv["checkoutLink"] = BTCPAY_PUBLIC + link[len(BTCPAY_URL):]
return inv
def get_invoice(invoice_id):
r = requests.get(f"{BTCPAY_URL}/api/v1/stores/{BTCPAY_STORE_ID}/invoices/{invoice_id}",
headers=btcpay_headers(), timeout=20, verify=False)
r.raise_for_status()
return r.json()
# --------------------------------------------------------------------------
# Routes
# --------------------------------------------------------------------------
@app.route("/")
def index():
return render_template("index.html", user=current_user())
@app.route("/robots.txt")
def robots():
body = ("User-agent: *\n"
"Allow: /\n"
"Sitemap: https://supernova.thetempleofdoom.com/sitemap.xml\n")
return body, 200, {"Content-Type": "text/plain"}
@app.route("/sitemap.xml")
def sitemap():
pages = [
("/", "1.0", "weekly"),
("/services", "0.9", "daily"),
("/signup", "0.5", "monthly"),
("/login", "0.3", "monthly"),
]
urls = "".join(
f"https://supernova.thetempleofdoom.com{p}"
f"{freq}{pri}"
for p, pri, freq in pages
)
xml = ('\n'
''
f"{urls}")
return xml, 200, {"Content-Type": "application/xml"}
@app.route("/bg-demo")
def bg_demo():
theme = request.args.get("theme", "cosmos")
themes = ["starfield", "cosmos", "blackhole", "geometric", "nebula", "particles", "waves", "grid"]
return render_template("bg-demo.html", user=current_user(), theme=theme, themes=themes)
@app.route("/signup", methods=["GET", "POST"])
def signup():
if request.method == "POST":
email = request.form.get("email", "").strip().lower()
pw = request.form.get("password", "")
if len(pw) < 8:
flash("Password must be at least 8 characters.", "error")
return redirect(url_for("signup"))
c = db()
try:
c.execute("INSERT INTO users (email, password_hash, created_at) VALUES (?,?,?)",
(email, hash_password(pw), int(time.time())))
c.commit()
except sqlite3.IntegrityError:
c.close()
flash("That email is already registered.", "error")
return redirect(url_for("signup"))
uid = c.execute("SELECT id FROM users WHERE email=?", (email,)).fetchone()["id"]
c.close()
session["uid"] = uid
return redirect(url_for("dashboard"))
return render_template("auth.html", mode="signup", user=None)
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
email = request.form.get("email", "").strip().lower()
pw = request.form.get("password", "")
c = db()
u = c.execute("SELECT * FROM users WHERE email=?", (email,)).fetchone()
c.close()
if u and verify_password(pw, u["password_hash"]):
session["uid"] = u["id"]
nxt = request.args.get("next") or url_for("dashboard")
return redirect(nxt)
flash("Invalid email or password.", "error")
return render_template("auth.html", mode="login", user=None)
@app.route("/logout")
def logout():
session.clear()
return redirect(url_for("index"))
@app.route("/services")
def services():
svcs = get_services()
# group by category
cats = {}
for s in svcs:
cats.setdefault(s["category"], []).append(s)
return render_template("services.html", user=current_user(), cats=cats)
@app.route("/order/", methods=["GET", "POST"])
@login_required
def order(service_id):
svcs = {s["service"]: s for s in get_services()}
s = svcs.get(service_id)
if not s:
abort(404)
if request.method == "POST":
link = request.form.get("link", "").strip()
quantity = int(request.form.get("quantity", 0))
cost = retail_price(s["rate"], quantity)
if not link or quantity < s["min"]:
flash(f"Enter a valid link and quantity (min {s['min']}).", "error")
return redirect(url_for("order", service_id=service_id))
u = current_user()
if u["balance"] < cost:
flash("Insufficient balance — deposit more BTC first.", "error")
return redirect(url_for("deposit"))
# charge + place upstream order
try:
res = panel.place_order(service_id, link, quantity)
panel_oid = res.get("order")
except Exception as e:
flash(f"Upstream order failed: {e}", "error")
return redirect(url_for("order", service_id=service_id))
c = db()
c.execute("UPDATE users SET balance = balance - ? WHERE id=?",
(cost, u["id"]))
c.execute("""INSERT INTO orders
(user_id, service_id, service_name, link, quantity, cost,
panel_order_id, status, created_at)
VALUES (?,?,?,?,?,?,?,?,?)""",
(u["id"], service_id, s["name"], link, quantity, cost,
panel_oid, "pending", int(time.time())))
c.commit()
c.close()
flash(f"Order placed! ${cost:.2f} — it'll start delivering shortly.", "success")
return redirect(url_for("orders") + "?launched=1")
return render_template("order.html", user=current_user(), s=s,
markup=MARKUP_PCT)
@app.route("/orders")
@login_required
def orders():
u = current_user()
c = db()
rows = c.execute("SELECT * FROM orders WHERE user_id=? ORDER BY id DESC LIMIT 100",
(u["id"],)).fetchall()
c.close()
return render_template("orders.html", user=u, orders=rows)
@app.route("/dashboard")
@login_required
def dashboard():
u = current_user()
c = db()
orders = c.execute("SELECT * FROM orders WHERE user_id=? ORDER BY id DESC LIMIT 10",
(u["id"],)).fetchall()
deposits = c.execute("SELECT * FROM deposits WHERE user_id=? ORDER BY id DESC LIMIT 10",
(u["id"],)).fetchall()
c.close()
return render_template("dashboard.html", user=u, orders=orders, deposits=deposits)
@app.route("/deposit", methods=["GET", "POST"])
@login_required
def deposit():
u = current_user()
if request.method == "POST":
amount = float(request.form.get("amount", 0))
if amount <= 0:
flash("Enter a valid amount.", "error")
return redirect(url_for("deposit"))
c = db()
cur = c.execute("""INSERT INTO deposits (user_id, amount, status, created_at)
VALUES (?,?,'pending',?)""",
(u["id"], amount, int(time.time())))
c.commit()
dep_id = cur.lastrowid
c.close()
inv = create_invoice(amount, dep_id, u["email"])
c = db()
c.execute("UPDATE deposits SET invoice_id=? WHERE id=?",
(inv["id"], dep_id))
c.commit()
c.close()
return redirect(inv["checkoutLink"])
return render_template("deposit.html", user=u)
@app.route("/webhook/btcpay", methods=["POST"])
def btcpay_webhook():
# verify signature
sig = request.headers.get("BTCPay-Sig", "")
body = request.get_data()
expected = "sha256=" + hmac.new(BTCPAY_WEBHOOK_SECRET.encode(), body,
hashlib.sha256).hexdigest()
if BTCPAY_WEBHOOK_SECRET and not hmac.compare_digest(sig, expected):
return "bad signature", 401
data = request.get_json(silent=True) or {}
inv_id = data.get("invoiceId")
if not inv_id:
return "ok", 200
# re-fetch invoice to confirm status (don't trust the webhook blindly)
try:
inv = get_invoice(inv_id)
except Exception:
return "ok", 200
if inv.get("status") != "Settled":
return "ok", 200
dep_id = (inv.get("metadata") or {}).get("orderId")
amount = float(inv.get("amount", 0))
c = db()
dep = c.execute("SELECT * FROM deposits WHERE id=?", (dep_id,)).fetchone()
if dep and dep["status"] != "credited":
c.execute("UPDATE deposits SET status='credited' WHERE id=?", (dep_id,))
c.execute("UPDATE users SET balance = balance + ? WHERE id=?",
(amount, dep["user_id"]))
c.commit()
c.close()
return "ok", 200
@app.route("/api/quote//")
def api_quote(service_id, quantity):
svcs = {s["service"]: s for s in get_services()}
s = svcs.get(service_id)
if not s:
return jsonify({"error": "unknown service"}), 404
return jsonify({
"quantity": quantity,
"wholesale": round(wholesale_cost(s["rate"], quantity), 4),
"retail": round(retail_price(s["rate"], quantity), 2),
"rate": s["rate"],
"min": s["min"],
"max": s["max"],
})
@app.route("/api/orders-status")
@login_required
def api_orders_status():
"""Live delivery status for the dashboard ticker."""
u = current_user()
c = db()
rows = c.execute("SELECT * FROM orders WHERE user_id=? ORDER BY id DESC LIMIT 8",
(u["id"],)).fetchall()
c.close()
out = []
for o in rows:
status = o["status"]
remains = 0
delivered = o["quantity"]
if o["panel_order_id"]:
try:
st = panel.order_status(o["panel_order_id"])
status = (st.get("status") or o["status"]).lower().replace(" ", "")
remains = int(st.get("remains") or 0)
delivered = max(0, o["quantity"] - remains)
except Exception:
pass
out.append({
"id": o["id"],
"name": o["service_name"],
"quantity": o["quantity"],
"delivered": delivered,
"status": status,
})
return jsonify({"orders": out})
if __name__ == "__main__":
init_db()
app.run(host="0.0.0.0", port=5000)