#!/usr/bin/env python3 """Pleiades storefront — Flask app: signup/login, plans, BTCPay checkout, dashboard.""" import base64 import hashlib import hmac import json import time from functools import wraps import requests from flask import (Flask, abort, flash, jsonify, redirect, render_template, request, session, url_for) import db import iproyal import hydraproxy import quality CFG = db.CFG app = Flask(__name__) app.secret_key = CFG["secret_key"] app.config["SESSION_COOKIE_SAMESITE"] = "Lax" # mitigate CSRF on modern browsers app.config["SESSION_COOKIE_HTTPONLY"] = True # block JS session theft (XSS) db.init_db() # ensure schema + migrations on gunicorn start # simple SQLite-backed rate limiter (shared across gunicorn workers) def _client_ip(): xff = request.headers.get("X-Forwarded-For", "") return xff.split(",")[0].strip() if xff else (request.remote_addr or "?") def _rate_ok(ip, limit=10, window=60): now = time.time() d = db.get_db() d.execute("DELETE FROM rate_limits WHERE ts < ?", (now - window,)) count = d.execute("SELECT COUNT(*) c FROM rate_limits WHERE ip=?", (ip,)).fetchone()["c"] if count >= limit: d.close() return False d.execute("INSERT INTO rate_limits (ip, ts) VALUES (?,?)", (ip, now)) d.commit() d.close() return True BTCPAY = CFG["btcpay"] PROXY = CFG["proxy_public"] SITE_HOST = CFG.get("site_host", "clean-proxys.thetempleofdoom.com") PRICE_USD_PER_GB = CFG.get("price_usd_per_gb", 8.0) # display only # Dedicated IP catalog: product_id -> {name, desc, plans: {days: (iproyal_plan_id, price_sats)}} # Overridable via config.json "dedicated_products" (JSON keys are strings -> converted). _DEDICATED_DEFAULT = { 3: {"name": "Datacenter Dedicated", "desc": "Static datacenter IP — budget tier", "plans": {30: (5, 10000), 60: (26, 20000), 90: (27, 30000)}}, 9: {"name": "ISP Dedicated", "desc": "Clean residential-ISP IP — premium tier", "plans": {30: (22, 22000), 60: (24, 44000), 90: (25, 66000)}}, } def _load_dedicated_products(): raw = CFG.get("dedicated_products") if not raw: return _DEDICATED_DEFAULT out = {} for pid, p in raw.items(): plans = {int(d): (int(v[0]), int(v[1])) for d, v in p.get("plans", {}).items()} out[int(pid)] = {"name": p.get("name", ""), "desc": p.get("desc", ""), "plans": plans} return out or _DEDICATED_DEFAULT DEDICATED_PRODUCTS = _load_dedicated_products() # ---------- auth ---------- def current_user(): uid = session.get("uid") if not uid: return None d = db.get_db() row = d.execute("SELECT * FROM users WHERE id=?", (uid,)).fetchone() d.close() return dict(row) if row else None def login_required(f): @wraps(f) def wrapper(*a, **kw): if not current_user(): flash("Log in first.", "warn") return redirect(url_for("login")) return f(*a, **kw) return wrapper # ---------- BTCPay ---------- def create_invoice(amount_sats, order_id, meta=None): data = { "amount": amount_sats / 1e8, "currency": "BTC", "checkout": { "redirectURL": f"https://{SITE_HOST}/order/{order_id}", "redirectAutomatically": True, }, "metadata": {"orderId": order_id}, } if meta: data["metadata"].update(meta) r = requests.post( f"{BTCPAY['url']}/api/v1/stores/{BTCPAY['store_id']}/invoices", headers={"Authorization": f"token {BTCPAY['api_key']}"}, json=data, timeout=20, verify=False, ) r.raise_for_status() return r.json() def verify_webhook(): sig = request.headers.get("BTCPay-Sig", "") if not sig.startswith("sha256="): return False expected = sig.split("=", 1)[1] calc = hmac.new(BTCPAY["webhook_secret"].encode(), request.get_data(), hashlib.sha256).hexdigest() return hmac.compare_digest(calc, expected) # ---------- routes ---------- @app.route("/") def index(): return render_template("index.html", user=current_user()) @app.route("/signup", methods=["GET", "POST"]) def signup(): if request.method == "POST": if not _rate_ok(_client_ip(), limit=20, window=300): flash("Too many attempts. Slow down.", "warn") return render_template("signup.html") username = request.form.get("username", "").strip() password = request.form.get("password", "") if len(username) < 3 or len(password) < 6: flash("Username 3+ chars, password 6+ chars.", "warn") return render_template("signup.html") d = db.get_db() exists = d.execute("SELECT 1 FROM users WHERE username=?", (username,)).fetchone() if exists: d.close() flash("Username taken.", "warn") return render_template("signup.html") proxy_pass = db.random_token(18) d.execute( "INSERT INTO users (username,password_hash,proxy_password_hash,proxy_password_plain," "active,region,country,city,sticky,balance_gb,created_at) VALUES (?,?,?,?,0,'','US','',1,0,?)", (username, db.scrypt_hash(password), db.scrypt_hash(proxy_pass), proxy_pass, int(time.time()))) d.commit() uid = d.execute("SELECT id FROM users WHERE username=?", (username,)).fetchone()["id"] d.close() session["uid"] = uid flash(f"Account created. Proxy password: {proxy_pass} (save it)", "ok") return redirect(url_for("dashboard")) return render_template("signup.html") @app.route("/login", methods=["GET", "POST"]) def login(): if request.method == "POST": if not _rate_ok(_client_ip(), limit=20, window=300): flash("Too many attempts. Slow down.", "warn") return render_template("login.html") username = request.form.get("username", "").strip() password = request.form.get("password", "") d = db.get_db() row = d.execute("SELECT * FROM users WHERE username=?", (username,)).fetchone() d.close() if row and db.verify_hash(password, row["password_hash"]): session["uid"] = row["id"] return redirect(url_for("dashboard")) flash("Bad credentials.", "warn") return render_template("login.html") @app.route("/logout") def logout(): session.clear() return redirect(url_for("index")) @app.route("/plans") def plans(): d = db.get_db() ps = [dict(r) for r in d.execute("SELECT * FROM plans WHERE active=1 ORDER BY gb")] d.close() return render_template("plans.html", plans=ps, user=current_user()) @app.route("/buy/", methods=["POST"]) @login_required def buy(plan_id): u = current_user() d = db.get_db() plan = d.execute("SELECT * FROM plans WHERE id=?", (plan_id,)).fetchone() d.close() if not plan: abort(404) price = plan["price_sats"] if db.get_balance_sats(u["id"]) < price: flash("Insufficient wallet balance. Deposit first.", "warn") return redirect(url_for("wallet")) db.add_transaction(u["id"], -price, "gb", f"plan_{plan_id}") d = db.get_db() d.execute("UPDATE users SET balance_gb = balance_gb + ?, active=1 WHERE id=?", (plan["gb"], u["id"])) d.commit() d.close() flash(f"Added {plan['gb']} GB. Happy scraping.", "ok") return redirect(url_for("dashboard")) @app.route("/order/") @login_required def order(order_id): d = db.get_db() o = d.execute("SELECT * FROM orders WHERE invoice_id=? AND user_id=?", (order_id, current_user()["id"])).fetchone() d.close() if not o: abort(404) return render_template("order.html", order=dict(o), user=current_user()) @app.route("/webhook/btcpay", methods=["POST"]) def webhook_btcpay(): if not verify_webhook(): abort(401) payload = request.get_json(force=True) if payload.get("type") not in ("InvoiceSettled", "InvoiceProcessing"): return "ok" order_id = (payload.get("metadata") or {}).get("orderId") kind = (payload.get("metadata") or {}).get("kind") if not order_id: return "ok" if kind == "deposit": uid = (payload.get("metadata") or {}).get("user_id") amt = (payload.get("metadata") or {}).get("amount_sats") d = db.get_db() already = d.execute("SELECT 1 FROM transactions WHERE ref=? AND type='deposit'", (order_id,)).fetchone() if not already and uid and amt: d.execute("UPDATE users SET balance_sats = balance_sats + ? WHERE id=?", (int(amt), uid)) d.execute("INSERT INTO transactions (user_id, amount_sats, type, ref, ts) " "VALUES (?,?,?,?,?)", (uid, int(amt), "deposit", order_id, int(time.time()))) d.commit() d.close() return "ok" d = db.get_db() if kind == "dedicated": row = d.execute("SELECT * FROM dedicated_ips WHERE invoice_id=? AND status='pending_payment'", (order_id,)).fetchone() if row: try: plan_id = DEDICATED_PRODUCTS[row["product_id"]]["plans"][row["plan_days"]][0] o = iproyal.create_order(row["product_id"], plan_id, row["location_id"], 1) oid = o.get("id") or o.get("order_id") or (o.get("data") or {}).get("id") d.execute("UPDATE dedicated_ips SET status='provisioning', iproyal_order_id=? WHERE id=?", (oid, row["id"])) d.commit() app.logger.info("dedicated IPRoyal order %s created for dedicated_ips #%s", oid, row["id"]) except Exception as e: app.logger.error("dedicated order failed: %s", e) d.execute("UPDATE dedicated_ips SET status='failed' WHERE id=?", (row["id"],)) d.commit() d.close() return "ok" o = d.execute("SELECT * FROM orders WHERE invoice_id=?", (order_id,)).fetchone() if o and o["status"] != "paid": plan = d.execute("SELECT * FROM plans WHERE id=?", (o["plan_id"],)).fetchone() d.execute("UPDATE orders SET status='paid', paid_at=? WHERE id=?", (int(time.time()), o["id"])) d.execute("UPDATE users SET balance_gb=balance_gb+?, active=1 WHERE id=?", (plan["gb"], o["user_id"])) d.commit() d.close() return "ok" @app.route("/wallet") @login_required def wallet(): u = current_user() bal = db.get_balance_sats(u["id"]) txs = db.get_transactions(u["id"]) return render_template("wallet.html", user=u, balance=bal, txs=txs) @app.route("/wallet/deposit", methods=["POST"]) @login_required def wallet_deposit(): u = current_user() try: sats = int(request.form.get("sats", 0)) except ValueError: sats = 0 if sats < 500: flash("Minimum deposit is 500 sats.", "warn") return redirect(url_for("wallet")) ref = db.random_token(12) inv = create_invoice(sats, ref, meta={"kind": "deposit", "user_id": u["id"], "amount_sats": sats}) return redirect(inv["checkoutLink"]) @app.route("/dashboard") @login_required def dashboard(): u = current_user() d = db.get_db() used = d.execute("SELECT COALESCE(SUM(bytes),0) s FROM usage_log WHERE user_id=?", (u["id"],)).fetchone()["s"] deds = [dict(r) for r in d.execute("SELECT * FROM dedicated_ips WHERE user_id=? ORDER BY id DESC", (u["id"],)).fetchall()] orders = [dict(r) for r in d.execute( "SELECT o.*, p.name plan_name, p.gb plan_gb FROM orders o LEFT JOIN plans p ON o.plan_id=p.id " "WHERE o.user_id=? ORDER BY o.id DESC LIMIT 20", (u["id"],)).fetchall()] sessions = [dict(r) for r in d.execute( "SELECT * FROM usage_log WHERE user_id=? ORDER BY id DESC LIMIT 10", (u["id"],)).fetchall()] hydra = [dict(r) for r in d.execute( "SELECT * FROM hydraproxy_orders WHERE user_id=? ORDER BY id DESC", (u["id"],)).fetchall()] d.close() bal = db.get_balance_sats(u["id"]) socks = f"socks5://{u['username']}:{u['proxy_password_plain']}@{PROXY['host']}:{PROXY['socks_port']}" http = f"http://{u['username']}:{u['proxy_password_plain']}@{PROXY['host']}:{PROXY['http_port']}" return render_template("dashboard.html", user=u, used_gb=used / 1e9, socks=socks, http=http, dedicated=deds, orders=orders, sessions=sessions, hydra=hydra, balance=bal) @app.route("/dashboard/test") @login_required def dashboard_test(): """Live proxy check: egress through the customer's own creds via the gateway.""" u = current_user() proxy = f"socks5h://{u['username']}:{u['proxy_password_plain']}@127.0.0.1:{PROXY['socks_port']}" try: import subprocess r = subprocess.run(["curl", "-s", "--max-time", "20", "-x", proxy, "http://ip-api.com/json?fields=query,country,city,isp,status"], capture_output=True, text=True, timeout=25) return app.response_class(r.stdout or '{"status":"fail","message":"no response"}', mimetype="application/json") except Exception as e: return jsonify({"status": "fail", "message": str(e)}), 502 @app.route("/dashboard/location", methods=["POST"]) @login_required def set_location(): u = current_user() country = request.form.get("country", "").strip().upper() city = request.form.get("city", "").strip() region = request.form.get("region", "").strip() sticky = 1 if request.form.get("sticky") else 0 d = db.get_db() d.execute("UPDATE users SET country=?, city=?, region=?, sticky=? WHERE id=?", (country, city, region, sticky, u["id"])) d.commit() d.close() flash("Location updated.", "ok") return redirect(url_for("dashboard")) @app.route("/dashboard/rotate", methods=["POST"]) @login_required def rotate(): u = current_user() newpass = db.random_token(18) d = db.get_db() d.execute("UPDATE users SET proxy_password_hash=?, proxy_password_plain=? WHERE id=?", (db.scrypt_hash(newpass), newpass, u["id"])) d.commit() d.close() flash(f"New proxy password: {newpass}", "ok") return redirect(url_for("dashboard")) @app.route("/dashboard/credentials", methods=["POST"]) @login_required def change_credentials(): """Let the customer set their own proxy username and/or password.""" u = current_user() new_username = request.form.get("username", "").strip() new_password = request.form.get("proxy_password", "").strip() d = db.get_db() changed = [] if new_username and new_username != u["username"]: taken = d.execute("SELECT 1 FROM users WHERE username=? AND id!=?", (new_username, u["id"])).fetchone() if taken: d.close() flash("Username already taken.", "warn") return redirect(url_for("dashboard")) d.execute("UPDATE users SET username=? WHERE id=?", (new_username, u["id"])) changed.append("username") if new_password: d.execute("UPDATE users SET proxy_password_hash=?, proxy_password_plain=? WHERE id=?", (db.scrypt_hash(new_password), new_password, u["id"])) changed.append("password") d.commit() d.close() if changed: flash("Proxy " + " & ".join(changed) + " updated.", "ok") else: flash("Nothing changed.", "warn") return redirect(url_for("dashboard")) # ---------- dedicated IPs ---------- @app.route("/dedicated") def dedicated(): dc_locs = isp_locs = [] try: dc_locs = iproyal.list_locations(3) isp_locs = iproyal.list_locations(9) except Exception as e: flash(f"Location catalog unavailable: {e}", "warn") return render_template("dedicated.html", products=DEDICATED_PRODUCTS, dc_locs=dc_locs, isp_locs=isp_locs, user=current_user()) @app.route("/dedicated/locations") def dedicated_locations(): pid = request.args.get("product", 3, type=int) try: return jsonify({"locations": [{"id": i, "name": n, "in_stock": s} for i, n, s in iproyal.list_locations(pid)]}) except Exception as e: return jsonify({"error": str(e)}), 502 @app.route("/api/v1/dedicated/locations") def api_dedicated_locations(): pid = request.args.get("product", 9, type=int) try: return jsonify({"locations": [{"id": i, "name": n, "in_stock": s} for i, n, s in iproyal.list_locations(pid)]}) except Exception as e: return jsonify({"error": str(e)}), 502 @app.route("/dedicated/buy", methods=["POST"]) @login_required def dedicated_buy(): pid = int(request.form.get("product", 3)) days = int(request.form.get("days", 30)) loc_id = int(request.form.get("location_id", 0)) loc_name = request.form.get("location_name", "") if pid not in DEDICATED_PRODUCTS or days not in DEDICATED_PRODUCTS[pid]["plans"]: flash("Bad product or duration.", "warn") return redirect(url_for("dedicated")) if not loc_id or not loc_name: flash("Pick a location.", "warn") return redirect(url_for("dedicated")) _, price = DEDICATED_PRODUCTS[pid]["plans"][days] u = current_user() if db.get_balance_sats(u["id"]) < price: flash("Insufficient wallet balance. Deposit first.", "warn") return redirect(url_for("wallet")) oid = db.random_token(12) d = db.get_db() d.execute("INSERT INTO dedicated_ips (user_id,product_id,product_name,plan_days,location_id," "location_name,invoice_id,price_sats,status,created_at) VALUES (?,?,?,?,?,?,?,?,?,?)", (u["id"], pid, DEDICATED_PRODUCTS[pid]["name"], days, loc_id, loc_name, oid, price, "pending_payment", int(time.time()))) d.commit() d.close() db.add_transaction(u["id"], -price, "dedicated", oid) # place the IPRoyal order directly (no webhook needed in wallet model) try: plan_id = DEDICATED_PRODUCTS[pid]["plans"][days][0] o = iproyal.create_order(pid, plan_id, loc_id, 1) oid2 = o.get("id") or o.get("order_id") or (o.get("data") or {}).get("id") d = db.get_db() d.execute("UPDATE dedicated_ips SET status='provisioning', iproyal_order_id=? WHERE invoice_id=?", (oid2, oid)) d.commit() d.close() flash("Dedicated IP ordered — provisioning now.", "ok") except Exception as e: app.logger.error("dedicated order failed: %s", e) d = db.get_db() d.execute("UPDATE dedicated_ips SET status='failed' WHERE invoice_id=?", (oid,)) d.commit() d.close() db.add_transaction(u["id"], price, "dedicated_refund", oid) flash("Dedicated order failed — wallet refunded.", "warn") return redirect(url_for("dashboard")) @app.route("/dedicated/poll", methods=["POST"]) def dedicated_poll(): """Admin hook: poll provisioning for pending dedicated orders.""" if not session.get("admin"): abort(403) ok, failed = poll_provisioning() return jsonify({"provisioned": ok, "failed": failed}) def poll_provisioning(): """Check pending IPRoyal orders, move confirmed ones to active. Returns (ok, failed).""" d = db.get_db() pending = d.execute("SELECT * FROM dedicated_ips WHERE status IN ('provisioning')").fetchall() d.close() ok = failed = 0 for row in pending: try: o = iproyal.get_order(row["iproyal_order_id"]) status = o.get("status") if status == "confirmed": pd = o.get("proxy_data") or {} proxies = pd.get("proxies") or [] ports = pd.get("ports") or {} if proxies: p = proxies[0] host = p.get("ip") or "" user = p.get("username") or "" pw = p.get("password") or "" socks_port = str(ports.get("socks5", "")) http_port = str(ports.get("http|https", "")) d = db.get_db() d.execute("UPDATE dedicated_ips SET status='active', proxy_host=?, proxy_port=?," "http_port=?, proxy_user=?, proxy_pass=?, expires_at=? WHERE id=?", (host, socks_port, http_port, user, pw, int(time.time()) + row["plan_days"] * 86400, row["id"])) d.commit() d.close() ok += 1 elif status in ("refunded", "expired"): d = db.get_db() d.execute("UPDATE dedicated_ips SET status='failed' WHERE id=?", (row["id"],)) d.commit() d.close() failed += 1 except Exception as e: app.logger.warning("poll order %s failed: %s", row["iproyal_order_id"], e) # expire past-due active IPs d = db.get_db() d.execute("UPDATE dedicated_ips SET status='expired' WHERE status='active' " "AND expires_at > 0 AND expires_at < ?", (int(time.time()),)) d.commit() d.close() return ok, failed # ---------- Mobile proxy tier (4G carrier / static mobile — manually fulfilled) ---------- HYDRA_PRODUCTS = CFG.get("hydraproxy", {}).get("products", {}) @app.route("/mobile") def hydraproxy_page(): account = None err = None try: account = hydraproxy.get_account_info() except Exception as e: err = str(e) return render_template("mobile.html", products=HYDRA_PRODUCTS, account=account, err=err, user=current_user()) @app.route("/api/v1/hydraproxy/info") def api_hydraproxy_info(): try: account = hydraproxy.get_account_info() locations = hydraproxy.get_locations() return jsonify({"account": account, "locations": locations, "products": HYDRA_PRODUCTS}) except Exception as e: return jsonify({"error": str(e)}), 502 @app.route("/mobile/order", methods=["POST"]) @login_required def hydraproxy_order(): u = current_user() product = request.form.get("product", "").strip() location = request.form.get("location", "").strip() if product not in HYDRA_PRODUCTS: flash("Bad product.", "warn") return redirect(url_for("hydraproxy_page")) price = HYDRA_PRODUCTS[product]["price_sats"] if db.get_balance_sats(u["id"]) < price: flash("Insufficient wallet balance. Deposit first.", "warn") return redirect(url_for("wallet")) d = db.get_db() d.execute("INSERT INTO hydraproxy_orders (user_id, product, location, price_sats, status, created_at) " "VALUES (?,?,?,?,'pending_fulfillment',?)", (u["id"], product, location, price, int(time.time()))) d.commit() d.close() db.add_transaction(u["id"], -price, "hydraproxy", product) flash("Order placed — your proxy is provisioned shortly and delivered to the dashboard.", "ok") return redirect(url_for("dashboard")) @app.route("/quality") @login_required def quality_page(): return render_template("quality.html", user=current_user(), price=CFG.get("quality_price_sats", 220)) @app.route("/quality/run", methods=["POST"]) @login_required def quality_run(): u = current_user() price = CFG.get("quality_price_sats", 220) if db.get_balance_sats(u["id"]) < price: return jsonify({"error": "Insufficient balance. Deposit first."}), 402 proxy = request.form.get("proxy", "").strip() if not proxy: proxy = f"socks5h://{u['username']}:{u['proxy_password_plain']}@127.0.0.1:{PROXY['socks_port']}" db.add_transaction(u["id"], -price, "quality", "ip_check") result = quality.score_proxy(proxy) result["charged_sats"] = price return jsonify(result) # ---------- admin ---------- ADMIN_PASSWORD = CFG.get("admin_password", "") @app.route("/admin", methods=["GET", "POST"]) def admin(): if request.method == "POST": if request.form.get("password") == ADMIN_PASSWORD: session["admin"] = True else: flash("Bad admin password.", "warn") if not session.get("admin"): return render_template("admin_login.html") d = db.get_db() stats = { "users": d.execute("SELECT COUNT(*) c FROM users").fetchone()["c"], "active": d.execute("SELECT COUNT(*) c FROM users WHERE active=1").fetchone()["c"], "revenue_sats": d.execute("SELECT COALESCE(SUM(amount_sats),0) s FROM orders WHERE status='paid'").fetchone()["s"], "pending_orders": d.execute("SELECT COUNT(*) c FROM orders WHERE status='pending'").fetchone()["c"], "gb_sold": d.execute("SELECT COALESCE(SUM(gb),0) s FROM plans WHERE id IN " "(SELECT plan_id FROM orders WHERE status='paid')").fetchone()["s"], } users = [dict(r) for r in d.execute("SELECT id,username,active,balance_gb,country,city,created_at " "FROM users ORDER BY id DESC LIMIT 50")] orders = [dict(r) for r in d.execute("SELECT * FROM orders ORDER BY id DESC LIMIT 20")] deds = [dict(r) for r in d.execute("SELECT * FROM dedicated_ips ORDER BY id DESC LIMIT 30")] hydra_orders = [dict(r) for r in d.execute("SELECT * FROM hydraproxy_orders ORDER BY id DESC LIMIT 30")] d.close() try: ipr_balance = iproyal.get_balance() except Exception: ipr_balance = "unavailable" try: hydra_acct = hydraproxy.get_account_info() hydra_balance = hydra_acct.get("balance_usd", "unavailable") except Exception: hydra_balance = "unavailable" low_balance = isinstance(ipr_balance, (int, float)) and \ ipr_balance < CFG.get("alerts", {}).get("low_balance_threshold", 10.0) return render_template("admin.html", stats=stats, users=users, orders=orders, dedicated=deds, ipr_balance=ipr_balance, low_balance=low_balance, hydra_balance=hydra_balance, hydra_orders=hydra_orders) @app.route("/admin/credit", methods=["POST"]) def admin_credit(): if not session.get("admin"): abort(403) username = request.form.get("username", "").strip() try: gb = float(request.form.get("gb", 0)) except ValueError: gb = 0 d = db.get_db() d.execute("UPDATE users SET balance_gb=balance_gb+?, active=1 WHERE username=?", (gb, username)) d.commit() d.close() flash(f"Credited {gb} GB to {username}", "ok") return redirect(url_for("admin")) @app.route("/admin/hydraproxy/fulfill", methods=["POST"]) def admin_hydraproxy_fulfill(): if not session.get("admin"): abort(403) oid = request.form.get("order_id", "").strip() hydra_order_id = request.form.get("hydra_order_id", "").strip() if not oid or not hydra_order_id: flash("Need our order id and the HydraProxy order id.", "warn") return redirect(url_for("admin")) try: details = hydraproxy.proxy_details(hydra_order_id) pinfo = details.get("proxy_info", {}) proxy = details.get("proxy", {}) host = proxy.get("hostname") or proxy.get("server_ip") port = proxy.get("port") if isinstance(port, list): port = port[0] user = pinfo.get("username", "") pw = pinfo.get("password", "") d = db.get_db() d.execute("UPDATE hydraproxy_orders SET status='active', hydra_order_id=?, proxy_host=?, " "proxy_port=?, proxy_user=?, proxy_pass=?, fulfilled_at=? WHERE id=?", (hydra_order_id, host, str(port), user, pw, int(time.time()), oid)) d.commit() d.close() flash(f"Fulfilled order {oid} with HydraProxy order {hydra_order_id}.", "ok") except Exception as e: flash(f"Fulfill failed: {e}", "warn") return redirect(url_for("admin")) # ---------- agent discovery ---------- @app.route("/llms.txt") def llms_txt(): body = f"""# {SITE_HOST} > Clean residential SOCKS5/HTTP proxies. No KYC. Crypto checkout. Encrypted backend. ## What this service does Sells residential SOCKS5 and HTTP CONNECT proxies with global geo-targeting (country/city/region). Buy with Bitcoin (no KYC). Instant activation. ## Why agents use Clean Proxys Agents that scrape, crawl, or access geo-restricted or rate-limited endpoints fail fast on datacenter-flagged or shared IPs. Clean Proxys issues clean residential IPs (not VPN, not datacenter) that bypass IP-based blocks, with per-country/city targeting and sticky or rotating sessions. One POST provisions a working proxy — no KYC, Bitcoin billing, programmatic end-to-end. ## Key facts - Protocol: SOCKS5 (port {PROXY['socks_port']}), HTTP CONNECT (port {PROXY['http_port']}) - Auth: per-user username + password - Geo: country, city, region targeting - Sessions: sticky or rotating - Billing: pay-per-GB, Bitcoin (BTCPay) - Signup: username + password only (no email, no KYC) ## MCP (for agent clients) - Streamable HTTP MCP server: {SITE_HOST}/mcp - Tools: get_info, list_plans, buy_proxy, get_order_status, list_dedicated_locations ## API - OpenAPI spec: {SITE_HOST}/openapi.json - GET /api/v1/info -> service info (JSON) - GET /api/v1/plans -> residential GB plans (JSON) - POST /api/v1/proxy -> one-call purchase (JSON: plan_id, country, city, username, password) -> creds + BTCPay checkout URL - GET /api/v1/order/ -> payment status (pending/paid) - GET /api/v1/dedicated/locations?product=9 -> ISP dedicated locations (JSON) - GET /api/v1/dedicated/locations?product=3 -> datacenter dedicated locations (JSON) - Human signup: {SITE_HOST}/signup - Dedicated IPs: {SITE_HOST}/dedicated (datacenter $1.80/30d + ISP $4/30d resold at markup) ## Connect (after signup + top-up) socks5://USER:PASS@{PROXY['host']}:{PROXY['socks_port']} """ return app.response_class(body, mimetype="text/plain") @app.route("/robots.txt") def robots(): return app.response_class( "User-agent: *\nAllow: /\n" "User-agent: GPTBot\nAllow: /\n" "User-agent: ClaudeBot\nAllow: /\n" "User-agent: anthropic-ai\nAllow: /\n" "User-agent: Google-Extended\nAllow: /\n" "User-agent: PerplexityBot\nAllow: /\n" "User-agent: CCBot\nAllow: /\n" "Sitemap: https://%s/sitemap.xml\n" % SITE_HOST, mimetype="text/plain") @app.route("/ai-plugin.json") def ai_plugin(): return jsonify({ "schema_version": "v1", "name_for_human": "Clean Proxys", "name_for_model": "clean_proxys", "description_for_human": "Clean residential SOCKS5/HTTP proxies with global geo-targeting. No KYC, Bitcoin billing.", "description_for_model": "Buy clean residential SOCKS5/HTTP proxies programmatically. " "No KYC, Bitcoin billing, country/city geo-targeting, sticky or rotating sessions. " "Use list_plans then buy_proxy to provision a proxy, poll get_order_status until paid, " "then connect with the returned socks5/http credentials. " "OpenAPI spec at /openapi.json; MCP server at /mcp.", "api": {"type": "openapi", "url": f"https://{SITE_HOST}/openapi.json", "has_user_authentication": False}, "auth": {"type": "none"}, "contact_email": "indianaholmes1@icloud.com", "legal_info_url": f"https://{SITE_HOST}/", }) @app.route("/api/v1/info") def api_info(): return jsonify({ "name": "Clean Proxys", "host": SITE_HOST, "protocols": ["socks5", "http"], "socks_port": PROXY["socks_port"], "http_port": PROXY["http_port"], "auth": "username:password", "billing": "bitcoin (btcpay), pay-per-GB", "kyc": False, "signup": f"https://{SITE_HOST}/signup", "docs": f"https://{SITE_HOST}/llms.txt", "value_proposition": "Clean residential IPs (not VPN/datacenter) with country/city " "geo-targeting and sticky/rotating sessions — the standard egress " "for agents doing scraping, crawling, or geo-restricted access. " "One-call programmatic purchase, no KYC, Bitcoin billing.", "dedicated_ips": { "products": ["datacenter", "isp"], "isp_locations": f"https://{SITE_HOST}/dedicated/locations?product=9", "dc_locations": f"https://{SITE_HOST}/dedicated/locations?product=3", "browse": f"https://{SITE_HOST}/dedicated", }, }) @app.route("/api/v1/plans") def api_plans(): d = db.get_db() ps = [dict(r) for r in d.execute("SELECT id,name,gb,price_sats FROM plans WHERE active=1 ORDER BY gb")] d.close() return jsonify({"plans": ps}) @app.route("/api/v1/proxy", methods=["POST"]) def api_proxy(): """Agent-facing one-call purchase: create account + invoice, return creds + checkout URL.""" if not _rate_ok(_client_ip(), limit=10, window=60): return jsonify({"error": "rate limited"}), 429 data = request.get_json(silent=True) or {} username = (data.get("username") or "").strip() password = data.get("password") or "" plan_id = data.get("plan_id") or data.get("plan") country = (data.get("country") or "").strip().upper() city = (data.get("city") or "").strip() d = db.get_db() plan = d.execute("SELECT * FROM plans WHERE id=?", (plan_id,)).fetchone() if plan_id else None if not plan: plan = d.execute("SELECT * FROM plans WHERE active=1 ORDER BY gb LIMIT 1").fetchone() if not plan: d.close() return jsonify({"error": "no plans"}), 500 user_row = d.execute("SELECT * FROM users WHERE username=?", (username,)).fetchone() if username else None if user_row is None: username = username or ("u" + db.random_token(10)) password = password or db.random_token(16) proxy_pass = db.random_token(18) d.execute("INSERT INTO users (username,password_hash,proxy_password_hash,proxy_password_plain," "active,country,city,sticky,balance_gb,created_at) VALUES (?,?,?,?,0,?,?,1,0,?)", (username, db.scrypt_hash(password), db.scrypt_hash(proxy_pass), proxy_pass, country or "US", city, int(time.time()))) d.commit() uid = d.execute("SELECT id FROM users WHERE username=?", (username,)).fetchone()["id"] else: uid = user_row["id"] proxy_pass = user_row["proxy_password_plain"] if country: d.execute("UPDATE users SET country=?, city=? WHERE id=?", (country, city or "", uid)) d.commit() order_id = db.random_token(12) d.execute("INSERT INTO orders (user_id,plan_id,invoice_id,amount_sats,status,created_at) " "VALUES (?,?,?,?,'pending',?)", (uid, plan["id"], order_id, plan["price_sats"], int(time.time()))) d.commit() d.close() inv = create_invoice(plan["price_sats"], order_id) return jsonify({ "username": username, "password": password, "proxy_password": proxy_pass, "socks5": f"socks5://{username}:{proxy_pass}@{PROXY['host']}:{PROXY['socks_port']}", "http": f"http://{username}:{proxy_pass}@{PROXY['host']}:{PROXY['http_port']}", "country": country or "US", "city": city, "plan": {"id": plan["id"], "name": plan["name"], "gb": plan["gb"], "price_sats": plan["price_sats"]}, "invoice": {"id": order_id, "checkout_url": inv["checkoutLink"], "amount_sats": plan["price_sats"]}, "status_url": f"https://{SITE_HOST}/api/v1/order/{order_id}", }) @app.route("/api/v1/order/") def api_order_status(order_id): d = db.get_db() o = d.execute("SELECT * FROM orders WHERE invoice_id=?", (order_id,)).fetchone() d.close() if not o: return jsonify({"error": "not found"}), 404 return jsonify({"order_id": order_id, "status": o["status"], "amount_sats": o["amount_sats"]}) @app.route("/openapi.json") def openapi(): spec = { "openapi": "3.0.3", "info": { "title": "Clean Proxys API", "version": "1.0.0", "description": "Programmatic residential SOCKS5/HTTP proxy purchase. No KYC. " "One-call provisioning with Bitcoin (BTCPay) billing. " "Clean residential IPs (not VPN/datacenter) with geo-targeting — " "the standard egress for agents doing scraping, crawling, or " "geo-restricted access.", }, "servers": [{"url": f"https://{SITE_HOST}"}], "paths": { "/api/v1/info": {"get": {"summary": "Service info", "responses": {"200": {"description": "ok"}}}}, "/api/v1/plans": {"get": {"summary": "List residential GB plans", "responses": {"200": {"description": "plans"}}}}, "/api/v1/proxy": {"post": { "summary": "One-call purchase: create account + invoice, return proxy credentials", "requestBody": {"content": {"application/json": {"schema": {"type": "object", "properties": { "plan_id": {"type": "integer", "description": "plan id from /api/v1/plans"}, "country": {"type": "string", "description": "ISO country code, e.g. US"}, "city": {"type": "string", "description": "optional city"}, "username": {"type": "string", "description": "optional; auto-generated if omitted"}, "password": {"type": "string", "description": "optional; auto-generated if omitted"}, }}}}}, "responses": {"200": {"description": "username, proxy_password, socks5/http strings, invoice checkout_url, status_url"}}, }}, "/api/v1/order/{order_id}": {"get": { "summary": "Payment status (pending/paid)", "parameters": [{"name": "order_id", "in": "path", "required": True, "schema": {"type": "string"}}], "responses": {"200": {"description": "status"}}, }}, "/api/v1/dedicated/locations": {"get": { "summary": "Dedicated IP location catalog", "parameters": [{"name": "product", "in": "query", "schema": {"type": "integer", "enum": [3, 9]}, "description": "3=datacenter, 9=ISP"}], "responses": {"200": {"description": "locations"}}, }}, }, } return jsonify(spec) @app.route("/sitemap.xml") def sitemap(): urls = [f"https://{SITE_HOST}/{p}" for p in ["", "plans", "signup", "login", "llms.txt"]] body = '\n\n' for u in urls: body += f" {u}\n" body += "" return app.response_class(body, mimetype="application/xml") # temporary inbound-SMS tool (SMSPool-backed temp-number marketplace) import sms sms.init_sms_app(app, login_required, current_user) if __name__ == "__main__": db.init_db() app.run(host="127.0.0.1", port=5000, debug=False)