v5: SNAP LINKS — server-free shortener (/s). Target rides in the #fragment (base64url), decoded in the opener's browser with 5s safety preview, host readout, cancel, QR, 10-slot localStorage history. /api/snap/decode for agents to inspect a snap without opening it.

This commit is contained in:
drjones
2026-10-07 15:08:02 -07:00
parent 6d49c5dcfc
commit 735a58266d

146
app.py
View File

@@ -371,7 +371,7 @@ li::marker{color:var(--acc)}
<a href=/canary class={{o('canary')}}>CANARY</a><a href=/deaddrop class={{o('deaddrop')}}>DEAD-DROP</a><a href=/mail class={{o('mail')}}>BURNER-MAIL</a>
<a href=/shot class={{o('shot')}}>SHOT</a><a href=/score class={{o('score')}}>FRAUD-SCORE</a>
<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=/maglab class={{o('maglab')}}>MAG-LAB</a><a href=/beacon class={{o('beacon')}}>PORT BEACON</a><a href=/bssid class={{o('bssid')}}>BSSID RADAR</a><a href=/hooks class={{o('hooks')}}>HOOK-RELAY</a><a href=/face class={{o('face')}}>FACE TRACE</a><a href=/rotator class={{o('rotator')}}>ROTATOR</a><a href=/shelf class={{o('shelf')}}>SHELF</a><a href=/unfurl class={{o('unfurl')}}>UNFURL</a><a href=/warp class={{o('warp')}}>WARP</a><a href=/tools class={{o('tools')}}>TOOLS</a>
<a href=/pass class={{o('pass')}}>PASS</a><a href=/keys class={{o('keys')}}>KEYS</a><a href=/maglab class={{o('maglab')}}>MAG-LAB</a><a href=/beacon class={{o('beacon')}}>PORT BEACON</a><a href=/bssid class={{o('bssid')}}>BSSID RADAR</a><a href=/hooks class={{o('hooks')}}>HOOK-RELAY</a><a href=/face class={{o('face')}}>FACE TRACE</a><a href=/rotator class={{o('rotator')}}>ROTATOR</a><a href=/shelf class={{o('shelf')}}>SHELF</a><a href=/s class={{o('s')}}>SNAP</a><a href=/unfurl class={{o('unfurl')}}>UNFURL</a><a href=/warp class={{o('warp')}}>WARP</a><a href=/tools class={{o('tools')}}>TOOLS</a>
</div>
<div id="acct">{{acct}}</div><button class=burger id=burger onclick="drw()">☰</button>
</div></header>
@@ -407,6 +407,7 @@ li::marker{color:var(--acc)}
<a class="dl {{o('face')}}" href=/face>◈ FACE TRACE <small>profile-picture triangulation — hash an avatar, harvest a username's pfps, Hamming verdicts</small></a>
<a class="dl {{o('rotator')}}" href=/rotator>◈ ROTATOR <small>consistent browser identity pools with replayable seeds</small></a>
<a class="dl {{o('shelf')}}" href=/shelf>◈ SHELF <small>every burner you own, with live countdowns</small></a>
<a class="dl {{o('s')}}" href=/s>◈ SNAP <small>server-free one-click short links — target lives in the #fragment</small></a>
<a class="dl {{o('unfurl')}}" href=/unfurl>◈ UNFURL <small>Follow every redirect hop manually and dissect the final page</small></a>
<a class="dl {{o('warp')}}" href=/warp>◈ WARP <small>Domain time machine — Wayback snapshots, previews, DNS drift</small></a>
<h4>Account</h4>
@@ -567,6 +568,7 @@ var PAL=[
["/face", "avatar pfp triangulation"],
["/rotator", "header rotator \u2014 identity pools + seeds"],
["/shelf", "identity shelf \u2014 every burner + countdowns"],
["/s", "snap \u2014 server-free short links + safety decoder"],
["/unfurl", "redirect chain + page dissection"],
["/warp", "domain time machine \u2014 wayback timeline, previews, DNS drift"],
['/llms.txt','machine catalog for agents'],
@@ -620,6 +622,7 @@ NEBULAS = {
"score": ("rgba(255,110,180,.10)", "rgba(66,232,164,.10)"),
"warp": ("rgba(255,110,180,.11)", "rgba(120,85,255,.11)"),
"unfurl": ("rgba(255,110,180,.11)", "rgba(120,85,255,.11)"),
"s": ("rgba(111,214,255,.12)", "rgba(167,139,250,.10)"),
"shelf": ("rgba(66,232,164,.11)", "rgba(255,170,60,.09)"),
"rotator": ("rgba(111,214,255,.12)", "rgba(167,139,250,.10)"),
"face": ("rgba(255,110,180,.11)", "rgba(120,85,255,.11)"),
@@ -750,6 +753,7 @@ API_INDEX = {
{"method": "GET", "path": "/api/rotator?platform=&n=&seed=", "desc": "Spin 1-25 consistent browser identities (UA, referer, Accept-Language, DNT) from desktop/mobile/agent/stealth pools. Same seed = same rotation. Returns identities + ready-made curl. FREE, 20/min."},
{"method": "GET", "path": "/api/rotator/pools", "desc": "Pool sizes: desktop, mobile, agent, stealth + referer/language counts."},
{"method": "GET", "path": "/api/shelf", "desc": "Identity shelf: all your mailboxes, SMS numbers, dead-drops, canaries + expiry stats in one JSON. Login required. Perfect for expiry-monitoring crons."},
{"method": "POST", "path": "/api/snap/decode", "desc": "Decode a snap link fragment (raw = text after #) WITHOUT opening it: returns target URL + host + scheme check. The shortener itself is server-free — targets ride in the #fragment and nothing is stored. FREE 60/min."},
{"method": "GET", "path": "/unfurl", "desc": "URL unfurl: follows every redirect hop one at a time (scheme, host, status, Location) and dissects the final page (title, meta/og tags, iframes, forms). Detects loops and refuses non-http schemes. FREE."},
{"method": "GET", "path": "/api/unfurl", "params": {"url": "http(s):// target", "max_hops": "1-10 default 6", "extract": "0|1"}, "desc": "Full redirect chain + final-page metadata as JSON. 401 without session/key; rate-limited. FREE."},
{"method": "GET", "path": "/api/unfurl/history", "desc": "Your last 25 unfurl lookups (url, final_url, status, ts). Login required."},
@@ -857,6 +861,7 @@ def openapi():
add("/api/rotator", "get", "Spin consistent browser identities (UA+referer+language+DNT), optional deterministic seed", {"platform": "desktop|mobile|agent|stealth", "n": "1-25", "seed": "optional"})
add("/api/rotator/pools", "get", "Pool inventory")
add("/api/shelf", "get", "Identity shelf — all burners + expiry stats (login)")
add("/api/snap/decode", "post", "Decode snap-link fragment safely (no visit)", {"raw": "fragment after #"}, req=True)
add("/api/unfurl", "get", "Unfurl a URL: follow redirects hop-by-hop, dissect final page", {"url": "https://bit.ly/abc", "max_hops": "6"}, req=True)
add("/api/unfurl/history", "get", "Your last 25 unfurl lookups", {}, req=True)
add("/api/warp", "get", "Domain time machine: Wayback timeline, screenshot-preview links, DNS/whois drift, hosted paths. Cached 6h.", {"domain": "example.com"}, req=True)
@@ -4720,6 +4725,144 @@ def api_shelf():
# ---------- END TOOL: IDENTITY SHELF ----------
# ---------- TOOL: SNAP LINK (client-side shortener) ----------
_SNAP_PAGE = r"""<!doctype html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<title>▶ SNAP — one click more</title>
<style>
:root{--bg:#070a13;--card:rgba(19,25,44,.9);--line:#242e4d;--fg:#e9edf8;--dim:#93a0c2;--acc:#a78bfa;--acc2:#6fd6ff;--ok:#42e8a4;--bad:#ff6161}
*{box-sizing:border-box}
body{margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;background:radial-gradient(ellipse at 50% -10%,rgba(120,85,255,.16),transparent 55%),var(--bg);color:var(--fg);font:16px/1.6 ui-monospace,Menlo,Consolas,monospace;padding:1rem}
.card{background:var(--card);border:1px solid var(--line);border-radius:16px;padding:1.6rem;max-width:520px;width:100%;box-shadow:0 0 34px -16px var(--acc)}
h1{font-size:1.3rem;margin:0 0 .4rem;letter-spacing:.06em}
h1 b{color:var(--acc)}
.sub{color:var(--dim);font-size:.88rem;margin:0 0 1rem}
.url{background:rgba(10,15,30,.95);border:1px solid var(--line);border-radius:10px;padding:.7rem .9rem;word-break:break-all;font-size:.86rem;margin:.5rem 0}
.warn{color:var(--bad);font-size:.8rem;margin:.4rem 0}
button{font:inherit;font-weight:800;background:linear-gradient(135deg,var(--acc),var(--acc2));color:#0d0722;border:0;border-radius:10px;padding:.7rem 1.2rem;cursor:pointer;margin:.3rem .4rem .3rem 0}
button.ghost{background:transparent;color:var(--acc);border:1px solid var(--acc)}
.count{color:var(--dim);font-size:.8rem}
.noscript{color:var(--bad)}
.hist{margin-top:1.2rem;border-top:1px solid var(--line);padding-top:.9rem}
.hist h3{font-size:.78rem;color:var(--dim);letter-spacing:.2em;margin:0 0 .5rem}
.hist a{display:block;color:var(--acc2);font-size:.82rem;margin:.25rem 0;text-decoration:none;word-break:break-all}
.hist a:hover{color:var(--acc)}
.mono{font-family:ui-monospace,Menlo,monospace}
details{margin:.6rem 0;font-size:.85rem}
summary{cursor:pointer;color:var(--dim)}
</style></head><body>
<div class=card id=main>
<h1>▶ <b>SNAP</b> — one click more</h1>
<p class=sub>This is a dark0rbits snap link. The destination lives in the part of the address after the <span class=mono>#</span> — which is never sent to any server, anywhere. It decoded right here in your browser.</p>
<div id=stage class=noscript>JavaScript is off — snap links decode client-side, so this one can't open. The raw destination is visible in the address bar after the #.</div>
<div id=dest style=display:none>
<div class=warn>⚠ check where you're going — a snap link can point anywhere:</div>
<div class=url id=target></div>
<div class=count id=cd></div>
<button id=go>Open now ▸</button>
<button class=ghost id=cancel>stop</button>
<details><summary>host + full safety read</summary><div class=url id=hostread style=font-size:.8rem></div></details>
</div>
<div class=hist id=histbox style=display:none>
<h3>RECENT FROM THIS BROWSER</h3>
<div id=hist></div>
<p class=sub style=margin:.6rem 0 0;font-size:.75rem>history lives only in this browser's storage — the server keeps nothing</p>
</div>
</div>
<script>
(function(){
function d64(s){s=s.replace(/-/g,'+').replace(/_/g,'/');while(s.length%4)s+='=';return decodeURIComponent(escape(atob(s)))}
function e64(s){return btoa(unescape(encodeURIComponent(s))).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'')}
var h=location.hash.replace(/^#/,'');
var box=document.getElementById('histbox');
try{
var hist=JSON.parse(localStorage.getItem('drb_snap_hist')||'[]');
if(hist.length){
box.style.display='block';
var hh=document.getElementById('hist');
hist.forEach(function(it){
var a=document.createElement('a');a.href='#'+it.c;a.textContent='▶ '+it.t.slice(0,60);a.title=it.t;
a.onclick=function(ev){ev.preventDefault();document.getElementById('target').textContent=it.t;proceed(it.t)};
hh.appendChild(a)});
}
}catch(e){}
function showList(){}
function proceed(target){
document.getElementById('stage').style.display='none';
var dv=document.getElementById('dest');dv.style.display='block';
document.getElementById('target').textContent=target;
try{var u=new URL(target);document.getElementById('hostread').textContent='host: '+u.host+' · scheme: '+u.protocol.replace(':','')+' · path: '+u.pathname;}catch(e){document.getElementById('hostread').textContent='(could not parse as a standard web address)'}
var n=5,cd=document.getElementById('cd');cd.textContent='auto-opening in 5…';
var t=setInterval(function(){if(n<=0){clearInterval(t);location.replace(target);return}cd.textContent='auto-opening in '+n+'…';n--},1000);
document.getElementById('cancel').onclick=function(){clearInterval(t);cd.textContent='auto-open cancelled — use the button when ready.'};
document.getElementById('go').onclick=function(){clearInterval(t);location.replace(target)};
// remember (dedupe, cap 10)
try{
hist=hist.filter(function(x){return x.t!==target});
hist.unshift({t:target,c:h});
hist=hist.slice(0,10);
localStorage.setItem('drb_snap_hist',JSON.stringify(hist));
}catch(e){}
}
if(h){
try{
var target=d64(h);
if(!/^https?:\/\//i.test(target)){document.getElementById('stage').textContent='this snap link does not decode to a web address — refusing to open it.';}
else proceed(target);
}catch(e){document.getElementById('stage').textContent='this snap link is malformed or was corrupted in transit.';}
}else{
// encoder mode
document.getElementById('stage').style.display='none';
var m=document.getElementById('main');
var d=document.createElement('div');
d.innerHTML='<h3 style="font-size:1rem;margin:.4rem 0">MAKE A SNAP LINK</h3>'+
'<p class=sub>Paste a long URL. It gets packed into the link itself — after the # — so nothing is stored on any server. The short link works forever and reveals its target only in the opener\'s browser.</p>'+
'<div class=url contenteditable id=src style=min-height:2.4rem>https://</div>'+
'<button id=mk>▸ snap it</button><div id=out></div>';
m.appendChild(d);
document.getElementById('mk').onclick=function(){
var src=document.getElementById('src').textContent.trim();
if(!/^https?:\\/\\//i.test(src)){document.getElementById('out').innerHTML='<div class=warn>that is not a web address — needs http(s)://</div>';return}
var link=location.origin+'/s#'+e64(src);
document.getElementById('out').innerHTML='<div class=warn>✓ stored nowhere. copy it:</div><div class=url id=lnk>'+link+'</div><button class=ghost id=cp>copy</button> <button class=ghost id=qr>QR ▸</button><div id=qrbox></div>';
document.getElementById('cp').onclick=function(){navigator.clipboard.writeText(link).then(function(){document.getElementById('cp').textContent='copied ✓'})};
document.getElementById('qr').onclick=function(){document.getElementById('qrbox').innerHTML='<img style="max-width:200px;margin-top:.5rem;border-radius:8px" alt="QR served by external service api.qrserver.com — the snap link itself stays server-free" src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data='+encodeURIComponent(link)+'">'};
};
}
})();
</script>
</body></html>"""
@app.route("/snap")
@app.route("/s")
@app.route("/s/<path:_any>")
def snap(_any=None):
r = Response(_SNAP_PAGE, mimetype="text/html")
r.headers["Cache-Control"] = "no-store"
r.headers["X-Robots-Tag"] = "noindex"
return r
@app.route("/api/snap/decode", methods=["POST"])
def api_snap_decode():
"""Agents: decode a snap fragment server-side WITHOUT opening it. raw = text after #."""
r = rate_limit("snap", 60, 60)
if r: return r
raw = (param("raw") or "").strip()
if not raw: return jsonify({"ok": False, "error": "raw (fragment after #) required"}), 400
try:
s = raw.replace("-", "+").replace("_", "/")
s += "=" * (-len(s) % 4)
import base64 as _b
target = base64.b64decode(s).decode("utf-8", "replace")
except Exception:
return jsonify({"ok": False, "error": "not a valid snap fragment"}), 400
import re as _re
m = _re.match(r"^https?://([^/]+)", target, _re.I)
return jsonify({"ok": True, "target": target,
"host": m.group(1) if m else None,
"scheme_safe": bool(m)})
# ---------- END TOOL: SNAP LINK ----------
# ---------- TOOL: UNFURL ----------
def _unfurl_db():
con = db()
@@ -5321,6 +5464,7 @@ def index():
("face","FACE TRACE","Hash an avatar, harvest a username's profile pictures across platforms, and get Hamming verdicts — no reverse-image APIs.","◈","Hunt"),
("rotator","ROTATOR","Spin consistent browser identities from four pools with replayable seeds.","◈","UTILITY"),
("shelf","IDENTITY SHELF","Every burner you own on one page — mailboxes, numbers, drops, traps — with live countdowns so nothing dies silently.","◈","ACCOUNT"),
("s","SNAP LINKS","One-click short links with zero server storage — the target rides in the #fragment, decodes in the opener's browser, with a safety preview and QR.","◈","UTILITY"),
("unfurl", "UNFURL", "Follow every redirect hop in a URL chain and dissect the page at the end.", "◈", "Hunt"),
("warp","WARP ARCHIVE","A domain time machine: snapshot timeline from the Wayback Machine, archived-page previews, and DNS/whois drift — watch a domain morph over years.","◈","INTEL"),
("passport","AGENT PASSPORT","Machine-readable trust badge for your bots. Agents are first-class here.","◈","ACCOUNT"),