Closer file structure to desired
This commit is contained in:
BIN
embed/assets/static/anubis/geist.woff2
Normal file
BIN
embed/assets/static/anubis/geist.woff2
Normal file
Binary file not shown.
BIN
embed/assets/static/anubis/iosevka-curly.woff2
Normal file
BIN
embed/assets/static/anubis/iosevka-curly.woff2
Normal file
Binary file not shown.
BIN
embed/assets/static/anubis/podkova.woff2
Normal file
BIN
embed/assets/static/anubis/podkova.woff2
Normal file
Binary file not shown.
105
embed/assets/static/anubis/style.css
Normal file
105
embed/assets/static/anubis/style.css
Normal file
@@ -0,0 +1,105 @@
|
||||
@font-face {
|
||||
font-family: "Geist";
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url("geist.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Podkova";
|
||||
font-style: normal;
|
||||
font-weight: 400 800;
|
||||
font-display: swap;
|
||||
src: url("podkova.woff2") format("woff2");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Iosevka Curly";
|
||||
font-style: monospace;
|
||||
font-display: swap;
|
||||
src: url("iosevka-curly.woff2") format("woff2");
|
||||
}
|
||||
|
||||
main {
|
||||
font-family: Geist, sans-serif;
|
||||
max-width: 50rem;
|
||||
padding: 2rem;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: #d3869b;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #1d2021;
|
||||
color: #f9f5d7;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #3c3836;
|
||||
padding: 1em;
|
||||
border: 0;
|
||||
font-family: Iosevka Curly Iaso, monospace;
|
||||
}
|
||||
|
||||
a,
|
||||
a:active,
|
||||
a:visited {
|
||||
color: #b16286;
|
||||
background-color: #282828;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
margin-bottom: 0.1rem;
|
||||
font-family: Podkova, serif;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 1px solid #bdae93;
|
||||
margin: 0.5em 10px;
|
||||
padding: 0.5em 10px;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
body {
|
||||
background: #f9f5d7;
|
||||
color: #1d2021;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #ebdbb2;
|
||||
padding: 1em;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
a,
|
||||
a:active,
|
||||
a:visited {
|
||||
color: #b16286;
|
||||
background-color: #fbf1c7;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
margin-bottom: 0.1rem;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 1px solid #655c54;
|
||||
margin: 0.5em 10px;
|
||||
padding: 0.5em 10px;
|
||||
}
|
||||
}
|
BIN
embed/assets/static/logo.png
Normal file
BIN
embed/assets/static/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
103
embed/challenge/js-pow-sha256/runtime/runtime.go
Normal file
103
embed/challenge/js-pow-sha256/runtime/runtime.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/subtle"
|
||||
"encoding/binary"
|
||||
"git.gammaspectra.live/git/go-away/lib/challenge"
|
||||
"git.gammaspectra.live/git/go-away/lib/challenge/inline"
|
||||
"math/bits"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//go:generate tinygo build -target wasip1 -buildmode=c-shared -opt=2 -scheduler=none -gc=leaking -no-debug -o runtime.wasm runtime.go
|
||||
func main() {
|
||||
|
||||
}
|
||||
|
||||
func getChallenge(key []byte, params map[string]string) ([]byte, uint64) {
|
||||
difficulty := uint64(20)
|
||||
var err error
|
||||
if diffStr, ok := params["difficulty"]; ok {
|
||||
difficulty, err = strconv.ParseUint(diffStr, 10, 64)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
hasher := sha256.New()
|
||||
hasher.Write(binary.LittleEndian.AppendUint64(nil, difficulty))
|
||||
hasher.Write(key)
|
||||
return hasher.Sum(nil), difficulty
|
||||
}
|
||||
|
||||
//go:wasmexport MakeChallenge
|
||||
func MakeChallenge(in challenge.Allocation) (out challenge.Allocation) {
|
||||
return challenge.MakeChallengeDecode(func(in challenge.MakeChallengeInput, out *challenge.MakeChallengeOutput) {
|
||||
c, difficulty := getChallenge(in.Key, in.Parameters)
|
||||
|
||||
// create target
|
||||
target := make([]byte, len(c))
|
||||
nBits := difficulty
|
||||
for i := 0; i < len(target); i++ {
|
||||
var v uint8
|
||||
for j := 0; j < 8; j++ {
|
||||
v <<= 1
|
||||
if nBits == 0 {
|
||||
v |= 1
|
||||
} else {
|
||||
nBits--
|
||||
}
|
||||
}
|
||||
target[i] = v
|
||||
}
|
||||
|
||||
dst := make([]byte, inline.EncodedLen(len(c)))
|
||||
dst = dst[:inline.Encode(dst, c)]
|
||||
|
||||
targetDst := make([]byte, inline.EncodedLen(len(target)))
|
||||
targetDst = targetDst[:inline.Encode(targetDst, target)]
|
||||
|
||||
out.Data = []byte("{\"challenge\": \"" + string(dst) + "\", \"target\": \"" + string(targetDst) + "\", \"difficulty\": " + strconv.FormatUint(difficulty, 10) + "}")
|
||||
out.Headers.Set("Content-Type", "application/json; charset=utf-8")
|
||||
}, in)
|
||||
}
|
||||
|
||||
//go:wasmexport VerifyChallenge
|
||||
func VerifyChallenge(in challenge.Allocation) (out challenge.VerifyChallengeOutput) {
|
||||
return challenge.VerifyChallengeDecode(func(in challenge.VerifyChallengeInput) challenge.VerifyChallengeOutput {
|
||||
c, difficulty := getChallenge(in.Key, in.Parameters)
|
||||
|
||||
result := make([]byte, inline.DecodedLen(len(in.Result)))
|
||||
n, err := inline.Decode(result, in.Result)
|
||||
if err != nil {
|
||||
return challenge.VerifyChallengeOutputError
|
||||
}
|
||||
result = result[:n]
|
||||
|
||||
if len(result) < 8 {
|
||||
return challenge.VerifyChallengeOutputError
|
||||
}
|
||||
|
||||
// verify we used same challenge
|
||||
if subtle.ConstantTimeCompare(result[:len(result)-8], c) != 1 {
|
||||
return challenge.VerifyChallengeOutputFailed
|
||||
}
|
||||
|
||||
hash := sha256.Sum256(result)
|
||||
|
||||
var leadingZeroesCount int
|
||||
for i := 0; i < len(hash); i++ {
|
||||
leadingZeroes := bits.LeadingZeros8(hash[i])
|
||||
leadingZeroesCount += leadingZeroes
|
||||
if leadingZeroes < 8 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if leadingZeroesCount < int(difficulty) {
|
||||
return challenge.VerifyChallengeOutputFailed
|
||||
}
|
||||
|
||||
return challenge.VerifyChallengeOutputOK
|
||||
}, in)
|
||||
}
|
BIN
embed/challenge/js-pow-sha256/runtime/runtime.wasm
Normal file
BIN
embed/challenge/js-pow-sha256/runtime/runtime.wasm
Normal file
Binary file not shown.
119
embed/challenge/js-pow-sha256/static/load.mjs
Normal file
119
embed/challenge/js-pow-sha256/static/load.mjs
Normal file
@@ -0,0 +1,119 @@
|
||||
let _worker;
|
||||
let _webWorkerURL;
|
||||
let _challenge;
|
||||
let _target;
|
||||
let _difficulty;
|
||||
|
||||
async function setup(config) {
|
||||
const { challenge, target, difficulty } = await fetch(config.Path + "/make-challenge", { method: "POST" })
|
||||
.then(r => {
|
||||
if (!r.ok) {
|
||||
throw new Error("Failed to fetch config");
|
||||
}
|
||||
return r.json();
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
_challenge = challenge;
|
||||
_target = target;
|
||||
_difficulty = difficulty;
|
||||
|
||||
_webWorkerURL = URL.createObjectURL(new Blob([
|
||||
'(', processTask(challenge, difficulty), ')()'
|
||||
], { type: 'application/javascript' }));
|
||||
_worker = new Worker(_webWorkerURL);
|
||||
|
||||
return `Difficulty ${difficulty}`
|
||||
}
|
||||
|
||||
function challenge() {
|
||||
return new Promise((resolve, reject) => {
|
||||
_worker.onmessage = (event) => {
|
||||
_worker.terminate();
|
||||
resolve(event.data);
|
||||
};
|
||||
|
||||
_worker.onerror = (event) => {
|
||||
_worker.terminate();
|
||||
reject();
|
||||
};
|
||||
|
||||
_worker.postMessage({
|
||||
challenge: _challenge,
|
||||
target: _target,
|
||||
difficulty: _difficulty,
|
||||
});
|
||||
|
||||
URL.revokeObjectURL(_webWorkerURL);
|
||||
});
|
||||
}
|
||||
|
||||
function processTask() {
|
||||
return function () {
|
||||
|
||||
const decodeHex = (str) => {
|
||||
let result = new Uint8Array(str.length>>1)
|
||||
for (let i = 0; i < str.length; i += 2){
|
||||
result[i>>1] = parseInt(str.substring(i, i + 2), 16)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const encodeHex = (buf) => {
|
||||
return buf.reduce((a, b) => a + b.toString(16).padStart(2, '0'), '')
|
||||
}
|
||||
|
||||
const lessThan = (buf, target) => {
|
||||
for(let i = 0; i < buf.length; ++i){
|
||||
if (buf[i] < target[i]){
|
||||
return true;
|
||||
} else if (buf[i] > target[i]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
const increment = (number) => {
|
||||
for ( let i = 0; i < number.length; i++ ) {
|
||||
if(number[i]===255){
|
||||
number[i] = 0;
|
||||
} else {
|
||||
number[i]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener('message', async (event) => {
|
||||
let data = decodeHex(event.data.challenge);
|
||||
let target = decodeHex(event.data.target);
|
||||
|
||||
let nonce = new Uint8Array(8);
|
||||
let buf = new Uint8Array(data.length + nonce.length);
|
||||
buf.set(data, 0);
|
||||
|
||||
while(true) {
|
||||
buf.set(nonce, data.length);
|
||||
let result = new Uint8Array(await crypto.subtle.digest("SHA-256", buf))
|
||||
|
||||
if (lessThan(result, target)){
|
||||
const nonceNumber = Number(new BigUint64Array(nonce.buffer).at(0))
|
||||
postMessage({
|
||||
result: encodeHex(buf),
|
||||
info: `iterations ${nonceNumber}`,
|
||||
});
|
||||
return
|
||||
}
|
||||
increment(nonce)
|
||||
}
|
||||
|
||||
});
|
||||
}.toString();
|
||||
}
|
||||
|
||||
export { setup, challenge }
|
15
embed/embed.go
Normal file
15
embed/embed.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package embed
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed assets
|
||||
var AssetsFs embed.FS
|
||||
|
||||
//go:embed challenge
|
||||
var ChallengeFs embed.FS
|
||||
|
||||
//go:embed templates
|
||||
var TemplatesFs embed.FS
|
||||
|
||||
//go:embed poison/*.poison
|
||||
var PoisonFs embed.FS
|
BIN
embed/poison/text_html.br.poison
Normal file
BIN
embed/poison/text_html.br.poison
Normal file
Binary file not shown.
BIN
embed/poison/text_html.gzip.poison
Normal file
BIN
embed/poison/text_html.gzip.poison
Normal file
Binary file not shown.
BIN
embed/poison/text_html.zstd.poison
Normal file
BIN
embed/poison/text_html.zstd.poison
Normal file
Binary file not shown.
201
embed/templates/challenge-anubis.gohtml
Normal file
201
embed/templates/challenge-anubis.gohtml
Normal file
@@ -0,0 +1,201 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{{ .Title }}</title>
|
||||
<link rel="stylesheet" href="{{ .Path }}/embed/assets/static/anubis/style.css?cacheBust={{ .Random }}"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
{{ range $key, $value := .Meta }}
|
||||
{{ if eq $key "refresh"}}
|
||||
<meta http-equiv="{{ $key }}" content="{{ $value }}"/>
|
||||
{{else}}
|
||||
<meta name="{{ $key }}" content="{{ $value }}"/>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ range .Tags }}
|
||||
{{ . }}
|
||||
{{ end }}
|
||||
<style>
|
||||
body,
|
||||
html {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.centered-div {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lds-roller,
|
||||
.lds-roller div,
|
||||
.lds-roller div:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.lds-roller {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.lds-roller div {
|
||||
animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
transform-origin: 40px 40px;
|
||||
}
|
||||
|
||||
.lds-roller div:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 7.2px;
|
||||
height: 7.2px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
margin: -3.6px 0 0 -3.6px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(1) {
|
||||
animation-delay: -0.036s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(1):after {
|
||||
top: 62.62742px;
|
||||
left: 62.62742px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(2) {
|
||||
animation-delay: -0.072s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(2):after {
|
||||
top: 67.71281px;
|
||||
left: 56px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(3) {
|
||||
animation-delay: -0.108s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(3):after {
|
||||
top: 70.90963px;
|
||||
left: 48.28221px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(4) {
|
||||
animation-delay: -0.144s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(4):after {
|
||||
top: 72px;
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(5) {
|
||||
animation-delay: -0.18s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(5):after {
|
||||
top: 70.90963px;
|
||||
left: 31.71779px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(6) {
|
||||
animation-delay: -0.216s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(6):after {
|
||||
top: 67.71281px;
|
||||
left: 24px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(7) {
|
||||
animation-delay: -0.252s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(7):after {
|
||||
top: 62.62742px;
|
||||
left: 17.37258px;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(8) {
|
||||
animation-delay: -0.288s;
|
||||
}
|
||||
|
||||
.lds-roller div:nth-child(8):after {
|
||||
top: 56px;
|
||||
left: 12.28719px;
|
||||
}
|
||||
|
||||
@keyframes lds-roller {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body id="top">
|
||||
<main>
|
||||
<center>
|
||||
<h1 id="title" class=".centered-div">{{ .Title }}</h1>
|
||||
</center>
|
||||
|
||||
<div class="centered-div">
|
||||
<img
|
||||
id="image"
|
||||
style="width:100%;max-width:256px;"
|
||||
src="{{ .Path }}/embed/assets/static/logo.png?cacheBust={{ .Random }}"
|
||||
/>
|
||||
{{if .Challenge }}
|
||||
<p id="status">Loading challenge <em>{{ .Challenge }}</em>...</p>
|
||||
<script async type="module" src="{{ .Path }}/challenge/{{ .Challenge }}/challenge.mjs?cacheBust={{ .Random }}"></script>
|
||||
{{else if .Error}}
|
||||
<p id="status">Error: {{ .Error }}</p>
|
||||
{{else}}
|
||||
<p id="status">Loading...</p>
|
||||
{{end}}
|
||||
{{if not .HideSpinner }}
|
||||
<div id="spinner" class="lds-roller">
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
{{end}}
|
||||
<details>
|
||||
<summary>Why am I seeing this?</summary>
|
||||
<p>You are seeing this because the administrator of this website has set up <a href="https://git.gammaspectra.live/git/go-away">go-away</a> to protect the server against the scourge of <a href="https://thelibre.news/foss-infrastructure-is-under-attack-by-ai-companies/">AI companies aggressively scraping websites</a>. This can and does cause downtime for the websites, which makes their resources inaccessible for everyone.</p>
|
||||
<p>Please note that some challenges requires the use of modern JavaScript features and some plugins may will disable. Please disable such plugins for this domain (for example, JShelter).</p>
|
||||
<p>If you have any issues contact the administrator and provide this request id: <em>{{ .Id }}</em></p>
|
||||
</details>
|
||||
<noscript>
|
||||
<p>
|
||||
Sadly, you may need to enable JavaScript to get past this challenge. This is required because AI companies have changed
|
||||
the social contract around how website hosting works.
|
||||
</p>
|
||||
</noscript>
|
||||
<div id="testarea"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<footer>
|
||||
<center>
|
||||
<p>
|
||||
Protected by <a href="https://git.gammaspectra.live/git/go-away">go-away</a> :: Request Id <em>{{ .Id }}</em>
|
||||
</p>
|
||||
</center>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
101
embed/templates/challenge-forgejo.gohtml
Normal file
101
embed/templates/challenge-forgejo.gohtml
Normal file
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
{{$theme := "forgejo-dark"}}
|
||||
{{ if .Theme }}
|
||||
{{$theme = .Theme}}
|
||||
{{ end }}
|
||||
<html lang="en-US" data-theme="{{ $theme }}">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>{{ .Title }}</title>
|
||||
<meta name="referrer" content="no-referrer">
|
||||
|
||||
{{ range $key, $value := .Meta }}
|
||||
{{ if eq $key "refresh"}}
|
||||
<meta http-equiv="{{ $key }}" content="{{ $value }}"/>
|
||||
{{else}}
|
||||
<meta name="{{ $key }}" content="{{ $value }}"/>
|
||||
{{end}}
|
||||
{{ end }}
|
||||
{{ range .Tags }}
|
||||
{{ . }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
<link rel="icon" href="/assets/img/favicon.svg" type="image/svg+xml">
|
||||
<link rel="alternate icon" href="/assets/img/favicon.png" type="image/png">
|
||||
|
||||
<noscript>
|
||||
<style>
|
||||
.dropdown:hover > .menu { display: block; }
|
||||
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; }
|
||||
</style>
|
||||
</noscript>
|
||||
|
||||
<link rel="stylesheet" href="/assets/css/index.css">
|
||||
<link rel="stylesheet" href="/assets/css/theme-{{$theme}}.css">
|
||||
|
||||
|
||||
</head>
|
||||
<body hx-swap="outerHTML" hx-ext="morph" hx-push-url="false">
|
||||
|
||||
|
||||
<div class="full height">
|
||||
<nav id="navbar" aria-label="Navigation bar">
|
||||
<div class="navbar-left ui secondary menu">
|
||||
<a class="item" id="navbar-logo" href="/" aria-label="Home">
|
||||
<img width="30" height="30" src="/assets/img/logo.svg" alt="Logo" aria-hidden="true">
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="home">
|
||||
<div class="ui stackable middle very relaxed page grid">
|
||||
<div class="sixteen wide center aligned centered column">
|
||||
<div>
|
||||
<img class="logo" id="image" src="/assets/img/logo.png" />
|
||||
</div>
|
||||
<div class="hero">
|
||||
<h2 class="ui icon header title" id="title">
|
||||
{{ .Title }}
|
||||
</h2>
|
||||
|
||||
{{if .Challenge }}
|
||||
<h3 id="status">Loading challenge <em>{{ .Challenge }}</em>...</h3>
|
||||
<script async type="module" src="{{ .Path }}/challenge/{{ .Challenge }}/challenge.mjs?cacheBust={{ .Random }}"></script>
|
||||
{{else if .Error}}
|
||||
<h3 id="status">Error: {{ .Error }}</h3>
|
||||
{{else}}
|
||||
<h3 id="status">Loading...</h3>
|
||||
{{end}}
|
||||
<div id="spinner"></div>
|
||||
|
||||
<details>
|
||||
<summary>Why am I seeing this?</summary>
|
||||
<p>You are seeing this because the administrator of this website has set up <a href="https://git.gammaspectra.live/git/go-away">go-away</a> to protect the server against the scourge of <a href="https://thelibre.news/foss-infrastructure-is-under-attack-by-ai-companies/">AI companies aggressively scraping websites</a>. This can and does cause downtime for the websites, which makes their resources inaccessible for everyone.</p>
|
||||
<p>Please note that some challenges requires the use of modern JavaScript features and some plugins may will disable. Please disable such plugins for this domain (for example, JShelter).</p>
|
||||
<p>If you have any issues contact the administrator and provide the request id: <em>{{ .Id }}</em></p>
|
||||
</details>
|
||||
|
||||
|
||||
<div id="testarea"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<footer class="page-footer" role="group" aria-label="">
|
||||
<div class="left-links" role="contentinfo" aria-label="">
|
||||
Protected by <a href="https://git.gammaspectra.live/git/go-away">go-away</a> :: Request Id <em>{{ .Id }}</em>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
69
embed/templates/challenge.mjs
Normal file
69
embed/templates/challenge.mjs
Normal file
@@ -0,0 +1,69 @@
|
||||
import {setup, challenge} from "{{ .ChallengeScript }}";
|
||||
|
||||
|
||||
// from Xeact
|
||||
const u = (url = "", params = {}) => {
|
||||
let result = new URL(url, window.location.href);
|
||||
Object.entries(params).forEach((kv) => {
|
||||
let [k, v] = kv;
|
||||
result.searchParams.set(k, v);
|
||||
});
|
||||
return result.toString();
|
||||
};
|
||||
|
||||
(async () => {
|
||||
const status = document.getElementById('status');
|
||||
const title = document.getElementById('title');
|
||||
const spinner = document.getElementById('spinner');
|
||||
|
||||
status.innerText = 'Starting challenge {{ .Challenge }}...';
|
||||
|
||||
try {
|
||||
const info = await setup({
|
||||
Path: "{{ .Path }}",
|
||||
Parameters: "{{ .Parameters }}"
|
||||
});
|
||||
|
||||
if (info != "") {
|
||||
status.innerText = 'Calculating... ' + info
|
||||
} else {
|
||||
status.innerText = 'Calculating...';
|
||||
}
|
||||
} catch (err) {
|
||||
title.innerHTML = "Oh no!";
|
||||
status.innerHTML = `Failed to initialize: ${err.message}`;
|
||||
spinner.innerHTML = "";
|
||||
spinner.style.display = "none";
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const t0 = Date.now();
|
||||
const { result, info } = await challenge();
|
||||
const t1 = Date.now();
|
||||
console.log({ result, info });
|
||||
|
||||
title.innerHTML = "Challenge success!";
|
||||
if (info != "") {
|
||||
status.innerHTML = `Done! Took ${t1 - t0}ms, ${info}`;
|
||||
} else {
|
||||
status.innerHTML = `Done! Took ${t1 - t0}ms`;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const redir = window.location.href;
|
||||
window.location.href = u("{{ .Path }}/verify-challenge", {
|
||||
result: result,
|
||||
redirect: redir,
|
||||
requestId: "{{ .Id }}",
|
||||
elapsedTime: t1 - t0,
|
||||
});
|
||||
}, 500);
|
||||
} catch (err) {
|
||||
title.innerHTML = "Oh no!";
|
||||
status.innerHTML = `Failed to challenge: ${err.message}`;
|
||||
spinner.innerHTML = "";
|
||||
spinner.style.display = "none";
|
||||
}
|
||||
})();
|
Reference in New Issue
Block a user