diff options
Diffstat (limited to 'cmd')
| -rw-r--r-- | cmd/anubis/index.templ | 135 | ||||
| -rw-r--r-- | cmd/anubis/index_templ.go | 44 | ||||
| -rw-r--r-- | cmd/anubis/js/main.mjs | 12 | ||||
| -rw-r--r-- | cmd/anubis/js/proof-of-work.mjs | 78 | ||||
| -rw-r--r-- | cmd/anubis/main.go | 2 | ||||
| -rw-r--r-- | cmd/anubis/static/js/main.mjs | 2 | ||||
| -rw-r--r-- | cmd/anubis/static/js/main.mjs.br | bin | 802 -> 993 bytes | |||
| -rw-r--r-- | cmd/anubis/static/js/main.mjs.gz | bin | 985 -> 1193 bytes | |||
| -rw-r--r-- | cmd/anubis/static/js/main.mjs.map | 6 | ||||
| -rw-r--r-- | cmd/anubis/static/js/main.mjs.zst | bin | 982 -> 1191 bytes |
10 files changed, 166 insertions, 113 deletions
diff --git a/cmd/anubis/index.templ b/cmd/anubis/index.templ index 028e89e..a2270fa 100644 --- a/cmd/anubis/index.templ +++ b/cmd/anubis/index.templ @@ -1,19 +1,18 @@ package main import ( -"github.com/TecharoHQ/anubis" -"github.com/TecharoHQ/anubis/xess" + "github.com/TecharoHQ/anubis" + "github.com/TecharoHQ/anubis/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%; @@ -139,60 +138,74 @@ templ base(title string, body templ.Component) { transform: rotate(360deg); } } - </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://github.com/TecharoHQ/anubis">Anubis</a> from <a - href="https://techaro.lol">Techaro</a>.</p> - </center> - </footer> - </main> -</body> - -</html> + </style> + @templ.JSONScript("anubis_version", anubis.Version) + </head> + <body id="top"> + <main> + <center> + <h1 id="title" class=".centered-div">{ title }</h1> + </center> + @body + <footer> + <center> + <p> + Protected by <a href="https://github.com/TecharoHQ/anubis">Anubis</a> from <a + href="https://techaro.lol" +>Techaro</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=" + - anubis.Version } /> - <img style="display:none;" width="256" src={ "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + - anubis.Version } /> - <p id="status">Loading...</p> - <script async type="module" src={ "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.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. This is required because AI companies have changed - the social contract around how website hosting works. A no-JS solution is a work-in-progress.</p> - </noscript> - <div id="testarea"></div> -</div> + <div class="centered-div"> + <img + id="image" + width="256" + src={ "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + + anubis.Version } + /> + <img + style="display:none;" + width="256" + src={ "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + + anubis.Version } + /> + <p id="status">Loading...</p> + <script async type="module" src={ "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.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. This is required because AI companies have changed + the social contract around how website hosting works. A no-JS solution is a work-in-progress. + </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=" + anubis.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=" + anubis.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 70bd028..9bfa351 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: 16} + 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,26 +54,34 @@ 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: 40} + 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 { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>\n body,\n html {\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 65ch;\n margin-left: auto;\n margin-right: auto;\n }\n\n .centered-div {\n text-align: center;\n }\n\n .lds-roller,\n .lds-roller div,\n .lds-roller div:after {\n box-sizing: border-box;\n }\n\n .lds-roller {\n display: inline-block;\n position: relative;\n width: 80px;\n height: 80px;\n }\n\n .lds-roller div {\n animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n transform-origin: 40px 40px;\n }\n\n .lds-roller div:after {\n content: \" \";\n display: block;\n position: absolute;\n width: 7.2px;\n height: 7.2px;\n border-radius: 50%;\n background: currentColor;\n margin: -3.6px 0 0 -3.6px;\n }\n\n .lds-roller div:nth-child(1) {\n animation-delay: -0.036s;\n }\n\n .lds-roller div:nth-child(1):after {\n top: 62.62742px;\n left: 62.62742px;\n }\n\n .lds-roller div:nth-child(2) {\n animation-delay: -0.072s;\n }\n\n .lds-roller div:nth-child(2):after {\n top: 67.71281px;\n left: 56px;\n }\n\n .lds-roller div:nth-child(3) {\n animation-delay: -0.108s;\n }\n\n .lds-roller div:nth-child(3):after {\n top: 70.90963px;\n left: 48.28221px;\n }\n\n .lds-roller div:nth-child(4) {\n animation-delay: -0.144s;\n }\n\n .lds-roller div:nth-child(4):after {\n top: 72px;\n left: 40px;\n }\n\n .lds-roller div:nth-child(5) {\n animation-delay: -0.18s;\n }\n\n .lds-roller div:nth-child(5):after {\n top: 70.90963px;\n left: 31.71779px;\n }\n\n .lds-roller div:nth-child(6) {\n animation-delay: -0.216s;\n }\n\n .lds-roller div:nth-child(6):after {\n top: 67.71281px;\n left: 24px;\n }\n\n .lds-roller div:nth-child(7) {\n animation-delay: -0.252s;\n }\n\n .lds-roller div:nth-child(7):after {\n top: 62.62742px;\n left: 17.37258px;\n }\n\n .lds-roller div:nth-child(8) {\n animation-delay: -0.288s;\n }\n\n .lds-roller div:nth-child(8):after {\n top: 56px;\n left: 12.28719px;\n }\n\n @keyframes lds-roller {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n }\n </style></head><body id=\"top\"><main><center><h1 id=\"title\" class=\".centered-div\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>\n body,\n html {\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n width: 65ch;\n margin-left: auto;\n margin-right: auto;\n }\n\n .centered-div {\n text-align: center;\n }\n\n .lds-roller,\n .lds-roller div,\n .lds-roller div:after {\n box-sizing: border-box;\n }\n\n .lds-roller {\n display: inline-block;\n position: relative;\n width: 80px;\n height: 80px;\n }\n\n .lds-roller div {\n animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n transform-origin: 40px 40px;\n }\n\n .lds-roller div:after {\n content: \" \";\n display: block;\n position: absolute;\n width: 7.2px;\n height: 7.2px;\n border-radius: 50%;\n background: currentColor;\n margin: -3.6px 0 0 -3.6px;\n }\n\n .lds-roller div:nth-child(1) {\n animation-delay: -0.036s;\n }\n\n .lds-roller div:nth-child(1):after {\n top: 62.62742px;\n left: 62.62742px;\n }\n\n .lds-roller div:nth-child(2) {\n animation-delay: -0.072s;\n }\n\n .lds-roller div:nth-child(2):after {\n top: 67.71281px;\n left: 56px;\n }\n\n .lds-roller div:nth-child(3) {\n animation-delay: -0.108s;\n }\n\n .lds-roller div:nth-child(3):after {\n top: 70.90963px;\n left: 48.28221px;\n }\n\n .lds-roller div:nth-child(4) {\n animation-delay: -0.144s;\n }\n\n .lds-roller div:nth-child(4):after {\n top: 72px;\n left: 40px;\n }\n\n .lds-roller div:nth-child(5) {\n animation-delay: -0.18s;\n }\n\n .lds-roller div:nth-child(5):after {\n top: 70.90963px;\n left: 31.71779px;\n }\n\n .lds-roller div:nth-child(6) {\n animation-delay: -0.216s;\n }\n\n .lds-roller div:nth-child(6):after {\n top: 67.71281px;\n left: 24px;\n }\n\n .lds-roller div:nth-child(7) {\n animation-delay: -0.252s;\n }\n\n .lds-roller div:nth-child(7):after {\n top: 62.62742px;\n left: 17.37258px;\n }\n\n .lds-roller div:nth-child(8) {\n animation-delay: -0.288s;\n }\n\n .lds-roller div:nth-child(8):after {\n top: 56px;\n left: 12.28719px;\n }\n\n @keyframes lds-roller {\n 0% {\n transform: rotate(0deg);\n }\n\n 100% {\n transform: rotate(360deg);\n }\n }\n </style>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templ.JSONScript("anubis_version", anubis.Version).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</head><body id=\"top\"><main><center><h1 id=\"title\" class=\".centered-div\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } 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: 148, Col: 50} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 147, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</h1></center>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</h1></center>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -81,7 +89,7 @@ func base(title string, body templ.Component) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<footer><center><p>Protected by <a href=\"https://github.com/TecharoHQ/anubis\">Anubis</a> from <a href=\"https://techaro.lol\">Techaro</a>.</p></center></footer></main></body></html>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<footer><center><p>Protected by <a href=\"https://github.com/TecharoHQ/anubis\">Anubis</a> from <a href=\"https://techaro.lol\">Techaro</a>.</p></center></footer></main></body></html>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -110,7 +118,7 @@ func index() templ.Component { templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"centered-div\"><img id=\"image\" width=\"256\" src=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<div class=\"centered-div\"><img id=\"image\" width=\"256\" src=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -118,13 +126,13 @@ func index() templ.Component { templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 166, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 170, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\"> <img style=\"display:none;\" width=\"256\" src=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\"> <img style=\"display:none;\" width=\"256\" src=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -132,26 +140,26 @@ func index() templ.Component { templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + anubis.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 168, Col: 18} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 176, Col: 18} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\"><p id=\"status\">Loading...</p><script async type=\"module\" src=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\"><p id=\"status\">Loading...</p><script async type=\"module\" src=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var8 string templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 170, Col: 116} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 179, Col: 116} } _, 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. This is required because AI companies have changed the social contract around how website hosting works. A no-JS solution is a work-in-progress.</p></noscript><div id=\"testarea\"></div></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "\"></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. This is required because AI companies have changed the social contract around how website hosting works. A no-JS solution is a work-in-progress.</p></noscript><div id=\"testarea\"></div></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -180,33 +188,33 @@ func errorPage(message string) templ.Component { templ_7745c5c3_Var9 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div class=\"centered-div\"><img id=\"image\" width=\"256\" src=\"") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "<div class=\"centered-div\"><img id=\"image\" width=\"256\" src=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var10 string templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/sad.webp?cacheBuster=" + anubis.Version) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 192, Col: 117} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 205, Col: 90} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\"><p>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\"><p>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } 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: 194, Col: 14} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 207, Col: 14} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, ".</p><button onClick=\"window.location.reload();\">Try again</button><p><a href=\"/\">Go home</a></p></div>") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, ".</p><button onClick=\"window.location.reload();\">Try again</button><p><a href=\"/\">Go home</a></p></div>") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/cmd/anubis/js/main.mjs b/cmd/anubis/js/main.mjs index 3f2c652..fc85a44 100644 --- a/cmd/anubis/js/main.mjs +++ b/cmd/anubis/js/main.mjs @@ -11,15 +11,16 @@ const u = (url = "", params = {}) => { return result.toString(); }; -const imageURL = (mood) => { - return `/.within.website/x/cmd/anubis/static/img/${mood}.webp`; -}; +const imageURL = (mood, cacheBuster) => + u(`/.within.website/x/cmd/anubis/static/img/${mood}.webp`, { cacheBuster }); (async () => { const status = document.getElementById('status'); const image = document.getElementById('image'); const title = document.getElementById('title'); const spinner = document.getElementById('spinner'); + const anubisVersion = JSON.parse(document.getElementById('anubis_version').textContent); + // const testarea = document.getElementById('testarea'); // const videoWorks = await testVideo(testarea); @@ -57,15 +58,16 @@ const imageURL = (mood) => { const t0 = Date.now(); const { hash, nonce } = await process(challenge, difficulty); const t1 = Date.now(); + console.log({ hash, nonce }); title.innerHTML = "Success!"; status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`; - image.src = imageURL("happy"); + image.src = imageURL("happy", anubisVersion); 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 }); - }, 2000); + }, 250); })();
\ No newline at end of file diff --git a/cmd/anubis/js/proof-of-work.mjs b/cmd/anubis/js/proof-of-work.mjs index d71d2db..bd69c71 100644 --- a/cmd/anubis/js/proof-of-work.mjs +++ b/cmd/anubis/js/proof-of-work.mjs @@ -1,27 +1,35 @@ // https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm -export function process(data, difficulty = 5) { +export function process(data, difficulty = 5, threads = navigator.hardwareConcurrency) { return new Promise((resolve, reject) => { let webWorkerURL = URL.createObjectURL(new Blob([ '(', processTask(), ')()' ], { type: 'application/javascript' })); - let worker = new Worker(webWorkerURL); + const workers = []; - worker.onmessage = (event) => { - worker.terminate(); - resolve(event.data); - }; + for (let i = 0; i < threads; i++) { + let worker = new Worker(webWorkerURL); - worker.onerror = (event) => { - worker.terminate(); - reject(); - }; + worker.onmessage = (event) => { + workers.forEach(worker => worker.terminate()); + worker.terminate(); + resolve(event.data); + }; - worker.postMessage({ - data, - difficulty - }); + worker.onerror = (event) => { + worker.terminate(); + reject(); + }; + + worker.postMessage({ + data, + difficulty, + nonce: 1000000 * i, + }); + + workers.push(worker); + } URL.revokeObjectURL(webWorkerURL); }); @@ -31,22 +39,44 @@ function processTask() { return function () { const sha256 = (text) => { const encoded = new TextEncoder().encode(text); - return crypto.subtle.digest("SHA-256", encoded.buffer).then((result) => - Array.from(new Uint8Array(result)) - .map((c) => c.toString(16).padStart(2, "0")) - .join(""), - ); + return crypto.subtle.digest("SHA-256", encoded.buffer); }; + function uint8ArrayToHexString(arr) { + return Array.from(arr) + .map((c) => c.toString(16).padStart(2, "0")) + .join(""); + } + addEventListener('message', async (event) => { let data = event.data.data; let difficulty = event.data.difficulty; - let hash; - let nonce = 0; - do { - hash = await sha256(data + nonce++); - } while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0')); + let nonce = event.data.nonce || 0; + + while (true) { + const currentHash = await sha256(data + nonce++); + const thisHash = new Uint8Array(currentHash); + let valid = true; + + for (let j = 0; j < difficulty; j++) { + const byteIndex = Math.floor(j / 2); // which byte we are looking at + const nibbleIndex = j % 2; // which nibble in the byte we are looking at (0 is high, 1 is low) + + let nibble = (thisHash[byteIndex] >> (nibbleIndex === 0 ? 4 : 0)) & 0x0F; // Get the nibble + + if (nibble !== 0) { + valid = false; + break; + } + } + + if (valid) { + hash = uint8ArrayToHexString(thisHash); + console.log(hash); + break; + } + } nonce -= 1; // last nonce was post-incremented diff --git a/cmd/anubis/main.go b/cmd/anubis/main.go index 45afeb2..c71d368 100644 --- a/cmd/anubis/main.go +++ b/cmd/anubis/main.go @@ -82,7 +82,7 @@ const ( ) //go:generate go tool github.com/a-h/templ/cmd/templ generate -//go:generate esbuild js/main.mjs --sourcemap --minify --bundle --outfile=static/js/main.mjs +//go:generate esbuild js/main.mjs --sourcemap --bundle --minify --outfile=static/js/main.mjs //go:generate gzip -f -k static/js/main.mjs //go:generate zstd -f -k --ultra -22 static/js/main.mjs //go:generate brotli -fZk static/js/main.mjs diff --git a/cmd/anubis/static/js/main.mjs b/cmd/anubis/static/js/main.mjs index 043f617..3d9e2d0 100644 --- a/cmd/anubis/static/js/main.mjs +++ b/cmd/anubis/static/js/main.mjs @@ -1,2 +1,2 @@ -(()=>{function l(n,s=5){return new Promise((i,e)=>{let o=URL.createObjectURL(new Blob(["(",w(),")()"],{type:"application/javascript"})),t=new Worker(o);t.onmessage=r=>{t.terminate(),i(r.data)},t.onerror=r=>{t.terminate(),e()},t.postMessage({data:n,difficulty:s}),URL.revokeObjectURL(o)})}function w(){return function(){let n=s=>{let i=new TextEncoder().encode(s);return crypto.subtle.digest("SHA-256",i.buffer).then(e=>Array.from(new Uint8Array(e)).map(o=>o.toString(16).padStart(2,"0")).join(""))};addEventListener("message",async s=>{let i=s.data.data,e=s.data.difficulty,o,t=0;do o=await n(i+t++);while(o.substring(0,e)!==Array(e+1).join("0"));t-=1,postMessage({hash:o,data:i,difficulty:e,nonce:t})})}.toString()}var h=(n="",s={})=>{let i=new URL(n,window.location.href);return Object.entries(s).forEach(e=>{let[o,t]=e;i.searchParams.set(o,t)}),i.toString()},m=n=>`/.within.website/x/cmd/anubis/static/img/${n}.webp`;(async()=>{let n=document.getElementById("status"),s=document.getElementById("image"),i=document.getElementById("title"),e=document.getElementById("spinner");n.innerHTML="Calculating...";let{challenge:o,difficulty:t}=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 i.innerHTML="Oh no!",n.innerHTML=`Failed to fetch config: ${a.message}`,s.src=m("sad"),e.innerHTML="",e.style.display="none",a});n.innerHTML=`Calculating...<br/>Difficulty: ${t}`;let r=Date.now(),{hash:u,nonce:c}=await l(o,t),d=Date.now();i.innerHTML="Success!",n.innerHTML=`Done! Took ${d-r}ms, ${c} iterations`,s.src=m("happy"),e.innerHTML="",e.style.display="none",setTimeout(()=>{let a=window.location.href;window.location.href=h("/.within.website/x/cmd/anubis/api/pass-challenge",{response:u,nonce:c,redir:a,elapsedTime:d-r})},2e3)})();})(); +(()=>{function m(n,i=5,e=navigator.hardwareConcurrency){return new Promise((t,d)=>{let s=URL.createObjectURL(new Blob(["(",p(),")()"],{type:"application/javascript"})),a=[];for(let u=0;u<e;u++){let o=new Worker(s);o.onmessage=r=>{a.forEach(c=>c.terminate()),o.terminate(),t(r.data)},o.onerror=r=>{o.terminate(),d()},o.postMessage({data:n,difficulty:i,nonce:1e6*u}),a.push(o)}URL.revokeObjectURL(s)})}function p(){return function(){let n=e=>{let t=new TextEncoder().encode(e);return crypto.subtle.digest("SHA-256",t.buffer)};function i(e){return Array.from(e).map(t=>t.toString(16).padStart(2,"0")).join("")}addEventListener("message",async e=>{let t=e.data.data,d=e.data.difficulty,s,a=e.data.nonce||0;for(;;){let u=await n(t+a++),o=new Uint8Array(u),r=!0;for(let c=0;c<d;c++){let l=Math.floor(c/2),f=c%2;if((o[l]>>(f===0?4:0)&15)!==0){r=!1;break}}if(r){s=i(o),console.log(s);break}}a-=1,postMessage({hash:s,data:t,difficulty:d,nonce:a})})}.toString()}var w=(n="",i={})=>{let e=new URL(n,window.location.href);return Object.entries(i).forEach(t=>{let[d,s]=t;e.searchParams.set(d,s)}),e.toString()},h=(n,i)=>w(`/.within.website/x/cmd/anubis/static/img/${n}.webp`,{cacheBuster:i});(async()=>{let n=document.getElementById("status"),i=document.getElementById("image"),e=document.getElementById("title"),t=document.getElementById("spinner"),d=JSON.parse(document.getElementById("anubis_version").textContent);n.innerHTML="Calculating...";let{challenge:s,difficulty:a}=await fetch("/.within.website/x/cmd/anubis/api/make-challenge",{method:"POST"}).then(l=>{if(!l.ok)throw new Error("Failed to fetch config");return l.json()}).catch(l=>{throw e.innerHTML="Oh no!",n.innerHTML=`Failed to fetch config: ${l.message}`,i.src=h("sad"),t.innerHTML="",t.style.display="none",l});n.innerHTML=`Calculating...<br/>Difficulty: ${a}`;let u=Date.now(),{hash:o,nonce:r}=await m(s,a),c=Date.now();console.log({hash:o,nonce:r}),e.innerHTML="Success!",n.innerHTML=`Done! Took ${c-u}ms, ${r} iterations`,i.src=h("happy",d),t.innerHTML="",t.style.display="none",setTimeout(()=>{let l=window.location.href;window.location.href=w("/.within.website/x/cmd/anubis/api/pass-challenge",{response:o,nonce:r,redir:l,elapsedTime:c-u})},250)})();})(); //# sourceMappingURL=main.mjs.map diff --git a/cmd/anubis/static/js/main.mjs.br b/cmd/anubis/static/js/main.mjs.br Binary files differindex 27625da..56b6646 100644 --- a/cmd/anubis/static/js/main.mjs.br +++ b/cmd/anubis/static/js/main.mjs.br diff --git a/cmd/anubis/static/js/main.mjs.gz b/cmd/anubis/static/js/main.mjs.gz Binary files differindex c80b596..f4665ee 100644 --- a/cmd/anubis/static/js/main.mjs.gz +++ b/cmd/anubis/static/js/main.mjs.gz diff --git a/cmd/anubis/static/js/main.mjs.map b/cmd/anubis/static/js/main.mjs.map index d5b288f..577503b 100644 --- a/cmd/anubis/static/js/main.mjs.map +++ b/cmd/anubis/static/js/main.mjs.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../js/proof-of-work.mjs", "../../js/main.mjs"], - "sourcesContent": ["// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm\n\nexport function process(data, difficulty = 5) {\n return new Promise((resolve, reject) => {\n let webWorkerURL = URL.createObjectURL(new Blob([\n '(', processTask(), ')()'\n ], { type: 'application/javascript' }));\n\n let worker = new Worker(webWorkerURL);\n\n worker.onmessage = (event) => {\n worker.terminate();\n resolve(event.data);\n };\n\n worker.onerror = (event) => {\n worker.terminate();\n reject();\n };\n\n worker.postMessage({\n data,\n difficulty\n });\n\n URL.revokeObjectURL(webWorkerURL);\n });\n}\n\nfunction processTask() {\n return function () {\n const sha256 = (text) => {\n const encoded = new TextEncoder().encode(text);\n return crypto.subtle.digest(\"SHA-256\", encoded.buffer).then((result) =>\n Array.from(new Uint8Array(result))\n .map((c) => c.toString(16).padStart(2, \"0\"))\n .join(\"\"),\n );\n };\n\n addEventListener('message', async (event) => {\n let data = event.data.data;\n let difficulty = event.data.difficulty;\n\n let hash;\n let nonce = 0;\n do {\n hash = await sha256(data + nonce++);\n } while (hash.substring(0, difficulty) !== Array(difficulty + 1).join('0'));\n\n nonce -= 1; // last nonce was post-incremented\n\n postMessage({\n hash,\n data,\n difficulty,\n nonce,\n });\n });\n }.toString();\n}\n\n", "import { process } from './proof-of-work.mjs';\nimport { testVideo } from './video.mjs';\n\n// from Xeact\nconst u = (url = \"\", params = {}) => {\n let result = new URL(url, window.location.href);\n Object.entries(params).forEach((kv) => {\n let [k, v] = kv;\n result.searchParams.set(k, v);\n });\n return result.toString();\n};\n\nconst imageURL = (mood) => {\n return `/.within.website/x/cmd/anubis/static/img/${mood}.webp`;\n};\n\n(async () => {\n const status = document.getElementById('status');\n const image = document.getElementById('image');\n const title = document.getElementById('title');\n const spinner = document.getElementById('spinner');\n // const testarea = document.getElementById('testarea');\n\n // const videoWorks = await testVideo(testarea);\n // console.log(`videoWorks: ${videoWorks}`);\n\n // if (!videoWorks) {\n // title.innerHTML = \"Oh no!\";\n // status.innerHTML = \"Checks failed. Please check your browser's settings and try again.\";\n // image.src = imageURL(\"sad\");\n // spinner.innerHTML = \"\";\n // spinner.style.display = \"none\";\n // return;\n // }\n\n status.innerHTML = 'Calculating...';\n\n const { challenge, difficulty } = await fetch(\"/.within.website/x/cmd/anubis/api/make-challenge\", { method: \"POST\" })\n .then(r => {\n if (!r.ok) {\n throw new Error(\"Failed to fetch config\");\n }\n return r.json();\n })\n .catch(err => {\n title.innerHTML = \"Oh no!\";\n status.innerHTML = `Failed to fetch config: ${err.message}`;\n image.src = imageURL(\"sad\");\n spinner.innerHTML = \"\";\n spinner.style.display = \"none\";\n throw err;\n });\n\n status.innerHTML = `Calculating...<br/>Difficulty: ${difficulty}`;\n\n const t0 = Date.now();\n const { hash, nonce } = await process(challenge, difficulty);\n const t1 = Date.now();\n\n title.innerHTML = \"Success!\";\n status.innerHTML = `Done! Took ${t1 - t0}ms, ${nonce} iterations`;\n image.src = imageURL(\"happy\");\n spinner.innerHTML = \"\";\n spinner.style.display = \"none\";\n\n setTimeout(() => {\n const redir = window.location.href;\n window.location.href = u(\"/.within.website/x/cmd/anubis/api/pass-challenge\", { response: hash, nonce, redir, elapsedTime: t1 - t0 });\n }, 2000);\n})();"], - "mappings": "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", - "names": ["process", "data", "difficulty", "resolve", "reject", "webWorkerURL", "processTask", "worker", "event", "sha256", "text", "encoded", "result", "c", "hash", "nonce", "u", "url", "params", "result", "kv", "k", "v", "imageURL", "mood", "status", "image", "title", "spinner", "challenge", "difficulty", "r", "err", "t0", "hash", "nonce", "process", "t1", "redir"] + "sourcesContent": ["// https://dev.to/ratmd/simple-proof-of-work-in-javascript-3kgm\n\nexport function process(data, difficulty = 5, threads = navigator.hardwareConcurrency) {\n return new Promise((resolve, reject) => {\n let webWorkerURL = URL.createObjectURL(new Blob([\n '(', processTask(), ')()'\n ], { type: 'application/javascript' }));\n\n const workers = [];\n\n for (let i = 0; i < threads; i++) {\n let worker = new Worker(webWorkerURL);\n\n worker.onmessage = (event) => {\n workers.forEach(worker => worker.terminate());\n worker.terminate();\n resolve(event.data);\n };\n\n worker.onerror = (event) => {\n worker.terminate();\n reject();\n };\n\n worker.postMessage({\n data,\n difficulty,\n nonce: 1000000 * i,\n });\n\n workers.push(worker);\n }\n\n URL.revokeObjectURL(webWorkerURL);\n });\n}\n\nfunction processTask() {\n return function () {\n const sha256 = (text) => {\n const encoded = new TextEncoder().encode(text);\n return crypto.subtle.digest(\"SHA-256\", encoded.buffer);\n };\n\n function uint8ArrayToHexString(arr) {\n return Array.from(arr)\n .map((c) => c.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n addEventListener('message', async (event) => {\n let data = event.data.data;\n let difficulty = event.data.difficulty;\n let hash;\n let nonce = eve |
