jane remover
Some checks failed
Docker image builds / build (push) Waiting to run
Asset Build Verification / asset_verification (push) Has been cancelled
Docs deploy / build (push) Has been cancelled
Go Mod Tidy Check / go_mod_tidy_check (push) Has been cancelled
Go / go_tests (push) Has been cancelled
Package builds (unstable) / package_builds (push) Has been cancelled
Smoke tests / smoke-test (default-config-macro) (push) Has been cancelled
Smoke tests / smoke-test (docker-registry) (push) Has been cancelled
Smoke tests / smoke-test (double_slash) (push) Has been cancelled
Smoke tests / smoke-test (forced-language) (push) Has been cancelled
Smoke tests / smoke-test (git-clone) (push) Has been cancelled
Smoke tests / smoke-test (git-push) (push) Has been cancelled
Smoke tests / smoke-test (healthcheck) (push) Has been cancelled
Smoke tests / smoke-test (i18n) (push) Has been cancelled
Smoke tests / smoke-test (log-file) (push) Has been cancelled
Smoke tests / smoke-test (nginx) (push) Has been cancelled
Smoke tests / smoke-test (palemoon/amd64) (push) Has been cancelled
Smoke tests / smoke-test (robots_txt) (push) Has been cancelled
Check Spelling / Check Spelling (push) Has been cancelled
SSH CI / ssh (aarch64-16k) (push) Has been cancelled
SSH CI / ssh (aarch64-4k) (push) Has been cancelled
SSH CI / ssh (ppc64le) (push) Has been cancelled
SSH CI / ssh (riscv64) (push) Has been cancelled
zizmor / zizmor latest via PyPI (push) Has been cancelled

This commit is contained in:
Soph :3 2026-02-07 13:08:47 +02:00
parent d2205b11a7
commit 896858e027
332 changed files with 1482 additions and 33742 deletions

View file

