goes to a random website hosted on wisp.place

add app for serving on wisp place

ptr.pet e908fdbb 7af56907

verified
+102 -5
+1
.gitignore
··· 2 2 /.envrc 3 3 /.direnv 4 4 hydrant.db 5 + redirect.out.html
+3
build.ts
··· 1 + const html = await Deno.readTextFile("redirect.html"); 2 + const url = Deno.env.get("API_URL") ?? "/"; 3 + await Deno.writeTextFile("redirect.out.html", html.replaceAll("__API_URL__", url));
+2 -1
deno.json
··· 3 3 "version": "0.1.0", 4 4 "tasks": { 5 5 "start": "deno run -A --unstable-kv main.ts", 6 - "dev": "deno run -A --unstable-kv --watch main.ts" 6 + "dev": "deno run -A --unstable-kv --watch main.ts", 7 + "build": "deno run -A build.ts" 7 8 } 8 9 }
+18 -4
main.ts
··· 203 203 return null; 204 204 }; 205 205 206 + const corsHeaders = { 207 + headers: { 208 + "Access-Control-Allow-Origin": "*", 209 + "Access-Control-Allow-Methods": "GET", 210 + } 211 + }; 206 212 Deno.serve({ port: PORT }, async (req) => { 213 + if (req.method === "OPTIONS") { 214 + return new Response(null, { status: 204, ...corsHeaders }); 215 + } 216 + 207 217 const { pathname } = new URL(req.url); 208 218 209 219 if (pathname === "/health") { 210 220 const sites = await allSites(); 211 - return Response.json({ 221 + const data = { 212 222 total: sites.length, 213 223 withDomain: sites.filter((s) => s.domainUrl).length, 214 - }); 224 + }; 225 + return Response.json(data, corsHeaders); 215 226 } 216 227 217 228 const site = await pickRandomReachable(await allSites()); 218 229 return site 219 - ? new Response(JSON.stringify(site)) 220 - : new Response("no sites discovered yet, try again later", { status: 503 }); 230 + ? Response.json(site, corsHeaders) 231 + : new Response( 232 + "no sites discovered yet, try again later", 233 + { status: 503, ...corsHeaders }, 234 + ); 221 235 }); 222 236 console.log(`[?] listening on :${PORT}`); 223 237
+78
redirect.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <title>redirecting...</title> 6 + <style> 7 + body { 8 + margin: 0; 9 + min-height: 100vh; 10 + display: flex; 11 + flex-direction: column; 12 + align-items: center; 13 + justify-content: center; 14 + background: #0d0d0d; 15 + color: #aaa; 16 + } 17 + p { 18 + font-size: 0.9rem; 19 + letter-spacing: 0.05em; 20 + } 21 + .bar { 22 + position: fixed; 23 + bottom: 0; 24 + left: 0; 25 + width: 100%; 26 + height: 2px; 27 + } 28 + .bar::after { 29 + content: ""; 30 + position: absolute; 31 + height: 2px; 32 + width: 40%; 33 + background: #aaa; 34 + animation: bounce 1.4s ease-in-out infinite; 35 + } 36 + @keyframes bounce { 37 + 0% { left: -40%; } 38 + 100% { left: 100%; } 39 + } 40 + .bar.done { display: none; } 41 + .error { color: #c04; } 42 + #link { display: none; font-size: 0.9rem; margin-top: 0.2rem; } 43 + #link a { color: #666; text-decoration: none; } 44 + #link a:hover { color: #aaa; } 45 + </style> 46 + </head> 47 + <body> 48 + <p id="msg">picking a random site for you (^w^)</p> 49 + <p id="link"><a id="url" href="#"></a></p> 50 + <div class="bar" id="bar"></div> 51 + <script> 52 + fetch("__API_URL__") 53 + .then(r => { 54 + if (r.status === 503) throw new Error("no sites discovered yet, try again later (_ _*)Zzz"); 55 + if (!r.ok) throw new Error(`server error (T_T): ${r.status}`); 56 + return r.json(); 57 + }) 58 + .then(({ domainUrl, fallbackUrl }) => { 59 + const href = domainUrl ?? fallbackUrl; 60 + const a = document.getElementById("url"); 61 + a.href = href; 62 + a.textContent = href; 63 + const p = document.getElementById("msg"); 64 + p.textContent = "found website!! \\(^.^)/"; 65 + document.getElementById("link").style.display = "block"; 66 + document.getElementById("bar").classList.add("done"); 67 + window.location.href = href; 68 + }) 69 + .catch((err) => { 70 + const p = document.getElementById("msg"); 71 + p.textContent = err.message; 72 + p.className = "error"; 73 + document.title = "uh oh :c"; 74 + document.getElementById("bar").classList.add("done"); 75 + }); 76 + </script> 77 + </body> 78 + </html>