Files
dark0rbits/app.py

420 lines
26 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""AURIGA — homelab toolbox: IP intel, card validator, SMS rentals, proxy tools."""
import base64, binascii, hashlib, json, os, re, secrets, socket, sqlite3, string, struct, time, uuid
import urllib.request, urllib.parse
from flask import Flask, request, jsonify, render_template_string, g
app = Flask(__name__)
DB_PATH = os.environ.get("AURIGA_DB", "/opt/auriga/auriga.db")
SMSP_KEY = os.environ.get("SMSP_KEY", "")
PLEIADES_GW = os.environ.get("PLEIADES_GW", "10.30.20.178:8080")
PLEIADES_APP = os.environ.get("PLEIADES_APP", "http://10.30.20.178:5000")
BMAC = "https://buymeacoffee.com/r26xrthzttg"
def db():
con = sqlite3.connect(DB_PATH); con.row_factory = sqlite3.Row
con.execute("""CREATE TABLE IF NOT EXISTS sms_rentals(
id INTEGER PRIMARY KEY, phone TEXT, service TEXT, country TEXT,
purchase_id TEXT, cost REAL, status TEXT, created INTEGER, expires INTEGER)""")
con.execute("""CREATE TABLE IF NOT EXISTS proxy_checks(
id INTEGER PRIMARY KEY, user_key TEXT, egress_ip TEXT, geo TEXT, ok INTEGER, ts INTEGER)""")
return con
def http(url, headers=None, data=None, method="GET", timeout=12):
req = urllib.request.Request(url, headers=headers or {}, data=data, method=method)
try:
with urllib.request.urlopen(req, timeout=timeout) as r:
return r.status, r.read().decode("utf-8", "replace")
except urllib.error.HTTPError as e:
return e.code, e.read().decode("utf-8", "replace")
except Exception as e:
return 0, str(e)
def jf(b):
try: return json.loads(b)
except Exception: return None
BASE = """<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<meta name=robots content="noindex"><title>AURIGA — Toolbox</title>
<style>
:root{--bg:#0b0e17;--card:#141a2b;--fg:#e8ecf7;--dim:#8b95b3;--acc:#f0b429;--ok:#3ecf8e;--bad:#ff5d5d}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.5 ui-monospace,Menlo,Consolas,monospace}
nav{display:flex;flex-wrap:wrap;gap:.4rem;padding:1rem 1.4rem;border-bottom:1px solid #232b45;position:sticky;top:0;background:var(--bg);z-index:5}
nav a{color:var(--dim);text-decoration:none;padding:.45rem .9rem;border:1px solid #232b45;border-radius:999px}
nav a.on,nav a:hover{color:var(--acc);border-color:var(--acc)}
main{max-width:960px;margin:0 auto;padding:2rem 1.4rem}
h1{font-size:1.7rem;letter-spacing:.2em}h1 span{color:var(--acc)}
.sub{color:var(--dim);margin:.3rem 0 1.6rem}
.card{background:var(--card);border:1px solid #232b45;border-radius:14px;padding:1.2rem 1.4rem;margin:1rem 0}
.kv{display:grid;grid-template-columns:minmax(140px,220px) 1fr;gap:.3rem 1rem}
.kv div:nth-child(odd){color:var(--dim)}
input,select,button,textarea{font:inherit;background:#0e1424;color:var(--fg);border:1px solid #2a3555;border-radius:8px;padding:.6rem .8rem}
button{background:var(--acc);color:#111;border:0;font-weight:700;cursor:pointer}
button:hover{filter:brightness(1.1)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
@media(max-width:700px){.grid2{grid-template-columns:1fr}.kv{grid-template-columns:1fr}}
.tag{display:inline-block;padding:.15rem .6rem;border-radius:999px;font-size:.8rem;border:1px solid}
.tag.ok{color:var(--ok);border-color:var(--ok)}.tag.bad{color:var(--bad);border-color:var(--bad)}.tag.warn{color:var(--acc);border-color:var(--acc)}
table{width:100%;border-collapse:collapse}td,th{padding:.4rem;border-bottom:1px solid #232b45;text-align:left;font-size:.9rem}
footer{color:var(--dim);text-align:center;padding:2rem;font-size:.85rem}footer a{color:var(--acc)}
.spin{display:inline-block;animation:r 1s linear infinite}@keyframes r{to{transform:rotate(360deg)}}
</style></head><body>
<nav>
<a href=/ class={{o(ip)}}>◈ WHATS-MY-IP</a><a href=/card class={{o(card)}}>◈ CARD CHECK</a>
<a href=/sms class={{o(sms)}}>◈ SMS RENTAL</a><a href=/proxy class={{o(proxy)}}>◈ PROXY LAB</a>
<a href=/tools class={{o(tools)}}>◈ FREE TOOLS</a>
</nav><main>{{body}}</main>
<footer>Built for agents &amp; humans · <a href="{{bmac}}" target=_blank rel=noopener>☕ fuel the lab</a></footer>
<script defer src="https://analytics.thetempleofdoom.com/script.js" data-website-id="953c15df-ba4c-453a-a7c6-465fa9e3f202"></script>
</body></html>"""
def page(sec, body):
return render_template_string(BASE, body=body, bmac=BMAC, o=lambda s: "on" if s == sec else "")
def kv(pairs):
rows = "".join(f"<div>{k}</div><div>{v}</div>" for k, v in pairs)
return f'<div class="card"><div class="kv">{rows}</div></div>'
# ---------- 1. WHAT'S MY IP ----------
@app.route("/ip")
def ip_route(): return ip_lookup()
def ip_lookup():
ip = request.headers.get("X-Real-IP") or request.remote_addr or ""
st, b = http(f"http://ip-api.com/json/{ip}?fields=66846719")
d = jf(b) or {}
hdrs = {k: v for k, v in request.headers.items() if k.lower() in
("user-agent","accept-language","x-forwarded-for","cf-connecting-ip","cf-ipcountry","x-real-ip")}
proxy_hint = any(k.lower().startswith(("x-forwarded","via","proxy")) for k in request.headers.keys())
rows = [
("YOUR IP", f"<b style='font-size:1.3rem;color:var(--acc)'>{d.get('query', ip)}</b>"),
("Country", f"{d.get('country','?')} ({d.get('countryCode','?')}) 🏴 {d.get('flag') if 'flag' in d else ''}".strip()),
("Region / City", f"{d.get('regionName','?')} / {d.get('city','?')} {d.get('zip','')}"),
("Lat, Lon", f"{d.get('lat','?')}, {d.get('lon','?')} · TZ: {d.get('timezone','?')} · UTC offset {d.get('offset','?')}s"),
("ISP", d.get('isp','?')), ("Organization", d.get('org','?')), ("AS", d.get('as','?') if d.get('as') else d.get('asname','?')),
("Reverse DNS", str(d.get('reverse','—'))),
("Connection", f"mobile: {d.get('mobile')} · proxy/VPN: {d.get('proxy')} · hosting: {d.get('hosting')}"),
("Local guess", d.get('district') or '—'),
("Proxy headers seen", "YES ⚠ (you're behind a relay)" if proxy_hint else "none — looks direct"),
("Currency", d.get('currency','?')),
]
hdr_rows = "".join(f"<tr><td>{k}</td><td>{v}</td></tr>" for k, v in hdrs.items())
body = f"""
<h1>WHATS <span>MY IP</span></h1><p class=sub>Every drop of intel we can legally scrape, always on.</p>
{kv(rows)}
<div class=card><b>Headers you sent</b><table>{hdr_rows}</table></div>
<div class=card><b>Live check</b> — your browser also resolved this page in
<span id=ms>…</span>. <script>t=performance.timing.responseStart-performance.timing.requestStart;
document.getElementById('ms').textContent=Math.max(0,t)+' ms';</script></div>
<div class=card>API: <code>GET /api/ip</code> → same data as JSON. Agent-friendly.</div>"""
return page("ip", body)
@app.route("/api/ip")
def api_ip():
ip = request.headers.get("X-Real-IP") or request.remote_addr or ""
st, b = http(f"http://ip-api.com/json/{ip}?fields=66846719")
d = jf(b) or {}
d["headers_seen"] = {k: v for k, v in request.headers.items()}
return jsonify(d)
# ---------- 2. CARD CHECK ----------
def luhn_ok(num):
digits = [int(c) for c in num]
odd = digits[-1::-2]; even = digits[-2::-2]
s = sum(odd)
for d in even:
d *= 2
if d > 9: d -= 9
s += d
return s % 10 == 0
BRANDS = [("4","Visa"),("51","Mastercard"),("52","Mastercard"),("53","Mastercard"),("54","Mastercard"),("55","Mastercard"),
("22","Mastercard"),("23","Mastercard"),("24","Mastercard"),("25","Mastercard"),("26","Mastercard"),("27","Mastercard"),
("34","Amex"),("37","Amex"),("6011","Discover"),("65","Discover"),("644","Discover"),("645","Discover"),("646","Discover"),("647","Discover"),("648","Discover"),("649","Discover"),
("50","Maestro"),("56","Maestro"),("57","Maestro"),("58","Maestro"),("63","Maestro"),("67","Maestro"),
("30","Diners"),("36","Diners"),("38","Diners"),("39","Diners"),
("35","JCB"),("62","UnionPay"),("7","Mir")]
def brand_of(num):
for pfx, b in BRANDS:
if num.startswith(pfx): return b
return "Unknown"
@app.route("/card", methods=["GET", "POST"])
def card():
result = ""
num = re.sub(r"\D", "", request.form.get("num", ""))[:19]
if num:
tags = []
ok = luhn_ok(num)
tags.append(('<span class="tag ok">LUHN VALID</span>' if ok else '<span class="tag bad">LUHN INVALID — fake/dead number</span>'))
brand = brand_of(num)
bin8 = num[:8]
st, b = http(f"https://lookup.binlist.net/{bin8}", headers={"Accept-Version": "3"})
bl = jf(b) or {}
bank = (bl.get("bank") or {}).get("name", "—")
country = (bl.get("country") or {}).get("name", "—")
ctype = bl.get("type", "—")
prepaid = bl.get("prepaid", "—")
if not bl: tags.append('<span class="tag warn">BIN DB no data — structure-only result</span>')
flags = []
if ctype == "prepaid" or prepaid is True: flags.append("PREPAID — commonly flagged by merchants")
if ctype == "debit": flags.append("DEBIT")
if ctype == "credit": flags.append("CREDIT")
length = len(num)
rng = {"Visa":(13,16,19),"Mastercard":(16,),"Amex":(15,),}.get(brand, (13,15,16,19))
if length not in rng: tags.append(f'<span class="tag bad">LENGTH {length} WRONG for {brand}</span>')
else: tags.append(f'<span class="tag ok">length {length} valid for {brand}</span>')
result = f"""
{kv([("Brand",brand),("BIN",bin8),("Bank / Issuer",bank),("Country",country),("Type",str(ctype)),("Prepaid",str(prepaid))])}
<div class=card><b>Fraud &amp; structure flags</b><br>{' '.join(tags)}
{'<br>⚠ ' + ' · '.join(flags) if flags else ''}</div>
<div class=card style=color:var(--dim)>Nothing is stored. No charge, no auth, no $0 check — this is BIN + math validation only.
It cannot tell you if a card has available funds. Fraud "flagged" status lives at the issuer, not in any database we can legally query.</div>"""
body = f"""
<h1>CARD <span>CHECK</span></h1><p class=sub>Is it real? Luhn + BIN intelligence: issuer, brand, type, country, prepaid risk flags.</p>
<div class=card><form method=post><input name=num placeholder="4539 1488 0343 6467" style="width:70%" value="{num}"> <button>Check</button></form></div>
{result}"""
return page("card", body)
# ---------- 3. SMS RENTALS ----------
SMSP = "https://api.smspool.net"
SERVICES = [("google","Google"),("discord","Discord"),("telegram","Telegram"),("whatsapp","WhatsApp"),("other","Other/Any")]
COUNTRIES = [("1","United States"),("2","United Kingdom"),("4","Netherlands"),("22","Russia"),("150","Germany")]
def sms_api(path, **kw):
if kw:
kw["key"] = SMSP_KEY
data = urllib.parse.urlencode(kw).encode()
return http(f"{SMSP}/{path}", data=data, method="POST")
return http(f"{SMSP}/{path}?key={SMSP_KEY}")
@app.route("/sms", methods=["GET", "POST"])
def sms():
msg, listing = "", ""
if request.method == "POST":
act = request.form.get("act")
if act == "rent":
svc, ctry = request.form["service"], request.form["country"]
st, b = sms_api("purchase/sms", service=svc, country=ctry)
d = jf(b) or {}
if d.get("success") == 1:
con = db()
now = int(time.time())
con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)",
(d.get("number"), svc, ctry, str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800))
con.commit()
msg = f'<div class="card"><span class="tag ok">RENTED</span> Your number: <b style="font-size:1.2rem;color:var(--acc)">+{d.get("number")}</b> · expires in 30 min · order #{d.get("purchase_id")}</div>'
else:
msg = f'<div class="card"><span class="tag bad">RENT FAILED</span><br><pre>{b[:400]}</pre></div>'
elif act == "check":
pid = request.form["pid"]
st, b = sms_api("sms/check", orderid=pid)
d = jf(b) or {}
sms_txt = d.get("sms") or d.get("code") or ""
status = d.get("status", "?")
color = "ok" if sms_txt else "warn"
msg = f'<div class="card"><span class="tag {color}">STATUS: {status}</span> {"<b style=color:var(--ok)>" + str(sms_txt) + "</b>" if sms_txt else "no code yet — poll again in 10s"}</div>'
elif act == "cancel":
pid = request.form["pid"]
st, b = sms_api("sms/cancel", orderid=pid)
d = jf(b) or {}
ok = d.get("success") == 1
con = db(); con.execute("UPDATE sms_rentals SET status=? WHERE purchase_id=?", ("refunded" if ok else "cancel-failed", pid)); con.commit()
msg = f'<div class="card"><span class="tag {"ok" if ok else "bad"}">{"CANCELLED + REFUNDED" if ok else "CANCEL FAILED"}</span></div>'
st, b = sms_api("sms/instructions")
body = f"""
<h1>SMS <span>RENTAL</span></h1><p class=sub>Disposable numbers, 30-minute windows. Cancel before a code arrives = full refund.</p>
<div class="grid2">
<div class=card><b>Rent a number</b>
<form method=post><input type=hidden name=act value=rent>
<select name=service style="width:100%">{''.join(f'<option value={v}>{n}</option>' for v,n in SERVICES)}</select>
<select name=country style="width:100%;margin:.5rem 0">{''.join(f'<option value={v}>{n}</option>' for v,n in COUNTRIES)}</select>
<button>Rent — 30 min</button></form></div>
<div class=card><b>Check / manage</b>
<form method=post><input type=hidden name=act value=check><input name=pid placeholder="order # (purchase_id)" style="width:100%"><button style="margin:.5rem 0">Poll for code</button></form>
<form method=post><input type=hidden name=act value=cancel><input name=pid placeholder="order #" style="width:100%"><button style="background:var(--bad);color:#fff">Cancel &amp; refund</button></form></div>
</div>{msg}
<div class=card style=color:var(--dim)>API: POST /api/sms/rent (service,country) · /api/sms/check (pid) · /api/sms/cancel (pid)</div>"""
return page("sms", body)
@app.route("/api/sms/rent", methods=["POST"])
def api_sms_rent():
st, b = sms_api("purchase/sms", service=request.form["service"], country=request.form["country"])
d = jf(b) or {}
if d.get("success") == 1:
con = db(); now = int(time.time())
con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)",
(d.get("number"), request.form["service"], request.form["country"], str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800))
con.commit()
return jsonify(d)
@app.route("/api/sms/check", methods=["POST"])
def api_sms_check():
st, b = sms_api("sms/check", orderid=request.form["pid"])
return jf(b) or jsonify({"error": b[:200]})
@app.route("/api/sms/cancel", methods=["POST"])
def api_sms_cancel():
st, b = sms_api("sms/cancel", orderid=request.form["pid"])
return jf(b) or jsonify({"error": b[:200]})
# ---------- 4. PROXY LAB ----------
@app.route("/proxy", methods=["GET", "POST"])
def proxy():
result = ""
if request.method == "POST" and request.form.get("act") == "test":
user, pw = request.form.get("user",""), request.form.get("pass","")
test_url = request.form.get("target", "http://ip-api.com/json/?fields=66846719")
pauth = base64.b64encode(f"{user}:{pw}".encode()).decode()
try:
pu = urllib.parse.urlparse(test_url if "://" in test_url else "http://"+test_url)
req_line = f"GET {pu.path or '/'} HTTP/1.1\r\nHost: {pu.hostname}\r\nConnection: close\r\n\r\n"
s = socket.create_connection((PLEIADES_GW.split(":")[0], int(PLEIADES_GW.split(":")[1])), timeout=15)
s.sendall(f"CONNECT {pu.hostname}:80 HTTP/1.1\r\nHost: {pu.hostname}:80\r\nProxy-Authorization: Basic {pauth}\r\n\r\n".encode())
resp = s.recv(4096)
if b"200" in resp.split(b"\r\n")[0]:
s.sendall(req_line.encode())
data = b""
while True:
c = s.recv(8192)
if not c: break
data += c
s.close()
body = data.split(b"\r\n\r\n",1)[-1].decode("utf-8","replace")
j = jf(body) or {}
con = db()
con.execute("INSERT INTO proxy_checks(user_key,egress_ip,geo,ok,ts) VALUES(?,?,?,?,?)",
(user[:12], j.get("query","?"), f"{j.get('country')}/{j.get('city')}", 1, int(time.time())))
con.commit()
result = f'<div class="card"><span class="tag ok">PROXY LIVE</span> Egress: <b style=color:var(--acc)>{j.get("query")}</b> — {j.get("country")} / {j.get("city")} · ISP {j.get("isp")} · tz {j.get("timezone")}</div>'
else:
con = db()
con.execute("INSERT INTO proxy_checks(user_key,egress_ip,geo,ok,ts) VALUES(?,?,?,?,?)", (user[:12], "", "", 0, int(time.time())))
con.commit()
result = f'<div class="card"><span class="tag bad">AUTH/TUNNEL FAILED</span><pre>{resp[:200]!r}</pre></div>'
except Exception as e:
result = f'<div class="card"><span class="tag bad">ERROR</span> {e}</div>'
body = f"""
<h1>PROXY <span>LAB</span></h1><p class=sub>Rent residential proxies on the Pleiades rail — your existing gateway <code>user:pass</code> works here, same keys as everywhere.</p>
<div class=card><form method=post><input type=hidden name=act value=test>
<label>Gateway user</label><br><input name=user style="width:100%" placeholder="gw_… or your Pleiades username"><br>
<label style=color:var(--dim)>Password</label><br><input name=pass type=password style="width:100%"><br>
<button style=margin-top:.6rem>Test egress now</button></form></div>
{result}
<div class=card><b>Rent more</b> — buy GB plans &amp; geo-targeted sessions at the storefront:
<a href="{PLEIADES_APP}" style=color:var(--acc)>{PLEIADES_APP}</a>. Region/country/city suffixes on your password control geo; add
<code>_session-XXXX_lifetime-30m</code> for sticky 30-min IPs.</div>
<div class=card style=color:var(--dim)>API: POST /api/proxy/test (user, pass) → egress IP + geo JSON.</div>"""
return page("proxy", body)
@app.route("/api/proxy/test", methods=["POST"])
def api_proxy_test():
user, pw = request.form.get("user",""), request.form.get("pass","")
pauth = base64.b64encode(f"{user}:{pw}".encode()).decode()
try:
s = socket.create_connection((PLEIADES_GW.split(":")[0], int(PLEIADES_GW.split(":")[1])), timeout=15)
s.sendall(f"CONNECT ip-api.com:80 HTTP/1.1\r\nHost: ip-api.com:80\r\nProxy-Authorization: Basic {pauth}\r\n\r\n".encode())
resp = s.recv(4096)
if b"200" not in resp.split(b"\r\n")[0]: return jsonify({"ok": False, "raw": resp[:120].decode("utf-8","replace")})
s.sendall(b"GET /json/?fields=66846719 HTTP/1.1\r\nHost: ip-api.com\r\nConnection: close\r\n\r\n")
data = b""
while True:
c = s.recv(8192)
if not c: break
data += c
s.close()
j = jf(data.split(b"\r\n\r\n",1)[-1].decode("utf-8","replace")) or {}
return jsonify({"ok": True, "egress": j})
except Exception as e:
return jsonify({"ok": False, "error": str(e)})
# ---------- 5. FREE TOOLS ----------
TOOLS_JS = """
function tab(n){document.querySelectorAll('.pane').forEach(p=>p.style.display='none');document.getElementById(n).style.display='block';
document.querySelectorAll('.tbtn').forEach(b=>b.classList.remove('on'));event.target.classList.add('on')}
async function dns(){const d=document.getElementById('dq').value;const o=await (await fetch('https://dns.google/resolve?name='+encodeURIComponent(d)+'&type=A')).json();document.getElementById('do').textContent=JSON.stringify(o,null,1)}
async function hdr(){const u=document.getElementById('hq').value;const r=await (await fetch('/api/hdr?url='+encodeURIComponent(u))).json();document.getElementById('ho').textContent=JSON.stringify(r,null,1)}
function jwt(){try{const t=document.getElementById('jq').value.trim().split('.');const d=s=>JSON.stringify(JSON.parse(atob(s.replace(/-/g,'+').replace(/_/g,'/'))),null,1);document.getElementById('jo').textContent='HEADER\\n'+d(t[0])+'\\n\\nPAYLOAD\\n'+d(t[1])+'\\n\\n(signature: '+t[2]+')'}catch(e){document.getElementById('jo').textContent='Invalid JWT: '+e}}
function genhash(){const i=document.getElementById('hq2').value;['md5','sha1','sha256','sha512'].forEach(a=>{document.getElementById('h_'+a).textContent=hashlib(a,i)})}
function hashlib(a,s){return a}
async function genhash2(){const i=document.getElementById('hq2').value;const r=await(await fetch('/api/hash?s='+encodeURIComponent(i))).json();for(const k of ['md5','sha1','sha256','sha512'])document.getElementById('h_'+k).textContent=r[k]}
function uuids(){let o='';for(let i=0;i<5;i++)o+=crypto.randomUUID()+'\\n';document.getElementById('uo').textContent=o}
function pwgen(){const l=+document.getElementById('pl').value||24;const cs='abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%^&*-_=+';const a=new Uint32Array(l);crypto.getRandomValues(a);document.getElementById('po').textContent=Array.from(a,x=>cs[x%cs.length]).join('')}
"""
@app.route("/api/hdr")
def api_hdr():
url = request.args.get("url","")
if "://" not in url: url = "http://" + url
try:
req = urllib.request.Request(url, headers={"User-Agent":"Auriga/1.0"})
with urllib.request.urlopen(req, timeout=12) as r:
return jsonify({"status": r.status, "final_url": r.url, "headers": dict(r.headers)})
except Exception as e:
return jsonify({"error": str(e)})
@app.route("/api/hash")
def api_hash():
s = request.args.get("s","").encode()
return jsonify({"md5": hashlib.md5(s).hexdigest(), "sha1": hashlib.sha1(s).hexdigest(),
"sha256": hashlib.sha256(s).hexdigest(), "sha512": hashlib.sha512(s).hexdigest()})
@app.route("/tools")
def tools():
body = f"""
<h1>FREE <span>TOOLS</span></h1><p class=sub>High-value, zero-cost, no signup. Agent-friendly APIs underneath each.</p>
<style>.tbtn.on{{background:var(--acc);color:#111}}</style>
<div style=margin-bottom:1rem>
<button class="tbtn on" onclick="tab('dns_p')">DNS Lookup</button>
<button class=tbtn onclick="tab('hdr_p')">HTTP Headers</button>
<button class=tbtn onclick="tab('jwt_p')">JWT Decoder</button>
<button class=tbtn onclick="tab('hash_p')">Hasher</button>
<button class=tbtn onclick="tab('gen_p')">Generators</button></div>
<script>{TOOLS_JS}</script>
<div id=dns_p class="card pane"><b>DNS Lookup</b> <span style=color:var(--dim)>(Google DoH)</span><br>
<input id=dq placeholder=thetempleofdoom.com style=width:70%><button onclick=dns()>Resolve</button>
<pre id=do style=white-space:pre-wrap></pre><div style=color:var(--dim)>API: /api/hdr style JSON via dns.google</div></div>
<div id=hdr_p class="card pane" style=display:none><b>HTTP Header Inspector</b><br>
<input id=hq placeholder=https://lynx.thetempleofdoom.com style=width:70%><button onclick=hdr()>Inspect</button>
<pre id=ho style=white-space:pre-wrap></pre><div style=color:var(--dim)>API: GET /api/hdr?url=…</div></div>
<div id=jwt_p class="card pane" style=display:none><b>JWT Decoder</b> (client-side, token never leaves your browser)<br>
<textarea id=jq rows=3 style="width:100%">paste eyJ…</textarea><button onclick=jwt()>Decode</button>
<pre id=jo style=white-space:pre-wrap></pre></div>
<div id=hash_p class="card pane" style=display:none><b>Hasher</b><br>
<input id=hq2 placeholder="any string" style=width:70%><button onclick=genhash2()>Hash</button>
<table><tr><th>md5</th><td id=h_md5></td></tr><tr><th>sha1</th><td id=h_sha1></td></tr>
<tr><th>sha256</th><td id=h_sha256></td></tr><tr><th>sha512</th><td id=h_sha512></td></tr></table>
<div style=color:var(--dim)>API: GET /api/hash?s=…</div></div>
<div id=gen_p class="card pane" style=display:none><b>Generators</b><br>
<button onclick=uuids()>5× UUIDv4</button><pre id=uo></pre>
<label>password length</label> <input id=pl value=24 style=width:80px><button onclick=pwgen()>Generate</button>
<pre id=po style="font-size:1.2rem;color:var(--acc)"></pre></div>"""
return page("tools", body)
@app.route("/")
def index():
st, b = http(f"http://ip-api.com/json/{request.headers.get('X-Real-IP') or request.remote_addr}?fields=66846719")
d = jf(b) or {}
con = db()
n_sms = con.execute("SELECT COUNT(*) c FROM sms_rentals").fetchone()["c"]
n_px = con.execute("SELECT COUNT(*) c FROM proxy_checks").fetchone()["c"]
body = f"""
<h1>AURIGA <span>TOOLBOX</span></h1>
<p class=sub>One page. Every network weapon you actually use. No signup, no fluff.</p>
<div class=grid2>
<div class=card><h3>◈ Whats-My-IP MAX</h3><p style=color:var(--dim)>You're connecting from <b style=color:var(--acc)>{d.get('query','?')}</b> — {d.get('city','')}, {d.get('country','')}. Full dump: geo, ASN, ISP, VPN flags, rDNS, headers.</p><a href=/ip><button>Open</button></a> <a href=/api/ip><button style=background:#232b45;color:var(--fg)>API</button></a></div>
<div class=card><h3>◈ Card Check</h3><p style=color:var(--dim)>Luhn + BIN: brand, issuer, country, type, prepaid risk flags. Nothing stored, nothing charged.</p><a href=/card><button>Open</button></a></div>
<div class=card><h3>◈ SMS Rental</h3><p style=color:var(--dim)>Disposable numbers, 30-minute windows, cancel = refund. {n_sms} rentals served.</p><a href=/sms><button>Open</button></a></div>
<div class=card><h3>◈ Proxy Lab</h3><p style=color:var(--dim)>Test + rent residential proxies. Same gateway keys as the other sites. {n_px} checks run.</p><a href=/proxy><button>Open</button></a></div>
<div class=card><h3>◈ Free Tools</h3><p style=color:var(--dim)>DNS, HTTP headers, JWT, hasher, UUID/password generators.</p><a href=/tools><button>Open</button></a></div>
<div class=card><h3>◈ API-first</h3><p style=color:var(--dim)>Every tool has a JSON API. Agents welcome — that's the point.</p></div>
</div>"""
return page("ip", body)
@app.route("/health")
def health(): return jsonify({"ok": True, "service": "auriga"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, threaded=True)