@ -7,9 +7,9 @@ import (
"github.com/a-h/templ"
"github.com/TecharoHQ/anubis/lib/challenge"
"github.com/TecharoHQ/anubis/lib/config"
"github.com/TecharoHQ/anubis/lib/localization"
"git.sad.ovh/sophie/nuke/lib/challenge"
"git.sad.ovh/sophie/nuke/lib/config"
"git.sad.ovh/sophie/nuke/lib/localization"
)
func Base(title string, body templ.Component, impressum *config.Impressum, localizer *localization.SimpleLocalizer) templ.Component {

View file

@ -2,10 +2,10 @@ package web
import (
"fmt"
"github.com/TecharoHQ/anubis"
"github.com/TecharoHQ/anubis/lib/config"
"github.com/TecharoHQ/anubis/lib/localization"
"github.com/TecharoHQ/anubis/xess"
"git.sad.ovh/sophie/nuke"
"git.sad.ovh/sophie/nuke/lib/config"
"git.sad.ovh/sophie/nuke/lib/localization"
"git.sad.ovh/sophie/nuke/xess"
"github.com/google/uuid"
)
@ -14,7 +14,7 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
<html lang={ localizer.GetLang() }>
<head>
<title>{ title }</title>
<link rel="stylesheet" href={ anubis.BasePrefix + xess.URL }/>
<link rel="stylesheet" href={ nuke.BasePrefix + xess.URL }/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="robots" content="noindex,nofollow"/>
for key, value := range ogTags {
@ -58,31 +58,31 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
transition: width 0.25s ease-in;
}
</style>
@templ.JSONScript("anubis_version", anubis.Version)
@templ.JSONScript("anubis_challenge", challenge)
@templ.JSONScript("anubis_base_prefix", anubis.BasePrefix)
@templ.JSONScript("anubis_public_url", anubis.PublicUrl)
@templ.JSONScript("nuke_version", nuke.Version)
@templ.JSONScript("nuke_challenge", challenge)
@templ.JSONScript("nuke_base_prefix", nuke.BasePrefix)
@templ.JSONScript("nuke_public_url", nuke.PublicUrl)
</head>
<body id="top">
@honeypotLink(anubis.BasePrefix + fmt.Sprintf("%shoneypot/%s/init", anubis.APIPrefix, uuid.NewString()))
@honeypotLink(nuke.BasePrefix + fmt.Sprintf("%shoneypot/%s/init", nuke.APIPrefix, uuid.NewString()))
<main>
<h1 id="title" class="centered-div">{ title }</h1>
@body
<footer>
<div class="centered-div">
<p>
{ localizer.T("protected_by") } <a href="https://github.com/TecharoHQ/anubis">Anubis</a> { localizer.T("protected_from") } <a
href="https://techaro.lol"
>Techaro</a>. { localizer.T("made_with") }.
{ localizer.T("protected_by") } <a href="https://git.sad.ovh/sophie/nuke">Nuke</a> { localizer.T("protected_from") } <a
href="sad.ovh"
>sad.ovh</a>. { localizer.T("made_with") }.
</p>
<p>{ localizer.T("mascot_design") } <a href="https://bsky.app/profile/celphase.bsky.social">{ localizer.T("celphase") }</a>.</p>
if impressum != nil {
<p>
@templ.Raw(impressum.Footer)
-- <a href={ templ.SafeURL(anubis.BasePrefix + fmt.Sprintf("%simprint", anubis.APIPrefix)) }>Imprint</a>
-- <a href={ templ.SafeURL(nuke.BasePrefix + fmt.Sprintf("%simprint", nuke.APIPrefix)) }>Imprint</a>
</p>
}
<p>{ localizer.T("version_info") } <code>{ anubis.Version }</code>.</p>
<p>{ localizer.T("version_info") } <code>{ nuke.Version }</code>.</p>
</div>
</footer>
</main>
@ -92,7 +92,7 @@ templ base(title string, body templ.Component, impressum *config.Impressum, chal
templ errorPage(message, mail, code string, localizer *localization.SimpleLocalizer) {
<div class="centered-div">
<img id="image" alt="Sad Anubis" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/reject.webp?cacheBuster=" + anubis.Version }/>
<img id="image" alt="Sad Nuke" style="width:100%;max-width:256px;" src={ nuke.BasePrefix + "/.within.website/x/cmd/nuke/static/img/reject.webp?cacheBuster=" + nuke.Version }/>
<p>{ message }.</p>
if code != "" {
<code><pre>{ code }</pre></code>
@ -115,8 +115,8 @@ templ StaticHappy(localizer *localization.SimpleLocalizer) {
<img
style="display:none;"
style="width:100%;max-width:256px;"
src={ "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" +
anubis.Version }
src={ "/.within.website/x/cmd/nuke/static/img/happy.webp?cacheBuster=" +
nuke.Version }
/>
<p>{ localizer.T("static_check_endpoint") }</p>
</div>
@ -145,9 +145,9 @@ templ bench(localizer *localization.SimpleLocalizer) {
></tbody>
</table>
<div class="centered-div">
<img id="image" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version }/>
<img id="image" style="width:100%;max-width:256px;" src={ nuke.BasePrefix + "/.within.website/x/cmd/nuke/static/img/pensive.webp?cacheBuster=" + nuke.Version }/>
<p id="status" style="max-width:256px">{ localizer.T("loading") }</p>
<script async type="module" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/bench.mjs?cacheBuster=" + anubis.Version }></script>
<script async type="module" src={ nuke.BasePrefix + "/.within.website/x/cmd/nuke/static/js/bench.mjs?cacheBuster=" + nuke.Version }></script>
<div id="sparkline"></div>
<noscript>
<p>{ localizer.T("benchmark_requires_js") }</p>

56
web/index_templ.go generated
View file

@ -10,10 +10,10 @@ import templruntime "github.com/a-h/templ/runtime"
import (
"fmt"
"github.com/TecharoHQ/anubis"
"github.com/TecharoHQ/anubis/lib/config"
"github.com/TecharoHQ/anubis/lib/localization"
"github.com/TecharoHQ/anubis/xess"
"git.sad.ovh/sophie/nuke"
"git.sad.ovh/sophie/nuke/lib/config"
"git.sad.ovh/sophie/nuke/lib/localization"
"git.sad.ovh/sophie/nuke/xess"
"github.com/google/uuid"
)
@ -69,9 +69,9 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 templ.SafeURL
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(anubis.BasePrefix + xess.URL)
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(nuke.BasePrefix + xess.URL)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 17, Col: 61}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 17, Col: 59}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
@ -117,19 +117,19 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.JSONScript("anubis_version", anubis.Version).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = templ.JSONScript("nuke_version", nuke.Version).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.JSONScript("anubis_challenge", challenge).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = templ.JSONScript("nuke_challenge", challenge).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.JSONScript("anubis_base_prefix", anubis.BasePrefix).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = templ.JSONScript("nuke_base_prefix", nuke.BasePrefix).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.JSONScript("anubis_public_url", anubis.PublicUrl).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = templ.JSONScript("nuke_public_url", nuke.PublicUrl).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -137,7 +137,7 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = honeypotLink(anubis.BasePrefix+fmt.Sprintf("%shoneypot/%s/init", anubis.APIPrefix, uuid.NewString())).Render(ctx, templ_7745c5c3_Buffer)
templ_7745c5c3_Err = honeypotLink(nuke.BasePrefix+fmt.Sprintf("%shoneypot/%s/init", nuke.APIPrefix, uuid.NewString())).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -175,20 +175,20 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " <a href=\"https://github.com/TecharoHQ/anubis\">Anubis</a> ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, " <a href=\"https://git.sad.ovh/sophie/nuke\">Nuke</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("protected_from"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 74, Col: 127}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 74, Col: 121}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " <a href=\"https://techaro.lol\">Techaro</a>. ")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, " <a href=\"sad.ovh\">sad.ovh</a>. ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@ -245,9 +245,9 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 templ.SafeURL
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(anubis.BasePrefix + fmt.Sprintf("%simprint", anubis.APIPrefix)))
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(nuke.BasePrefix + fmt.Sprintf("%simprint", nuke.APIPrefix)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 82, Col: 98}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 82, Col: 94}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
@ -276,9 +276,9 @@ func base(title string, body templ.Component, impressum *config.Impressum, chall
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.Version)
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(nuke.Version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 85, Col: 63}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 85, Col: 61}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
@ -313,14 +313,14 @@ func errorPage(message, mail, code string, localizer *localization.SimpleLocaliz
templ_7745c5c3_Var16 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<div class=\"centered-div\"><img id=\"image\" alt=\"Sad Anubis\" style=\"width:100%;max-width:256px;\" src=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "<div class=\"centered-div\"><img id=\"image\" alt=\"Sad Nuke\" style=\"width:100%;max-width:256px;\" src=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var17 string
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/reject.webp?cacheBuster=" + anubis.Version)
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(nuke.BasePrefix + "/.within.website/x/cmd/nuke/static/img/reject.webp?cacheBuster=" + nuke.Version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 95, Col: 181}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 95, Col: 173}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
if templ_7745c5c3_Err != nil {
@ -472,10 +472,10 @@ func StaticHappy(localizer *localization.SimpleLocalizer) templ.Component {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" +
anubis.Version)
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs("/.within.website/x/cmd/nuke/static/img/happy.webp?cacheBuster=" +
nuke.Version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 119, Col: 18}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 119, Col: 16}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil {
@ -606,9 +606,9 @@ func bench(localizer *localization.SimpleLocalizer) templ.Component {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var35 string
templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version)
templ_7745c5c3_Var35, templ_7745c5c3_Err = templ.JoinStringErrs(nuke.BasePrefix + "/.within.website/x/cmd/nuke/static/img/pensive.webp?cacheBuster=" + nuke.Version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 148, Col: 166}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 148, Col: 160}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var35))
if templ_7745c5c3_Err != nil {
@ -632,9 +632,9 @@ func bench(localizer *localization.SimpleLocalizer) templ.Component {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var37 string
templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/bench.mjs?cacheBuster=" + anubis.Version)
templ_7745c5c3_Var37, templ_7745c5c3_Err = templ.JoinStringErrs(nuke.BasePrefix + "/.within.website/x/cmd/nuke/static/js/bench.mjs?cacheBuster=" + nuke.Version)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 150, Col: 138}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `index.templ`, Line: 150, Col: 132}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var37))
if templ_7745c5c3_Err != nil {

View file

@ -6,9 +6,9 @@ import (
"strings"
"testing"
"github.com/TecharoHQ/anubis"
"github.com/TecharoHQ/anubis/lib/config"
"github.com/TecharoHQ/anubis/lib/localization"
"git.sad.ovh/sophie/nuke"
"git.sad.ovh/sophie/nuke/lib/config"
"git.sad.ovh/sophie/nuke/lib/localization"
"github.com/a-h/templ"
)
@ -21,27 +21,27 @@ func TestBasePrefixInLinks(t *testing.T) {
{
name: "no prefix",
basePrefix: "",
wantInLink: "/.within.website/x/cmd/anubis/api/",
wantInLink: "/.within.website/x/cmd/nuke/api/",
},
{
name: "with rififi prefix",
basePrefix: "/rififi",
wantInLink: "/rififi/.within.website/x/cmd/anubis/api/",
wantInLink: "/rififi/.within.website/x/cmd/nuke/api/",
},
{
name: "with myapp prefix",
basePrefix: "/myapp",
wantInLink: "/myapp/.within.website/x/cmd/anubis/api/",
wantInLink: "/myapp/.within.website/x/cmd/nuke/api/",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Save original BasePrefix and restore after test
origPrefix := anubis.BasePrefix
defer func() { anubis.BasePrefix = origPrefix }()
origPrefix := nuke.BasePrefix
defer func() { nuke.BasePrefix = origPrefix }()
anubis.BasePrefix = tt.basePrefix
nuke.BasePrefix = tt.basePrefix
// Create test impressum
impressum := &config.Impressum{

View file

@ -6,7 +6,9 @@ interface ProcessOptions {
}
const getHardwareConcurrency = () =>
navigator.hardwareConcurrency !== undefined ? navigator.hardwareConcurrency : 1;
navigator.hardwareConcurrency !== undefined
? navigator.hardwareConcurrency
: 1;
export default function process(
options: ProcessOptions,
@ -25,13 +27,16 @@ export default function process(
workerMethod = "webcrypto";
}
if (navigator.userAgent.includes("Firefox") || navigator.userAgent.includes("Goanna")) {
if (
navigator.userAgent.includes("Firefox") ||
navigator.userAgent.includes("Goanna")
) {
console.log("Firefox detected, using pure-JS fallback");
workerMethod = "purejs";
}
return new Promise((resolve, reject) => {
let webWorkerURL = `${options.basePrefix}/.within.website/x/cmd/anubis/static/js/worker/sha256-${workerMethod}.mjs?cacheBuster=${options.version}`;
let webWorkerURL = `${options.basePrefix}/.within.website/x/cmd/nuke/static/js/worker/sha256-${workerMethod}.mjs?cacheBuster=${options.version}`;
const workers: Worker[] = [];
let settled = false;

View file

@ -17,65 +17,72 @@ const j = (id: string): any | null => {
};
const imageURL = (mood, cacheBuster, basePrefix) =>
u(`${basePrefix}/.within.website/x/cmd/anubis/static/img/${mood}.webp`, {
u(`${basePrefix}/.within.website/x/cmd/nuke/static/img/${mood}.webp`, {
cacheBuster,
});
// Detect available languages by loading the manifest
const getAvailableLanguages = async () => {
const basePrefix = j("anubis_base_prefix");
const basePrefix = j("nuke_base_prefix");
if (basePrefix === null) {
return;
}
try {
const response = await fetch(`${basePrefix}/.within.website/x/cmd/anubis/static/locales/manifest.json`);
const response = await fetch(
`${basePrefix}/.within.website/x/cmd/nuke/static/locales/manifest.json`,
);
if (response.ok) {
const manifest = await response.json();
return manifest.supportedLanguages || ['en'];
return manifest.supportedLanguages || ["en"];
}
} catch (error) {
console.warn('Failed to load language manifest, falling back to default languages');
console.warn(
"Failed to load language manifest, falling back to default languages",
);
}
// Fallback to default languages if manifest loading fails
return ['en'];
return ["en"];
};
// Use the browser language from the HTML lang attribute which is set by the server settings or request headers
const getBrowserLanguage = async () =>
document.documentElement.lang;
const getBrowserLanguage = async () => document.documentElement.lang;
// Load translations from JSON files
const loadTranslations = async (lang) => {
const basePrefix = j("anubis_base_prefix");
const basePrefix = j("nuke_base_prefix");
if (basePrefix === null) {
return;
}
try {
const response = await fetch(`${basePrefix}/.within.website/x/cmd/anubis/static/locales/${lang}.json`);
const response = await fetch(
`${basePrefix}/.within.website/x/cmd/nuke/static/locales/${lang}.json`,
);
return await response.json();
} catch (error) {
console.warn(`Failed to load translations for ${lang}, falling back to English`);
if (lang !== 'en') {
return await loadTranslations('en');
console.warn(
`Failed to load translations for ${lang}, falling back to English`,
);
if (lang !== "en") {
return await loadTranslations("en");
}
throw error;
}
};
const getRedirectUrl = () => {
const publicUrl = j("anubis_public_url");
const publicUrl = j("nuke_public_url");
if (publicUrl === null) {
return;
}
if (publicUrl && window.location.href.startsWith(publicUrl)) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get('redir');
return urlParams.get("redir");
}
return window.location.href;
}
};
let translations = {};
let currentLang;
@ -95,23 +102,31 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
const dependencies = [
{
name: "Web Workers",
msg: t('web_workers_error'),
msg: t("web_workers_error"),
value: window.Worker,
},
{
name: "Cookies",
msg: t('cookies_error'),
msg: t("cookies_error"),
value: navigator.cookieEnabled,
},
];
const status: HTMLParagraphElement = document.getElementById("status") as HTMLParagraphElement;
const image: HTMLImageElement = document.getElementById("image") as HTMLImageElement;
const title: HTMLHeadingElement = document.getElementById("title") as HTMLHeadingElement;
const progress: HTMLDivElement = document.getElementById("progress") as HTMLDivElement;
const status: HTMLParagraphElement = document.getElementById(
"status",
) as HTMLParagraphElement;
const image: HTMLImageElement = document.getElementById(
"image",
) as HTMLImageElement;
const title: HTMLHeadingElement = document.getElementById(
"title",
) as HTMLHeadingElement;
const progress: HTMLDivElement = document.getElementById(
"progress",
) as HTMLDivElement;
const anubisVersion = j("anubis_version");
const basePrefix = j("anubis_base_prefix");
const nukeVersion = j("nuke_version");
const basePrefix = j("nuke_base_prefix");
const details = document.querySelector("details");
let userReadDetails = false;
@ -130,38 +145,38 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
progress.style.display = "none";
};
status.innerHTML = t('calculating');
status.innerHTML = t("calculating");
for (const { value, name, msg } of dependencies) {
if (!value) {
ohNoes({
titleMsg: `${t('missing_feature')} ${name}`,
titleMsg: `${t("missing_feature")} ${name}`,
statusMsg: msg,
imageSrc: imageURL("reject", anubisVersion, basePrefix),
imageSrc: imageURL("reject", nukeVersion, basePrefix),
});
return;
}
}
const { challenge, rules } = j("anubis_challenge");
const { challenge, rules } = j("nuke_challenge");
const process = algorithms[rules.algorithm];
if (!process) {
ohNoes({
titleMsg: t('challenge_error'),
statusMsg: t('challenge_error_msg'),
imageSrc: imageURL("reject", anubisVersion, basePrefix),
titleMsg: t("challenge_error"),
statusMsg: t("challenge_error_msg"),
imageSrc: imageURL("reject", nukeVersion, basePrefix),
});
return;
}
status.innerHTML = `${t('calculating_difficulty')} ${rules.difficulty}, `;
status.innerHTML = `${t("calculating_difficulty")} ${rules.difficulty}, `;
progress.style.display = "inline-block";
// the whole text, including "Speed:", as a single node, because some browsers
// (Firefox mobile) present screen readers with each node as a separate piece
// of text.
const rateText = document.createTextNode(`${t('speed')} 0kH/s`);
const rateText = document.createTextNode(`${t("speed")} 0kH/s`);
status.appendChild(rateText);
let lastSpeedUpdate = 0;
@ -171,7 +186,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
try {
const t0 = Date.now();
const { hash, nonce } = await process(
{ basePrefix, version: anubisVersion },
{ basePrefix, version: nukeVersion },
challenge.randomData,
rules.difficulty,
null,
@ -180,7 +195,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
// only update the speed every second so it's less visually distracting
if (delta - lastSpeedUpdate > 1000) {
lastSpeedUpdate = delta;
rateText.data = `${t('speed')} ${(iters / delta).toFixed(3)}kH/s`;
rateText.data = `${t("speed")} ${(iters / delta).toFixed(3)}kH/s`;
}
// the probability of still being on the page is (1 - likelihood) ^ iters.
// by definition, half of the time the progress bar only gets to half, so
@ -192,13 +207,14 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
const distance = (1 - Math.pow(probability, 2)) * 100;
progress["aria-valuenow"] = distance;
if (progress.firstElementChild !== null) {
(progress.firstElementChild as HTMLElement).style.width = `${distance}%`;
(progress.firstElementChild as HTMLElement).style.width =
`${distance}%`;
}
if (probability < 0.1 && !showingApology) {
status.append(
document.createElement("br"),
document.createTextNode(t('verification_longer')),
document.createTextNode(t("verification_longer")),
);
showingApology = true;
}
@ -208,7 +224,9 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
console.log({ hash, nonce });
if (userReadDetails) {
const container: HTMLDivElement = document.getElementById("progress") as HTMLDivElement;
const container: HTMLDivElement = document.getElementById(
"progress",
) as HTMLDivElement;
// Style progress bar as a continue button
container.style.display = "flex";
@ -224,12 +242,12 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
container.style.outlineOffset = "2px";
container.style.width = "min(20rem, 90%)";
container.style.margin = "1rem auto 2rem";
container.innerHTML = t('finished_reading');
container.innerHTML = t("finished_reading");
function onDetailsExpand() {
const redir = getRedirectUrl();
window.location.replace(
u(`${basePrefix}/.within.website/x/cmd/anubis/api/pass-challenge`, {
u(`${basePrefix}/.within.website/x/cmd/nuke/api/pass-challenge`, {
id: challenge.id,
response: hash,
nonce,
@ -244,7 +262,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
} else {
const redir = getRedirectUrl();
window.location.replace(
u(`${basePrefix}/.within.website/x/cmd/anubis/api/pass-challenge`, {
u(`${basePrefix}/.within.website/x/cmd/nuke/api/pass-challenge`, {
id: challenge.id,
response: hash,
nonce,
@ -255,9 +273,9 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
}
} catch (err) {
ohNoes({
titleMsg: t('calculation_error'),
statusMsg: `${t('calculation_error_msg')} ${err.message}`,
imageSrc: imageURL("reject", anubisVersion, basePrefix),
titleMsg: t("calculation_error"),
statusMsg: `${t("calculation_error_msg")} ${err.message}`,
imageSrc: imageURL("reject", nukeVersion, basePrefix),
});
}
})();