diff options
| author | Xe Iaso <me@xeiaso.net> | 2025-01-25 15:32:51 -0500 |
|---|---|---|
| committer | Xe Iaso <me@xeiaso.net> | 2025-01-25 15:32:51 -0500 |
| commit | 58811194f0bced9b578937cdeb36d00243ac7df1 (patch) | |
| tree | e8406ed18f7fa8c4a99ff4e228f76149fbafc268 | |
| parent | 84a2cb246c5c6172c2499f57a43cbc898d4e2c3f (diff) | |
| download | x-58811194f0bced9b578937cdeb36d00243ac7df1.tar.xz x-58811194f0bced9b578937cdeb36d00243ac7df1.zip | |
cmd/anubis: minify JS, add video element test
Signed-off-by: Xe Iaso <me@xeiaso.net>
| -rw-r--r-- | cmd/anubis/index.templ | 86 | ||||
| -rw-r--r-- | cmd/anubis/index_templ.go | 18 | ||||
| -rw-r--r-- | cmd/anubis/js/main.mjs | 70 | ||||
| -rw-r--r-- | cmd/anubis/js/proof-of-work.mjs (renamed from cmd/anubis/static/js/proof-of-work.mjs) | 0 | ||||
| -rw-r--r-- | cmd/anubis/js/video.mjs | 16 | ||||
| -rw-r--r-- | cmd/anubis/main.go | 12 | ||||
| -rw-r--r-- | cmd/anubis/static/js/main.mjs | 51 | ||||
| -rw-r--r-- | cmd/anubis/static/testdata/black.mp4 | bin | 0 -> 1667 bytes |
8 files changed, 145 insertions, 108 deletions
diff --git a/cmd/anubis/index.templ b/cmd/anubis/index.templ index e0530d6..189cf8b 100644 --- a/cmd/anubis/index.templ +++ b/cmd/anubis/index.templ @@ -1,19 +1,18 @@ package main import ( - "within.website/x" - "within.website/x/xess" + "within.website/x" + "within.website/x/xess" ) templ base(title string, body templ.Component) { - <!DOCTYPE html> - <html> - - <head> - <title>{ title }</title> - <link rel="stylesheet" href={ xess.URL } /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <style> + <!DOCTYPE html> + <html> + <head> + <title>{ title }</title> + <link rel="stylesheet" href={ xess.URL }/> + <meta name="viewport" content="width=device-width, initial-scale=1.0"/> + <style> body, html { height: 100%; @@ -119,43 +118,42 @@ templ base(title string, body templ.Component) { } } </style> - </head> - - <body id="top"> - <main> - <center> - <h1 id="title" class=".centered-div">{ title }</h1> - </center> - @body - <footer> - <center> - <p>Protected by <a href="https://xeiaso.net/blog/2025/anubis">Anubis</a> from <a href="https://within.website">Within</a>.</p> - </center> - </footer> - </main> - </body> - - </html> + </head> + <body id="top"> + <main> + <center> + <h1 id="title" class=".centered-div">{ title }</h1> + </center> + @body + <footer> + <center> + <p>Protected by <a href="https://xeiaso.net/blog/2025/anubis">Anubis</a> from <a href="https://within.website">Within</a>.</p> + </center> + </footer> + </main> + </body> + </html> } templ index() { - <div class="centered-div"> - <img id="image" width="256" src={"/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + x.Version} /> - <img style="display:none;" width="256" src={"/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + x.Version} /> - <p id="status">Loading...</p> - <script async type="module" src={"/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + x.Version}></script> - <div id="spinner" class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div> - <noscript> - <p>Sadly, you must enable JavaScript to get past this challenge. I would love to not have to do this, but god is dead and AI scrapers have destroyed the common good.</p> - </noscript> - </div> + <div class="centered-div"> + <img id="image" width="256" src={ "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + x.Version }/> + <img style="display:none;" width="256" src={ "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + x.Version }/> + <p id="status">Loading...</p> + <script async type="module" src={ "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + x.Version }></script> + <div id="spinner" class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div> + <noscript> + <p>Sadly, you must enable JavaScript to get past this challenge. I would love to not have to do this, but god is dead and AI scrapers have destroyed the common good.</p> + </noscript> + <div id="testarea"></div> + </div> } templ errorPage(message string) { - <div class="centered-div"> - <img id="image" width="256" src={"/.within.website/x/cmd/anubis/static/img/sad.webp?cacheBuster=" + x.Version} /> - <p>{ message }.</p> - <button onClick="window.location.reload();">Try again</button> - <p><a href="/">Go home</a></p> - </div> -}
\ No newline at end of file + <div class="centered-div"> + <img id="image" width="256" src={ "/.within.website/x/cmd/anubis/static/img/sad.webp?cacheBuster=" + x.Version }/> + <p>{ message }.</p> + <button onClick="window.location.reload();">Try again</button> + <p><a href="/">Go home</a></p> + </div> +} diff --git a/cmd/anubis/index_templ.go b/cmd/anubis/index_templ.go index ee06a60..50d65ef 100644 --- a/cmd/anubis/index_templ.go +++ b/cmd/anubis/index_templ.go @@ -41,7 +41,7 @@ func base(title string, body templ.Component) templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 13, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 12, Col: 17} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { @@ -54,7 +54,7 @@ func base(title string, body templ.Component) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(xess.URL) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 14, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 13, Col: 41} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -67,7 +67,7 @@ func base(title string, body templ.Component) templ.Component { var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 127, Col: 52} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 125, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { @@ -117,7 +117,7 @@ func index() templ.Component { var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + x.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 143, Col: 117} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 140, Col: 116} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { @@ -130,7 +130,7 @@ func index() templ.Component { var templ_7745c5c3_Var7 string templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + x.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 144, Col: 126} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 141, Col: 125} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { @@ -143,13 +143,13 @@ func index() templ.Component { var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + x.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 146, Col: 112} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 143, Col: 111} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"></script><div id=\"spinner\" class=\"lds-roller\"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div><noscript><p>Sadly, you must enable JavaScript to get past this challenge. I would love to not have to do this, but god is dead and AI scrapers have destroyed the common good.</p></noscript></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"></script><div id=\"spinner\" class=\"lds-roller\"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div><noscript><p>Sadly, you must enable JavaScript to get past this challenge. I would love to not have to do this, but god is dead and AI scrapers have destroyed the common good.</p></noscript><div id=\"testarea\"></div></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -185,7 +185,7 @@ func errorPage(message string) templ.Component { var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/sad.webp?cacheBuster=" + x.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 156, Col: 113} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 154, Col: 112} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { @@ -198,7 +198,7 @@ func errorPage(message string) templ.Component { var templ_7745c5c3_Var11 string templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(message) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 157, Col: 16} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 155, Col: 14} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { diff --git a/cmd/anubis/js/main.mjs b/cmd/anubis/js/main.mjs new file mode 100644 index 0000000..38002d9 --- /dev/null +++ b/cmd/anubis/js/main.mjs @@ -0,0 +1,70 @@ +import { process } from './proof-of-work.mjs'; +import { testVideo } from './video.mjs'; + +// from Xeact +const u = (url = "", params = {}) => { + let result = new URL(url, window.location.href); + Object.entries(params).forEach((kv) => { + let [k, v] = kv; + result.searchParams.set(k, v); + }); + return result.toString(); +}; + +const imageURL = (mood) => { + return `/.within.website/x/cmd/anubis/static/img/${mood}.webp`; +}; + +(async () => { + const status = document.getElementById('status'); + const image = document.getElementById('image'); + const title = document.getElementById('title'); + const spinner = document.getElementById('spinner'); + const testarea = document.getElementById('testarea'); + + const videoWorks = await testVideo(testarea); + + if (!videoWorks) { + title.innerHTML = "Oh no!"; + status.innerHTML = "Checks failed. Please check your browser's settings and try again."; + image.src = imageURL("sad"); + spinner.innerHTML = ""; + spinner.style.display = "none"; + return; + } + + status.innerHTML = 'Calculating...'; + + const { challenge, difficulty } = await fetch("/.within.website/x/cmd/anubis/api/make-challenge", { method: "POST" }) + .then(r => { + if (!r.ok) { + throw new Error("Failed to fetch config"); + } + return r.json(); + }) + .catch(err => { + title.innerHTML = "Oh no!"; + status.innerHTML = `Failed to fetch config: ${err.message}`; + image.src = imageURL("sad"); + spinner.innerHTML = ""; + spinner.style.display = "none"; + throw err; + }); + + status.innerHTML = `Calculating...<br/>Difficulty: ${difficulty}`; + + const t0 = Date.now(); + const { hash, nonce } = await process(challenge, difficulty); + const t1 = Date.now(); + + title.innerHTML = "Success!"; + status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`; + image.src = imageURL("happy"); + spinner.innerHTML = ""; + spinner.style.display = "none"; + + setTimeout(() => { + const redir = window.location.href; + window.location.href = u("/.within.website/x/cmd/anubis/api/pass-challenge", { response: hash, nonce, redir, elapsedTime: t1 - t0, difficulty }); + }, 2000); +})();
\ No newline at end of file diff --git a/cmd/anubis/static/js/proof-of-work.mjs b/cmd/anubis/js/proof-of-work.mjs index d71d2db..d71d2db 100644 --- a/cmd/anubis/static/js/proof-of-work.mjs +++ b/cmd/anubis/js/proof-of-work.mjs diff --git a/cmd/anubis/js/video.mjs b/cmd/anubis/js/video.mjs new file mode 100644 index 0000000..59cde1e --- /dev/null +++ b/cmd/anubis/js/video.mjs @@ -0,0 +1,16 @@ +const videoElement = `<video id="videotest" width="0" height="0" src="/.within.website/x/cmd/anubis/static/testdata/black.mp4"></video>`; + +export const testVideo = async (testarea) => { + testarea.innerHTML = videoElement; + return (await new Promise((resolve) => { + const video = document.getElementById('videotest'); + video.oncanplay = () => { + testarea.style.display = "none"; + resolve(true); + }; + video.onerror = (ev) => { + testarea.style.display = "none"; + resolve(false); + }; + })); +};
\ No newline at end of file diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go index 43d9ab0..6217b48 100644 --- a/cmd/anubis/main.go +++ b/cmd/anubis/main.go @@ -73,6 +73,7 @@ const ( ) //go:generate go run github.com/a-h/templ/cmd/templ@latest generate +//go:generate esbuild js/main.mjs --minify --bundle --outfile=static/js/main.mjs func main() { internal.HandleStartup() @@ -445,7 +446,7 @@ func (s *Server) passChallenge(w http.ResponseWriter, r *http.Request) { Name: cookieName, Value: tokenString, Expires: time.Now().Add(24 * 7 * time.Hour), - SameSite: http.SameSiteDefaultMode, + SameSite: http.SameSiteLaxMode, Path: "/", }) @@ -461,10 +462,11 @@ func (s *Server) testError(w http.ResponseWriter, r *http.Request) { func clearCookie(w http.ResponseWriter) { http.SetCookie(w, &http.Cookie{ - Name: cookieName, - Value: "", - Expires: time.Now().Add(-1 * time.Hour), - MaxAge: -1, + Name: cookieName, + Value: "", + Expires: time.Now().Add(-1 * time.Hour), + MaxAge: -1, + SameSite: http.SameSiteLaxMode, }) } diff --git a/cmd/anubis/static/js/main.mjs b/cmd/anubis/static/js/main.mjs index f111bb4..4d8c60c 100644 --- a/cmd/anubis/static/js/main.mjs +++ b/cmd/anubis/static/js/main.mjs @@ -1,50 +1 @@ -import { process } from './proof-of-work.mjs'; - -// from Xeact -const u = (url = "", params = {}) => { - let result = new URL(url, window.location.href); - Object.entries(params).forEach((kv) => { - let [k, v] = kv; - result.searchParams.set(k, v); - }); - return result.toString(); -}; - -(async () => { - const status = document.getElementById('status'); - const image = document.getElementById('image'); - const title = document.getElementById('title'); - const spinner = document.getElementById('spinner'); - - status.innerHTML = 'Calculating...'; - - const { challenge, difficulty } = await fetch("/.within.website/x/cmd/anubis/api/make-challenge", { method: "POST" }) - .then(r => { - if (!r.ok) { - throw new Error("Failed to fetch config"); - } - return r.json(); - }) - .catch(err => { - status.innerHTML = `Failed to fetch config: ${err.message}`; - image.src = "/.within.website/x/cmd/anubis/static/img/sad.webp"; - throw err; - }); - - status.innerHTML = `Calculating...<br/>Difficulty: ${difficulty}`; - - const t0 = Date.now(); - const { hash, nonce } = await process(challenge, difficulty); - const t1 = Date.now(); - - title.innerHTML = "Success!"; - status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`; - image.src = "/.within.website/x/cmd/anubis/static/img/happy.webp"; - spinner.innerHTML = ""; - spinner.style.display = "none"; - - setTimeout(() => { - const redir = window.location.href; - window.location.href = u("/.within.website/x/cmd/anubis/api/pass-challenge", { response: hash, nonce, redir, elapsedTime: t1 - t0, difficulty }); - }, 2000); -})();
\ No newline at end of file +(()=>{function w(e,i=5){return new Promise((n,t)=>{let o=URL.createObjectURL(new Blob(["(",y(),")()"],{type:"application/javascript"})),s=new Worker(o);s.onmessage=r=>{s.terminate(),n(r.data)},s.onerror=r=>{s.terminate(),t()},s.postMessage({data:e,difficulty:i}),URL.revokeObjectURL(o)})}function y(){return function(){let e=i=>{let n=new TextEncoder().encode(i);return crypto.subtle.digest("SHA-256",n.buffer).then(t=>Array.from(new Uint8Array(t)).map(o=>o.toString(16).padStart(2,"0")).join(""))};addEventListener("message",async i=>{let n=i.data.data,t=i.data.difficulty,o,s=0;do o=await e(n+s++);while(o.substring(0,t)!==Array(t+1).join("0"));s-=1,postMessage({hash:o,data:n,difficulty:t,nonce:s})})}.toString()}var g='<video id="videotest" width="0" height="0" src="/.within.website/x/cmd/anubis/static/testdata/black.mp4"></video>',h=async e=>(e.innerHTML=g,await new Promise(i=>{let n=document.getElementById("videotest");n.oncanplay=()=>{e.style.display="none",i(!0)},n.onerror=t=>{e.style.display="none",i(!1)}}));var f=(e="",i={})=>{let n=new URL(e,window.location.href);return Object.entries(i).forEach(t=>{let[o,s]=t;n.searchParams.set(o,s)}),n.toString()},d=e=>`/.within.website/x/cmd/anubis/static/img/${e}.webp`;(async()=>{let e=document.getElementById("status"),i=document.getElementById("image"),n=document.getElementById("title"),t=document.getElementById("spinner"),o=document.getElementById("testarea");if(!await h(o)){n.innerHTML="Oh no!",e.innerHTML="Checks failed. Please check your browser's settings and try again.",i.src=d("sad"),t.innerHTML="",t.style.display="none";return}e.innerHTML="Calculating...";let{challenge:r,difficulty:c}=await fetch("/.within.website/x/cmd/anubis/api/make-challenge",{method:"POST"}).then(a=>{if(!a.ok)throw new Error("Failed to fetch config");return a.json()}).catch(a=>{throw n.innerHTML="Oh no!",e.innerHTML=`Failed to fetch config: ${a.message}`,i.src=d("sad"),t.innerHTML="",t.style.display="none",a});e.innerHTML=`Calculating...<br/>Difficulty: ${c}`;let l=Date.now(),{hash:p,nonce:m}=await w(r,c),u=Date.now();n.innerHTML="Success!",e.innerHTML=`Done! Took ${u-l}ms, ${m} iterations`,i.src=d("happy"),t.innerHTML="",t.style.display="none",setTimeout(()=>{let a=window.location.href;window.location.href=f("/.within.website/x/cmd/anubis/api/pass-challenge",{response:p,nonce:m,redir:a,elapsedTime:u-l,difficulty:c})},2e3)})();})(); diff --git a/cmd/anubis/static/testdata/black.mp4 b/cmd/anubis/static/testdata/black.mp4 Binary files differnew file mode 100644 index 0000000..83a9989 --- /dev/null +++ b/cmd/anubis/static/testdata/black.mp4 |
