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

@ -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),
});
}
})();