chore: port client-side JS to TypeScript (#1100)
* chore(challenge/preact): port to typescript Signed-off-by: Xe Iaso <me@xeiaso.net> * chore(js/algorithms): port to typescript Signed-off-by: Xe Iaso <me@xeiaso.net> * chore(js/worker): port to typescript Signed-off-by: Xe Iaso <me@xeiaso.net> * chore(web): fix TypeScript build logic Signed-off-by: Xe Iaso <me@xeiaso.net> * chore(web): port bench.mjs to typescript Signed-off-by: Xe Iaso <me@xeiaso.net> * chore(web): port main.mjs to typescript Signed-off-by: Xe Iaso <me@xeiaso.net> * Update metadata check-spelling run (pull_request) for Xe/use-typescript Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com> on-behalf-of: @check-spelling <check-spelling-bot@check-spelling.dev> * fix(js/algorithms/fast): handle old browsers Closes #1082 Signed-off-by: Xe Iaso <me@xeiaso.net> --------- Signed-off-by: Xe Iaso <me@xeiaso.net> Signed-off-by: check-spelling-bot <check-spelling-bot@users.noreply.github.com>
This commit is contained in:
parent
8ed89a6c6e
commit
2011b83a44
12 changed files with 190 additions and 130 deletions
2
.github/actions/spelling/expect.txt
vendored
2
.github/actions/spelling/expect.txt
vendored
|
|
@ -214,6 +214,7 @@ nicksnyder
|
||||||
nobots
|
nobots
|
||||||
NONINFRINGEMENT
|
NONINFRINGEMENT
|
||||||
nosleep
|
nosleep
|
||||||
|
nullglob
|
||||||
OCOB
|
OCOB
|
||||||
ogtag
|
ogtag
|
||||||
oklch
|
oklch
|
||||||
|
|
@ -278,6 +279,7 @@ Seo
|
||||||
setsebool
|
setsebool
|
||||||
shellcheck
|
shellcheck
|
||||||
shirou
|
shirou
|
||||||
|
shopt
|
||||||
Sidetrade
|
Sidetrade
|
||||||
simprint
|
simprint
|
||||||
sitemap
|
sitemap
|
||||||
|
|
|
||||||
4
lib/challenge/metarefresh/metarefresh_templ.go
generated
4
lib/challenge/metarefresh/metarefresh_templ.go
generated
|
|
@ -93,9 +93,9 @@ func page(redir string, difficulty int, loc *localization.SimpleLocalizer) templ
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var6 string
|
var templ_7745c5c3_Var6 string
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d; url=%s", difficulty, redir))
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d; url=%s", difficulty+1, redir))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `metarefresh.templ`, Line: 16, Col: 83}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `metarefresh.templ`, Line: 16, Col: 85}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ for the JavaScript code in this page.
|
||||||
|
|
||||||
mkdir -p static/js
|
mkdir -p static/js
|
||||||
|
|
||||||
for file in js/*.jsx; do
|
for file in js/*.tsx; do
|
||||||
filename="${file##*/}" # Extracts "app.jsx" from "./js/app.jsx"
|
filename="${file##*/}" # Extracts "app.jsx" from "./js/app.jsx"
|
||||||
output="${filename%.jsx}.js" # Changes "app.jsx" to "app.js"
|
output="${filename%.tsx}.js" # Changes "app.jsx" to "app.js"
|
||||||
echo $output
|
echo $output
|
||||||
|
|
||||||
esbuild "${file}" --minify --bundle --outfile=static/"${output}" --banner:js="${LICENSE}"
|
esbuild "${file}" --minify --bundle --outfile=static/"${output}" --banner:js="${LICENSE}"
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import { render, h, Fragment } from 'preact';
|
|
||||||
import { useState, useEffect } from 'preact/hooks';
|
|
||||||
import { g, j, u, x } from "./xeact.js";
|
|
||||||
import { Sha256 } from '@aws-crypto/sha256-js';
|
|
||||||
|
|
||||||
/** @jsx h */
|
|
||||||
/** @jsxFrag Fragment */
|
|
||||||
|
|
||||||
function toHexString(arr) {
|
|
||||||
return Array.from(arr)
|
|
||||||
.map((c) => c.toString(16).padStart(2, "0"))
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
const App = () => {
|
|
||||||
const [state, setState] = useState(null);
|
|
||||||
const [imageURL, setImageURL] = useState(null);
|
|
||||||
const [passed, setPassed] = useState(false);
|
|
||||||
const [challenge, setChallenge] = useState(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setState(j("preact_info"));
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setImageURL(state.pensive_url);
|
|
||||||
const hash = new Sha256('');
|
|
||||||
hash.update(state.challenge);
|
|
||||||
setChallenge(toHexString(hash.digestSync()));
|
|
||||||
}, [state]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const timer = setTimeout(() => {
|
|
||||||
setPassed(true);
|
|
||||||
}, state.difficulty * 125);
|
|
||||||
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
}, [challenge]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
window.location.href = u(state.redir, {
|
|
||||||
result: challenge,
|
|
||||||
});
|
|
||||||
}, [passed]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{imageURL !== null && (
|
|
||||||
<img src={imageURL} style="width:100%;max-width:256px;" />
|
|
||||||
)}
|
|
||||||
{state !== null && (
|
|
||||||
<>
|
|
||||||
<p id="status">{state.loading_message}</p>
|
|
||||||
<p>{state.connection_security_message}</p>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
x(g("app"));
|
|
||||||
render(<App />, g("app"));
|
|
||||||
87
lib/challenge/preact/js/app.tsx
Normal file
87
lib/challenge/preact/js/app.tsx
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import { render, h, Fragment } from "preact";
|
||||||
|
import { useState, useEffect } from "preact/hooks";
|
||||||
|
import { g, j, r, u, x } from "./xeact.js";
|
||||||
|
import { Sha256 } from "@aws-crypto/sha256-js";
|
||||||
|
|
||||||
|
/** @jsx h */
|
||||||
|
/** @jsxFrag Fragment */
|
||||||
|
|
||||||
|
function toHexString(arr: Uint8Array) {
|
||||||
|
return Array.from(arr)
|
||||||
|
.map((c) => c.toString(16).padStart(2, "0"))
|
||||||
|
.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PreactInfo {
|
||||||
|
redir: string;
|
||||||
|
challenge: string;
|
||||||
|
difficulty: number;
|
||||||
|
connection_security_message: string;
|
||||||
|
loading_message: string;
|
||||||
|
pensive_url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const [state, setState] = useState<PreactInfo>();
|
||||||
|
const [imageURL, setImageURL] = useState<string | null>(null);
|
||||||
|
const [passed, setPassed] = useState<boolean>(false);
|
||||||
|
const [challenge, setChallenge] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setState(j("preact_info"));
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (state === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setImageURL(state?.pensive_url);
|
||||||
|
const hash = new Sha256("");
|
||||||
|
hash.update(state.challenge);
|
||||||
|
setChallenge(toHexString(hash.digestSync()));
|
||||||
|
}, [state]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (state === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setPassed(true);
|
||||||
|
}, state?.difficulty * 125);
|
||||||
|
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
}, [challenge]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (state === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (challenge === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.location.href = u(state.redir, {
|
||||||
|
result: challenge,
|
||||||
|
});
|
||||||
|
}, [passed]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{imageURL !== null && (
|
||||||
|
<img src={imageURL} style={{ width: "100%", maxWidth: "256px" }} />
|
||||||
|
)}
|
||||||
|
{state !== undefined && (
|
||||||
|
<>
|
||||||
|
<p id="status">{state.loading_message}</p>
|
||||||
|
<p>{state.connection_security_message}</p>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
x(g("app"));
|
||||||
|
render(<App />, g("app"));
|
||||||
19
web/build.sh
19
web/build.sh
|
|
@ -39,9 +39,18 @@ for the JavaScript code in this page.
|
||||||
mkdir -p static/locales
|
mkdir -p static/locales
|
||||||
cp ../lib/localization/locales/*.json static/locales/
|
cp ../lib/localization/locales/*.json static/locales/
|
||||||
|
|
||||||
for file in js/*.mjs js/worker/*.mjs; do
|
shopt -s nullglob globstar
|
||||||
esbuild "${file}" --sourcemap --bundle --minify --outfile=static/"${file}" --banner:js="${LICENSE}"
|
|
||||||
gzip -f -k -n static/${file}
|
for file in js/**/*.ts js/**/*.mjs; do
|
||||||
zstd -f -k --ultra -22 static/${file}
|
out="static/${file}"
|
||||||
brotli -fZk static/${file}
|
if [[ "$file" == *.ts ]]; then
|
||||||
|
out="static/${file%.ts}.mjs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$out")"
|
||||||
|
|
||||||
|
esbuild "$file" --sourcemap --bundle --minify --outfile="$out" --banner:js="$LICENSE"
|
||||||
|
gzip -f -k -n "$out"
|
||||||
|
zstd -f -k --ultra -22 "$out"
|
||||||
|
brotli -fZk "$out"
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,21 @@
|
||||||
|
type ProgressCallback = (nonce: number) => void;
|
||||||
|
|
||||||
|
interface ProcessOptions {
|
||||||
|
basePrefix: string;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getHardwareConcurrency = () =>
|
||||||
|
navigator.hardwareConcurrency !== undefined ? navigator.hardwareConcurrency : 1;
|
||||||
|
|
||||||
export default function process(
|
export default function process(
|
||||||
{ basePrefix, version },
|
options: ProcessOptions,
|
||||||
data,
|
data: string,
|
||||||
difficulty = 5,
|
difficulty: number = 5,
|
||||||
signal = null,
|
signal: AbortSignal | null = null,
|
||||||
progressCallback = null,
|
progressCallback?: ProgressCallback,
|
||||||
threads = Math.trunc(Math.max(navigator.hardwareConcurrency / 2, 1)),
|
threads: number = Math.trunc(Math.max(getHardwareConcurrency() / 2, 1)),
|
||||||
) {
|
): Promise<string> {
|
||||||
console.debug("fast algo");
|
console.debug("fast algo");
|
||||||
|
|
||||||
let workerMethod = window.crypto !== undefined ? "webcrypto" : "purejs";
|
let workerMethod = window.crypto !== undefined ? "webcrypto" : "purejs";
|
||||||
|
|
@ -16,13 +26,17 @@ export default function process(
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let webWorkerURL = `${basePrefix}/.within.website/x/cmd/anubis/static/js/worker/sha256-${workerMethod}.mjs?cacheBuster=${version}`;
|
let webWorkerURL = `${options.basePrefix}/.within.website/x/cmd/anubis/static/js/worker/sha256-${workerMethod}.mjs?cacheBuster=${options.version}`;
|
||||||
|
|
||||||
console.log(webWorkerURL);
|
const workers: Worker[] = [];
|
||||||
|
|
||||||
const workers = [];
|
|
||||||
let settled = false;
|
let settled = false;
|
||||||
|
|
||||||
|
const onAbort = () => {
|
||||||
|
console.log("PoW aborted");
|
||||||
|
cleanup();
|
||||||
|
reject(new DOMException("Aborted", "AbortError"));
|
||||||
|
};
|
||||||
|
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
if (settled) {
|
if (settled) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -34,12 +48,6 @@ export default function process(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAbort = () => {
|
|
||||||
console.log("PoW aborted");
|
|
||||||
cleanup();
|
|
||||||
reject(new DOMException("Aborted", "AbortError"));
|
|
||||||
};
|
|
||||||
|
|
||||||
if (signal != null) {
|
if (signal != null) {
|
||||||
if (signal.aborted) {
|
if (signal.aborted) {
|
||||||
return onAbort();
|
return onAbort();
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import fast from "./fast.mjs";
|
import fast from "./fast";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fast: fast,
|
fast: fast,
|
||||||
|
|
@ -1,20 +1,24 @@
|
||||||
import algorithms from "./algorithms/index.mjs";
|
import algorithms from "./algorithms";
|
||||||
|
|
||||||
const defaultDifficulty = 4;
|
const defaultDifficulty = 4;
|
||||||
|
|
||||||
const status = document.getElementById("status");
|
const status: HTMLParagraphElement = document.getElementById("status") as HTMLParagraphElement;
|
||||||
const difficultyInput = document.getElementById("difficulty-input");
|
const difficultyInput: HTMLInputElement = document.getElementById("difficulty-input") as HTMLInputElement;
|
||||||
const algorithmSelect = document.getElementById("algorithm-select");
|
const algorithmSelect: HTMLSelectElement = document.getElementById("algorithm-select") as HTMLSelectElement;
|
||||||
const compareSelect = document.getElementById("compare-select");
|
const compareSelect: HTMLSelectElement = document.getElementById("compare-select") as HTMLSelectElement;
|
||||||
const header = document.getElementById("table-header");
|
const header: HTMLTableRowElement = document.getElementById("table-header") as HTMLTableRowElement;
|
||||||
const headerCompare = document.getElementById("table-header-compare");
|
const headerCompare: HTMLTableSectionElement = document.getElementById("table-header-compare") as HTMLTableSectionElement;
|
||||||
const results = document.getElementById("results");
|
const results: HTMLTableRowElement = document.getElementById("results") as HTMLTableRowElement;
|
||||||
|
|
||||||
const setupControls = () => {
|
const setupControls = () => {
|
||||||
difficultyInput.value = defaultDifficulty;
|
if (defaultDifficulty == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
difficultyInput.value = defaultDifficulty.toString();
|
||||||
for (const alg of Object.keys(algorithms)) {
|
for (const alg of Object.keys(algorithms)) {
|
||||||
const option1 = document.createElement("option");
|
const option1 = document.createElement("option");
|
||||||
algorithmSelect.append(option1);
|
algorithmSelect?.append(option1);
|
||||||
const option2 = document.createElement("option");
|
const option2 = document.createElement("option");
|
||||||
compareSelect.append(option2);
|
compareSelect.append(option2);
|
||||||
option1.value = option1.innerText = option2.value = option2.innerText = alg;
|
option1.value = option1.innerText = option2.value = option2.innerText = alg;
|
||||||
|
|
@ -116,13 +120,13 @@ const benchmarkLoop = async (controller) => {
|
||||||
await benchmarkLoop(controller);
|
await benchmarkLoop(controller);
|
||||||
};
|
};
|
||||||
|
|
||||||
let controller = null;
|
let controller: AbortController | null = null;
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
stats.time = stats.iters = 0;
|
stats.time = stats.iters = 0;
|
||||||
comparison.time = comparison.iters = 0;
|
comparison.time = comparison.iters = 0;
|
||||||
results.innerHTML = status.innerText = "";
|
results.innerHTML = status.innerText = "";
|
||||||
|
|
||||||
const table = results.parentElement;
|
const table = results.parentElement as HTMLElement;
|
||||||
if (compareSelect.value !== "NONE") {
|
if (compareSelect.value !== "NONE") {
|
||||||
table.style.gridTemplateColumns = "repeat(4,auto)";
|
table.style.gridTemplateColumns = "repeat(4,auto)";
|
||||||
header.style.display = "none";
|
header.style.display = "none";
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
import algorithms from "./algorithms/index.mjs";
|
import algorithms from "./algorithms";
|
||||||
|
|
||||||
// from Xeact
|
// from Xeact
|
||||||
const u = (url = "", params = {}) => {
|
const u = (url: string = "", params: Record<string, any> = {}) => {
|
||||||
let result = new URL(url, window.location.href);
|
let result = new URL(url, window.location.href);
|
||||||
Object.entries(params).forEach(([k, v]) => result.searchParams.set(k, v));
|
Object.entries(params).forEach(([k, v]) => result.searchParams.set(k, v));
|
||||||
return result.toString();
|
return result.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const j = (id: string): any | null => {
|
||||||
|
const elem = document.getElementById(id);
|
||||||
|
if (elem === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JSON.parse(elem.textContent);
|
||||||
|
};
|
||||||
|
|
||||||
const imageURL = (mood, cacheBuster, basePrefix) =>
|
const imageURL = (mood, cacheBuster, basePrefix) =>
|
||||||
u(`${basePrefix}/.within.website/x/cmd/anubis/static/img/${mood}.webp`, {
|
u(`${basePrefix}/.within.website/x/cmd/anubis/static/img/${mood}.webp`, {
|
||||||
cacheBuster,
|
cacheBuster,
|
||||||
|
|
@ -14,9 +23,10 @@ const imageURL = (mood, cacheBuster, basePrefix) =>
|
||||||
|
|
||||||
// Detect available languages by loading the manifest
|
// Detect available languages by loading the manifest
|
||||||
const getAvailableLanguages = async () => {
|
const getAvailableLanguages = async () => {
|
||||||
const basePrefix = JSON.parse(
|
const basePrefix = j("anubis_base_prefix");
|
||||||
document.getElementById("anubis_base_prefix").textContent,
|
if (basePrefix === null) {
|
||||||
);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${basePrefix}/.within.website/x/cmd/anubis/static/locales/manifest.json`);
|
const response = await fetch(`${basePrefix}/.within.website/x/cmd/anubis/static/locales/manifest.json`);
|
||||||
|
|
@ -38,9 +48,11 @@ const getBrowserLanguage = async () =>
|
||||||
|
|
||||||
// Load translations from JSON files
|
// Load translations from JSON files
|
||||||
const loadTranslations = async (lang) => {
|
const loadTranslations = async (lang) => {
|
||||||
const basePrefix = JSON.parse(
|
const basePrefix = j("anubis_base_prefix");
|
||||||
document.getElementById("anubis_base_prefix").textContent,
|
if (basePrefix === null) {
|
||||||
);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${basePrefix}/.within.website/x/cmd/anubis/static/locales/${lang}.json`);
|
const response = await fetch(`${basePrefix}/.within.website/x/cmd/anubis/static/locales/${lang}.json`);
|
||||||
return await response.json();
|
return await response.json();
|
||||||
|
|
@ -54,9 +66,10 @@ const loadTranslations = async (lang) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getRedirectUrl = () => {
|
const getRedirectUrl = () => {
|
||||||
const publicUrl = JSON.parse(
|
const publicUrl = j("anubis_public_url");
|
||||||
document.getElementById("anubis_public_url").textContent,
|
if (publicUrl === null) {
|
||||||
);
|
return;
|
||||||
|
}
|
||||||
if (publicUrl && window.location.href.startsWith(publicUrl)) {
|
if (publicUrl && window.location.href.startsWith(publicUrl)) {
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
return urlParams.get('redir');
|
return urlParams.get('redir');
|
||||||
|
|
@ -91,16 +104,14 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
|
||||||
value: navigator.cookieEnabled,
|
value: navigator.cookieEnabled,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const status = document.getElementById("status");
|
|
||||||
const image = document.getElementById("image");
|
const status: HTMLParagraphElement = document.getElementById("status") as HTMLParagraphElement;
|
||||||
const title = document.getElementById("title");
|
const image: HTMLImageElement = document.getElementById("image") as HTMLImageElement;
|
||||||
const progress = document.getElementById("progress");
|
const title: HTMLHeadingElement = document.getElementById("title") as HTMLHeadingElement;
|
||||||
const anubisVersion = JSON.parse(
|
const progress: HTMLDivElement = document.getElementById("progress") as HTMLDivElement;
|
||||||
document.getElementById("anubis_version").textContent,
|
|
||||||
);
|
const anubisVersion = j("anubis_version");
|
||||||
const basePrefix = JSON.parse(
|
const basePrefix = j("anubis_base_prefix");
|
||||||
document.getElementById("anubis_base_prefix").textContent,
|
|
||||||
);
|
|
||||||
const details = document.querySelector("details");
|
const details = document.querySelector("details");
|
||||||
let userReadDetails = false;
|
let userReadDetails = false;
|
||||||
|
|
||||||
|
|
@ -132,9 +143,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { challenge, rules } = JSON.parse(
|
const { challenge, rules } = j("anubis_challenge");
|
||||||
document.getElementById("anubis_challenge").textContent,
|
|
||||||
);
|
|
||||||
|
|
||||||
const process = algorithms[rules.algorithm];
|
const process = algorithms[rules.algorithm];
|
||||||
if (!process) {
|
if (!process) {
|
||||||
|
|
@ -182,7 +191,9 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
|
||||||
const probability = Math.pow(1 - likelihood, iters);
|
const probability = Math.pow(1 - likelihood, iters);
|
||||||
const distance = (1 - Math.pow(probability, 2)) * 100;
|
const distance = (1 - Math.pow(probability, 2)) * 100;
|
||||||
progress["aria-valuenow"] = distance;
|
progress["aria-valuenow"] = distance;
|
||||||
progress.firstElementChild.style.width = `${distance}%`;
|
if (progress.firstElementChild !== null) {
|
||||||
|
(progress.firstElementChild as HTMLElement).style.width = `${distance}%`;
|
||||||
|
}
|
||||||
|
|
||||||
if (probability < 0.1 && !showingApology) {
|
if (probability < 0.1 && !showingApology) {
|
||||||
status.append(
|
status.append(
|
||||||
|
|
@ -197,7 +208,7 @@ const t = (key) => translations[`js_${key}`] || translations[key] || key;
|
||||||
console.log({ hash, nonce });
|
console.log({ hash, nonce });
|
||||||
|
|
||||||
if (userReadDetails) {
|
if (userReadDetails) {
|
||||||
const container = document.getElementById("progress");
|
const container: HTMLDivElement = document.getElementById("progress") as HTMLDivElement;
|
||||||
|
|
||||||
// Style progress bar as a continue button
|
// Style progress bar as a continue button
|
||||||
container.style.display = "flex";
|
container.style.display = "flex";
|
||||||
|
|
@ -6,7 +6,7 @@ const calculateSHA256 = (text) => {
|
||||||
return hash.digest();
|
return hash.digest();
|
||||||
};
|
};
|
||||||
|
|
||||||
function toHexString(arr) {
|
function toHexString(arr: Uint8Array): string {
|
||||||
return Array.from(arr)
|
return Array.from(arr)
|
||||||
.map((c) => c.toString(16).padStart(2, "0"))
|
.map((c) => c.toString(16).padStart(2, "0"))
|
||||||
.join("");
|
.join("");
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
const calculateSHA256 = async (input) => {
|
|
||||||
|
const calculateSHA256 = async (input: string) => {
|
||||||
const data = encoder.encode(input);
|
const data = encoder.encode(input);
|
||||||
return await crypto.subtle.digest("SHA-256", data);
|
return await crypto.subtle.digest("SHA-256", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toHexString = (byteArray) => {
|
const toHexString = (byteArray: Uint8Array) => {
|
||||||
return byteArray.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
return byteArray.reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), "");
|
||||||
};
|
};
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue