mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-05-09 16:42:52 +00:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 082a57a1a0 | |||
| e42a328843 | |||
| c4b26e5a75 | |||
| 1342539a41 | |||
| bd6f654e1f | |||
| d2c3a326af | |||
| c2ed62f51d | |||
| 11c4adc6b4 | |||
| edbfd180b8 | |||
| efde4f0dc7 | |||
| 24857f430f |
@@ -31,3 +31,6 @@ Stargate
|
|||||||
FFXIV
|
FFXIV
|
||||||
uvensys
|
uvensys
|
||||||
de
|
de
|
||||||
|
resourced
|
||||||
|
envoyproxy
|
||||||
|
unipromos
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
|
|
||||||
- name: Apply k8s manifests to limsa lominsa
|
- name: Apply k8s manifests to limsa lominsa
|
||||||
uses: actions-hub/kubectl@5ada4e2c02eacc03978c2437e95c8b0f979a9619 # v1.35.2
|
uses: actions-hub/kubectl@934aaa4354bbbc3d2176ae8d7cae92d515032dff # v1.35.3
|
||||||
env:
|
env:
|
||||||
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
|
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
|
||||||
with:
|
with:
|
||||||
args: apply -k docs/manifest
|
args: apply -k docs/manifest
|
||||||
|
|
||||||
- name: Apply k8s manifests to limsa lominsa
|
- name: Apply k8s manifests to limsa lominsa
|
||||||
uses: actions-hub/kubectl@5ada4e2c02eacc03978c2437e95c8b0f979a9619 # v1.35.2
|
uses: actions-hub/kubectl@934aaa4354bbbc3d2176ae8d7cae92d515032dff # v1.35.3
|
||||||
env:
|
env:
|
||||||
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
|
KUBE_CONFIG: ${{ secrets.LIMSA_LOMINSA_KUBECONFIG }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
+8
-2
@@ -17,6 +17,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"net/http/pprof"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
@@ -275,7 +276,7 @@ func main() {
|
|||||||
|
|
||||||
internal.SetHealth("anubis", healthv1.HealthCheckResponse_NOT_SERVING)
|
internal.SetHealth("anubis", healthv1.HealthCheckResponse_NOT_SERVING)
|
||||||
|
|
||||||
lg := internal.InitSlog(*slogLevel, os.Stderr)
|
lg := internal.InitSlog(*slogLevel, os.Stderr, false)
|
||||||
lg.Info("starting up Anubis")
|
lg.Info("starting up Anubis")
|
||||||
|
|
||||||
if *healthcheck {
|
if *healthcheck {
|
||||||
@@ -427,7 +428,7 @@ func main() {
|
|||||||
redirectDomainsList = append(redirectDomainsList, strings.TrimSpace(domain))
|
redirectDomainsList = append(redirectDomainsList, strings.TrimSpace(domain))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lg.Warn("REDIRECT_DOMAINS is not set, Anubis will only redirect to the same domain a request is coming from, see https://anubis.techaro.lol/docs/admin/configuration/redirect-domains")
|
lg.Warn("REDIRECT_DOMAINS is not set, Anubis will redirect to any domain, see https://anubis.techaro.lol/docs/admin/configuration/redirect-domains")
|
||||||
}
|
}
|
||||||
|
|
||||||
anubis.CookieName = *cookiePrefix + "-auth"
|
anubis.CookieName = *cookiePrefix + "-auth"
|
||||||
@@ -522,6 +523,11 @@ func metricsServer(ctx context.Context, lg slog.Logger, done func()) {
|
|||||||
defer done()
|
defer done()
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("GET /debug/pprof/", pprof.Index)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/cmdline", pprof.Cmdline)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/profile", pprof.Profile)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/symbol", pprof.Symbol)
|
||||||
|
mux.HandleFunc("GET /debug/pprof/trace", pprof.Trace)
|
||||||
mux.Handle("/metrics", promhttp.Handler())
|
mux.Handle("/metrics", promhttp.Handler())
|
||||||
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
st, ok := internal.GetHealth("anubis")
|
st, ok := internal.GetHealth("anubis")
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func main() {
|
|||||||
flagenv.Parse()
|
flagenv.Parse()
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
slog.SetDefault(internal.InitSlog(*slogLevel, os.Stderr))
|
slog.SetDefault(internal.InitSlog(*slogLevel, os.Stderr, false))
|
||||||
|
|
||||||
koDockerRepo := strings.TrimSuffix(*dockerRepo, "/"+filepath.Base(*dockerRepo))
|
koDockerRepo := strings.TrimSuffix(*dockerRepo, "/"+filepath.Base(*dockerRepo))
|
||||||
|
|
||||||
@@ -159,8 +159,8 @@ func run(command string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setOutput(key, val string) {
|
func setOutput(key, val string) {
|
||||||
github_output := os.Getenv("GITHUB_OUTPUT")
|
github_output := os.Getenv("GITHUB_OUTPUT")
|
||||||
f, _ := os.OpenFile(github_output, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
f, _ := os.OpenFile(github_output, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||||
fmt.Fprintf(f, "%s=%s\n", key, val)
|
fmt.Fprintf(f, "%s=%s\n", key, val)
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,4 +8,5 @@
|
|||||||
- import: (data)/crawlers/marginalia.yaml
|
- import: (data)/crawlers/marginalia.yaml
|
||||||
- import: (data)/crawlers/mojeekbot.yaml
|
- import: (data)/crawlers/mojeekbot.yaml
|
||||||
- import: (data)/crawlers/commoncrawl.yaml
|
- import: (data)/crawlers/commoncrawl.yaml
|
||||||
|
- import: (data)/crawlers/wikimedia-citoid.yaml
|
||||||
- import: (data)/crawlers/yandexbot.yaml
|
- import: (data)/crawlers/yandexbot.yaml
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Wikimedia Foundation citation services
|
||||||
|
# https://www.mediawiki.org/wiki/Citoid
|
||||||
|
|
||||||
|
- name: wikimedia-citoid
|
||||||
|
user_agent_regex: "Citoid/WMF"
|
||||||
|
action: ALLOW
|
||||||
|
remote_addresses: [
|
||||||
|
"208.80.152.0/22",
|
||||||
|
"2620:0:860::/46",
|
||||||
|
]
|
||||||
|
|
||||||
|
- name: wikimedia-zotero-translation-server
|
||||||
|
user_agent_regex: "ZoteroTranslationServer/WMF"
|
||||||
|
action: ALLOW
|
||||||
|
remote_addresses: [
|
||||||
|
"208.80.152.0/22",
|
||||||
|
"2620:0:860::/46",
|
||||||
|
]
|
||||||
@@ -11,13 +11,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Expose [pprof endpoints](https://pkg.go.dev/net/http/pprof) on the metrics listener to enable profiling Anubis in production.
|
||||||
- fix: prevent nil pointer panic in challenge validation when threshold rules match during PassChallenge (#1463)
|
- fix: prevent nil pointer panic in challenge validation when threshold rules match during PassChallenge (#1463)
|
||||||
- Instruct reverse proxies to not cache error pages.
|
- Instruct reverse proxies to not cache error pages.
|
||||||
- Fixed mixed tab/space indentation in Caddy documentation code block
|
- Fixed mixed tab/space indentation in Caddy documentation code block
|
||||||
- Rewrite main proof of work challenge to use Preact instead of Vanilla.js ([#1149](https://github.com/TecharoHQ/anubis/issues/1149))
|
- Improve error messages and fix broken REDIRECT_DOMAINS link in docs ([#1193](https://github.com/TecharoHQ/anubis/issues/1193))
|
||||||
|
- Add Bulgarian locale ([#1394](https://github.com/TecharoHQ/anubis/pull/1394))
|
||||||
|
- Add option to hide source code origin of log lines in [logging configuration](./admin/policies.mdx#logging-management)
|
||||||
|
|
||||||
<!-- This changes the project to: -->
|
<!-- This changes the project to: -->
|
||||||
|
|
||||||
|
- Fix CEL internal errors when iterating `headers`/`query` map wrappers by implementing map iterators for `HTTPHeaders` and `URLValues` ([#1465](https://github.com/TecharoHQ/anubis/pull/1465)).
|
||||||
|
|
||||||
## v1.25.0: Necron
|
## v1.25.0: Necron
|
||||||
|
|
||||||
Hey all,
|
Hey all,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ Anubis uses these environment variables for configuration:
|
|||||||
| `OVERLAY_FOLDER` | unset | <EO /> If set, treat the given path as an [overlay folder](./botstopper.mdx#custom-images-and-css), allowing you to customize CSS, fonts, images, and add other assets to BotStopper deployments. |
|
| `OVERLAY_FOLDER` | unset | <EO /> If set, treat the given path as an [overlay folder](./botstopper.mdx#custom-images-and-css), allowing you to customize CSS, fonts, images, and add other assets to BotStopper deployments. |
|
||||||
| `POLICY_FNAME` | unset | The file containing [bot policy configuration](./policies.mdx). See the bot policy documentation for more details. If unset, the default bot policy configuration is used. |
|
| `POLICY_FNAME` | unset | The file containing [bot policy configuration](./policies.mdx). See the bot policy documentation for more details. If unset, the default bot policy configuration is used. |
|
||||||
| `PUBLIC_URL` | unset | The externally accessible URL for this Anubis instance, used for constructing redirect URLs (e.g., for Traefik forwardAuth). Leave it unset when Anubis terminates traffic directly (sidecar/standalone deployments) or redirect building will fail with `redir=null`. |
|
| `PUBLIC_URL` | unset | The externally accessible URL for this Anubis instance, used for constructing redirect URLs (e.g., for Traefik forwardAuth). Leave it unset when Anubis terminates traffic directly (sidecar/standalone deployments) or redirect building will fail with `redir=null`. |
|
||||||
| `REDIRECT_DOMAINS` | unset | Comma-separated list of domain names that Anubis should allow redirects to when passing a challenge. See [Redirect Domain Configuration](./configuration/redirect-domains) for more details. |
|
| `REDIRECT_DOMAINS` | unset | Comma-separated list of domain names that Anubis should allow redirects to when passing a challenge. See [Redirect Domain Configuration](./configuration/redirect-domains.mdx) for more details. |
|
||||||
| `SERVE_ROBOTS_TXT` | `false` | If set `true`, Anubis will serve a default `robots.txt` file that disallows all known AI scrapers by name and then additionally disallows every scraper. This is useful if facts and circumstances make it difficult to change the underlying service to serve such a `robots.txt` file. |
|
| `SERVE_ROBOTS_TXT` | `false` | If set `true`, Anubis will serve a default `robots.txt` file that disallows all known AI scrapers by name and then additionally disallows every scraper. This is useful if facts and circumstances make it difficult to change the underlying service to serve such a `robots.txt` file. |
|
||||||
| `SLOG_LEVEL` | `INFO` | The log level for structured logging. Valid values are `DEBUG`, `INFO`, `WARN`, and `ERROR`. Set to `DEBUG` to see all requests, evaluations, and detailed diagnostic information. |
|
| `SLOG_LEVEL` | `INFO` | The log level for structured logging. Valid values are `DEBUG`, `INFO`, `WARN`, and `ERROR`. Set to `DEBUG` to see all requests, evaluations, and detailed diagnostic information. |
|
||||||
| `SOCKET_MODE` | `0770` | _Only used when at least one of the `*_BIND_NETWORK` variables are set to `unix`._ The socket mode (permissions) for Unix domain sockets. |
|
| `SOCKET_MODE` | `0770` | _Only used when at least one of the `*_BIND_NETWORK` variables are set to `unix`._ The socket mode (permissions) for Unix domain sockets. |
|
||||||
|
|||||||
@@ -339,6 +339,7 @@ Anubis exposes the following logging settings in the policy file:
|
|||||||
| `level` | [log level](#log-levels) | `info` | The logging level threshold. Any logs that are at or above this threshold will be drained to the sink. Any other logs will be discarded. |
|
| `level` | [log level](#log-levels) | `info` | The logging level threshold. Any logs that are at or above this threshold will be drained to the sink. Any other logs will be discarded. |
|
||||||
| `sink` | string | `stdio`, `file` | The sink where the logs drain to as they are being recorded in Anubis. |
|
| `sink` | string | `stdio`, `file` | The sink where the logs drain to as they are being recorded in Anubis. |
|
||||||
| `parameters` | object | | Parameters for the given logging sink. This will vary based on the logging sink of choice. See below for more information. |
|
| `parameters` | object | | Parameters for the given logging sink. This will vary based on the logging sink of choice. See below for more information. |
|
||||||
|
| `hideSource` | boolean | `false` | If set, hide the details of which line of code triggered a log line. Setting this to `true` may make getting support more difficult. |
|
||||||
|
|
||||||
Anubis supports the following logging sinks:
|
Anubis supports the following logging sinks:
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,13 @@ If you use a browser extension such as [JShelter](https://jshelter.org/), you wi
|
|||||||
## Does Anubis mine Bitcoin?
|
## Does Anubis mine Bitcoin?
|
||||||
|
|
||||||
No. Anubis does not mine Bitcoin or any other cryptocurrency.
|
No. Anubis does not mine Bitcoin or any other cryptocurrency.
|
||||||
|
|
||||||
|
## I disabled Just-in-time compilation in my browser. Why is Anubis slow?
|
||||||
|
|
||||||
|
Anubis proof-of-work checks run an open source JavaScript program in your browser. These checks do a lot of complicated math and aim to be done quickly, so the execution speed depends on [Just-in-time (JIT) compilation](https://en.wikipedia.org/wiki/Just-in-time_compilation). JIT compiles JavaScript from the Internet into native machine code at runtime. The code produced by the JIT engine is almost as good as if it was written in a native programming language and compiled for your computer in particular. Without JIT, all JavaScript programs on every website you visit run through a slow interpreter.
|
||||||
|
|
||||||
|
This interpreter is much slower than native code because it has to translate each low level JavaScript operation into many dozens of calls to execute. This means that using the interpreter incurs a massive performance hit by its very nature; it takes longer to add numbers than if the CPU just added the numbers directly.
|
||||||
|
|
||||||
|
Some users choose to disable JIT as a hardening measure against theoretical browser exploits. This is a reasonable choice if you face targeted attacks from well-resourced adversaries (such as nation-state actors), but it comes with real performance costs.
|
||||||
|
|
||||||
|
If you've disabled JIT and find Anubis checks slow, re-enabling JIT is the fix. There is no way for Anubis to work around this on our end.
|
||||||
|
|||||||
+9
-3
@@ -10,7 +10,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitSlog(level string, sink io.Writer) *slog.Logger {
|
func InitSlog(level string, sink io.Writer, hideSource bool) *slog.Logger {
|
||||||
var programLevel slog.Level
|
var programLevel slog.Level
|
||||||
if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
|
if err := (&programLevel).UnmarshalText([]byte(level)); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
|
fmt.Fprintf(os.Stderr, "invalid log level %s: %v, using info\n", level, err)
|
||||||
@@ -20,10 +20,16 @@ func InitSlog(level string, sink io.Writer) *slog.Logger {
|
|||||||
leveler := &slog.LevelVar{}
|
leveler := &slog.LevelVar{}
|
||||||
leveler.Set(programLevel)
|
leveler.Set(programLevel)
|
||||||
|
|
||||||
h := slog.NewJSONHandler(sink, &slog.HandlerOptions{
|
opts := &slog.HandlerOptions{
|
||||||
AddSource: true,
|
AddSource: true,
|
||||||
Level: leveler,
|
Level: leveler,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if hideSource {
|
||||||
|
opts.AddSource = false
|
||||||
|
}
|
||||||
|
|
||||||
|
h := slog.NewJSONHandler(sink, opts)
|
||||||
result := slog.New(h)
|
result := slog.New(h)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -141,7 +141,7 @@ func (s *Server) issueChallenge(ctx context.Context, r *http.Request, lg *slog.L
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lg.Info("new challenge issued", "challenge", id.String(), "method", chall.Method)
|
lg.Info("new challenge issued", "challenge", id.String())
|
||||||
|
|
||||||
return &chall, err
|
return &chall, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import (
|
|||||||
|
|
||||||
templ page(localizer *localization.SimpleLocalizer) {
|
templ page(localizer *localization.SimpleLocalizer) {
|
||||||
<div class="centered-div">
|
<div class="centered-div">
|
||||||
<img style="display:none;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + anubis.Version }/>
|
<img id="image" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version }/>
|
||||||
<div id="app">
|
<img style="display:none;" style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + anubis.Version }/>
|
||||||
<img style="width:100%;max-width:256px;" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version }/>
|
<p id="status">{ localizer.T("loading") }</p>
|
||||||
<p id="status">{ localizer.T("loading") }</p>
|
|
||||||
</div>
|
|
||||||
<script async type="module" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.Version }></script>
|
<script async type="module" src={ anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.Version }></script>
|
||||||
|
<div id="progress" role="progressbar" aria-labelledby="status">
|
||||||
|
<div class="bar-inner"></div>
|
||||||
|
</div>
|
||||||
<details>
|
<details>
|
||||||
if anubis.UseSimplifiedExplanation {
|
if anubis.UseSimplifiedExplanation {
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
+16
-16
@@ -34,27 +34,27 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"centered-div\"><img style=\"display:none;\" src=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"centered-div\"><img id=\"image\" style=\"width:100%;max-width:256px;\" src=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var2 string
|
var templ_7745c5c3_Var2 string
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + anubis.Version)
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 10, Col: 138}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 10, Col: 165}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"><div id=\"app\"><img style=\"width:100%;max-width:256px;\" src=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"> <img style=\"display:none;\" style=\"width:100%;max-width:256px;\" src=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/pensive.webp?cacheBuster=" + anubis.Version)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/img/happy.webp?cacheBuster=" + anubis.Version)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 12, Col: 155}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 11, Col: 174}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -67,26 +67,26 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("loading"))
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("loading"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 13, Col: 42}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 12, Col: 41}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div><script async type=\"module\" src=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p><script async type=\"module\" src=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.Version)
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(anubis.BasePrefix + "/.within.website/x/cmd/anubis/static/js/main.mjs?cacheBuster=" + anubis.Version)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 15, Col: 136}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 13, Col: 136}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\"></script><details>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\"></script><div id=\"progress\" role=\"progressbar\" aria-labelledby=\"status\"><div class=\"bar-inner\"></div></div><details>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var6 string
|
var templ_7745c5c3_Var6 string
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("simplified_explanation"))
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("simplified_explanation"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 19, Col: 44}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 20, Col: 44}
|
||||||
}
|
}
|
||||||
_, 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 {
|
||||||
@@ -116,7 +116,7 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("ai_companies_explanation"))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("ai_companies_explanation"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 23, Col: 46}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 24, Col: 46}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -129,7 +129,7 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("anubis_compromise"))
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("anubis_compromise"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 26, Col: 39}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 27, Col: 39}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -142,7 +142,7 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("hack_purpose"))
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("hack_purpose"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 29, Col: 34}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 30, Col: 34}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -155,7 +155,7 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var10 string
|
var templ_7745c5c3_Var10 string
|
||||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("jshelter_note"))
|
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("jshelter_note"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 32, Col: 35}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 33, Col: 35}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -173,7 +173,7 @@ func page(localizer *localization.SimpleLocalizer) templ.Component {
|
|||||||
var templ_7745c5c3_Var11 string
|
var templ_7745c5c3_Var11 string
|
||||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("javascript_required"))
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(localizer.T("javascript_required"))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 38, Col: 40}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `proofofwork.templ`, Line: 39, Col: 40}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
ErrNoBotRulesDefined = errors.New("config: must define at least one (1) bot rule")
|
ErrNoBotRulesDefined = errors.New("config: must define at least one (1) bot rule")
|
||||||
ErrBotMustHaveName = errors.New("config.Bot: must set name")
|
ErrBotMustHaveName = errors.New("config.Bot: must set name")
|
||||||
ErrBotMustHaveUserAgentOrPath = errors.New("config.Bot: must set either user_agent_regex, path_regex, headers_regex, or remote_addresses")
|
ErrBotMustHaveUserAgentOrPath = errors.New("config.Bot: must set one of user_agent_regex, path_regex, headers_regex, remote_addresses, expression, or Thoth keyword")
|
||||||
ErrBotMustHaveUserAgentOrPathNotBoth = errors.New("config.Bot: must set either user_agent_regex, path_regex, and not both")
|
ErrBotMustHaveUserAgentOrPathNotBoth = errors.New("config.Bot: must set either user_agent_regex, path_regex, and not both")
|
||||||
ErrUnknownAction = errors.New("config.Bot: unknown action")
|
ErrUnknownAction = errors.New("config.Bot: unknown action")
|
||||||
ErrInvalidUserAgentRegex = errors.New("config.Bot: invalid user agent regex")
|
ErrInvalidUserAgentRegex = errors.New("config.Bot: invalid user agent regex")
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ type Logging struct {
|
|||||||
Sink string `json:"sink"` // Logging sink, either "stdio" or "file"
|
Sink string `json:"sink"` // Logging sink, either "stdio" or "file"
|
||||||
Level *slog.Level `json:"level"` // Log level, if set supersedes the level in flags
|
Level *slog.Level `json:"level"` // Log level, if set supersedes the level in flags
|
||||||
Parameters *LoggingFileConfig `json:"parameters"` // Logging parameters, to be dynamic in the future
|
Parameters *LoggingFileConfig `json:"parameters"` // Logging parameters, to be dynamic in the future
|
||||||
|
HideSource bool `json:"hideSource"` // If true, hide the `source` field in log lines
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
"loading": "Зареждане...",
|
||||||
|
"why_am_i_seeing": "Защо виждам това?",
|
||||||
|
"protected_by": "Защитено от",
|
||||||
|
"protected_from": "От",
|
||||||
|
"made_with": "Направено с ❤️ в 🇨🇦",
|
||||||
|
"mascot_design": "Дизайн на талисмана от",
|
||||||
|
"ai_companies_explanation": "Виждате това, защото администраторът на този уебсайт е kонфигурирал Anubis, за да защити сървъра от агресивното събиране на данни от компании, занимаващи се с изкуствен интелект. Това може и причинява прекъсвания на уебсайтовете, което прави техните ресурси недостъпни за всички.",
|
||||||
|
"anubis_compromise": "Anubis е компромис. Anubis използва схема за ддоказателство-за-работа по подобие на Hashcash, предложена схема за доказателство-за-работа за намаляване на спама в имейлите. Идеята е, че при индивидуални мащаби допълнителното натоварване е пренебрежимо, но при масов ниво на събиране на данни то се натрупва и прави събирането на данни много по-скъпо.",
|
||||||
|
"hack_purpose": "В крайна сметка, това е временно решение, за да се отдели повече време за идентифициране и разпознаване на безглави браузъри (например чрез това как те рендират шрифтовете), така че страницата за доказателство-за-работа да не се налага да се показва на потребители, които е по-вероятно да са легитимни.",
|
||||||
|
"simplified_explanation": "Това е мярка срещу ботове и злонамерени заявки, подобна на CAPTCHA. Вместо да трябва да правите нещо сами, браузърът ви получава задача за изчисление, която трябва да реши, за да се увери, че е валиден клиент. Тази концепция се нарича схема доказателство-за-работа. Задачата се изчислява за няколко секунди и ви се дава достъп до уебсайта. Благодаря ви за разбирането и търпението.",
|
||||||
|
"jshelter_note": "Моля, имайте предвид, че Anubis изисква използването на модерни функции на JavaScript, сред които и като JShelter ще деактивират. Моля, деактивирайте JShelter или други подобни добавки за този домейн.",
|
||||||
|
"version_info": "Този уебсайт използва версия на Anubis",
|
||||||
|
"try_again": "Опитайте отново",
|
||||||
|
"go_home": "Отидете на началната страница",
|
||||||
|
"contact_webmaster": "или ако смятате, че не трябва да бъдете блокирани, моля свържете се с уебмастъра на",
|
||||||
|
"connection_security": "Моля, изчакайте, докато се уверим в сигурността на връзката ви",
|
||||||
|
"javascript_required": "За съжаление, трябва да включите JavaScript, за да минете през това предизвикателство. Това е необходимо, защото компаниите за изкуствен интелект промениха социалния договор около начина на хостинг на уебсайтове. Решение без JavaScript е в процес на разработка.",
|
||||||
|
"benchmark_requires_js": "За да използвате инструмента за тестване, е необходимо да включите JavaScript.",
|
||||||
|
"difficulty": "Трудност:",
|
||||||
|
"algorithm": "Алгоритъм:",
|
||||||
|
"compare": "Сравни:",
|
||||||
|
"time": "Време",
|
||||||
|
"iters": "Итерации",
|
||||||
|
"time_a": "Време А",
|
||||||
|
"iters_a": "Итерации А",
|
||||||
|
"time_b": "Време Б",
|
||||||
|
"iters_b": "Итерации Б",
|
||||||
|
"static_check_endpoint": "Това е просто краен пункт за проверка, който да използва обратният ви прокси.",
|
||||||
|
"authorization_required": "Изисква се авторизация",
|
||||||
|
"cookies_disabled": "Браузърът ви е настроен да деактивира бисквитките. Anubis изисква бисквитки за законния интерес да се увери, че сте валиден клиент. Моля, включете бисквитките за този домейн",
|
||||||
|
"access_denied": "Достъпът е отказан: код на грешка",
|
||||||
|
"dronebl_entry": "DroneBL докладва запис",
|
||||||
|
"see_dronebl_lookup": "вижте",
|
||||||
|
"internal_server_error": "Вътрешна сървърна грешка: администраторът е грешно конфигурирал Anubis. Моля, свържете се с администратора и ги помолете да проверят логовете около",
|
||||||
|
"invalid_redirect": "Невалидно пренасочване",
|
||||||
|
"redirect_not_parseable": "URL адресът за пренасочване не може да бъде разпознат",
|
||||||
|
"redirect_domain_not_allowed": "Домейнът за пренасочване не е позволен",
|
||||||
|
"missing_required_forwarded_headers": "Липсват необходимите X-Forwarded-* заглавни части",
|
||||||
|
"failed_to_sign_jwt": "неуспешно подписване на JWT",
|
||||||
|
"invalid_invocation": "Невалидно извикване на MakeChallenge",
|
||||||
|
"client_error_browser": "Крешка в клиента: Моля, уверете се, че браузърът ви е актуализиран и опитайте отново по-късно.",
|
||||||
|
"oh_noes": "О, не!",
|
||||||
|
"benchmarking_anubis": "Тестване на Anubis!",
|
||||||
|
"you_are_not_a_bot": "Ти не си бот!",
|
||||||
|
"making_sure_not_bot": "Уверяваме се, че не си бот!",
|
||||||
|
"celphase": "CELPHASE",
|
||||||
|
"js_web_crypto_error": "Браузърът ви няма функциониращ web.crypto елемент. Гледате ли това през сигурен контекст?",
|
||||||
|
"js_web_workers_error": "Браузърът ви не поддържа уеб работници (Anubis използва това, за да избегне замръзване на браузъра ви). Имате ли инсталирана добавка като JShelter?",
|
||||||
|
"js_cookies_error": "Браузърът ви не съхранява бисквитки. Anubis използва бисквитки, за да определи които клиенти са преминали задачите, като съхранява подписан токен в бисквитка. Моля, включете съхраняването на бисквитки за този домейн. Имената на бисквитките, съхранени от Anubis, могат да се променят без предварително уведомление. Имената и стойностите на бисквитките не са част от публичния API.",
|
||||||
|
"js_context_not_secure": "Вашият контекст не е сигурен!",
|
||||||
|
"js_context_not_secure_msg": "Опитайте да се свържете чрез HTTPS или уведомете администратора да kонфигурира HTTPS. За повече информация вижте MDN.",
|
||||||
|
"js_calculating": "Изчисляване...",
|
||||||
|
"js_missing_feature": "Липсваща функция",
|
||||||
|
"js_challenge_error": "Грешка при задачата!",
|
||||||
|
"js_challenge_error_msg": "Неуспешно разрешаване на алгоритъма за проверка. Може би искате да презаредите страницата.",
|
||||||
|
"js_calculating_difficulty": "Изчисляване... Трудност:",
|
||||||
|
"js_speed": "Скорост:",
|
||||||
|
"js_verification_longer": "Проверката отнема повече време от очакваното. Моля, не презареждайте страницата.",
|
||||||
|
"js_success": "Успех!",
|
||||||
|
"js_done_took": "Готово! Отне",
|
||||||
|
"js_iterations": "итерации",
|
||||||
|
"js_finished_reading": "Приключих с четенето, продължете →",
|
||||||
|
"js_calculation_error": "Грешка при изчислението!",
|
||||||
|
"js_calculation_error_msg": "Неуспешно изчисление на задачата:"
|
||||||
|
}
|
||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_finished_reading": "Čtení dokončeno, pokračovat →",
|
"js_finished_reading": "Čtení dokončeno, pokračovat →",
|
||||||
"js_calculation_error": "Chyba výpočtu!",
|
"js_calculation_error": "Chyba výpočtu!",
|
||||||
"js_calculation_error_msg": "Nepodařilo se vypočítat výzvu:",
|
"js_calculation_error_msg": "Nepodařilo se vypočítat výzvu:",
|
||||||
"missing_required_forwarded_headers": "Chybějící požadované hlavičky X-Forwarded-*",
|
"missing_required_forwarded_headers": "Chybějící požadované hlavičky X-Forwarded-*"
|
||||||
"js_challenge_data_missing": "Data pro ověření chybí. Načtěte prosím stránku znovu."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
{
|
{
|
||||||
"loading": "Ladevorgang...",
|
"loading": "Wird geladen …",
|
||||||
"why_am_i_seeing": "Warum sehe ich diese Seite?",
|
"why_am_i_seeing": "Warum sehe ich diese Seite?",
|
||||||
"protected_by": "Geschützt durch",
|
"protected_by": "Geschützt durch",
|
||||||
"protected_from": "Von",
|
"protected_from": "Von",
|
||||||
"made_with": "Mit ❤️ entwickelt in 🇨🇦",
|
"made_with": "Mit ❤️ entwickelt in 🇨🇦",
|
||||||
"mascot_design": "Maskottchen erstellt von",
|
"mascot_design": "Maskottchen entworfen von",
|
||||||
"ai_companies_explanation": "Diese Seite wird angezeigt, da der Betreiber der Website Anubis eingerichtet hat, um sie vor aggressiven Webcrawlern von KI-Unternehmen zu schützen. Diese können Ausfälle verursachen, wodurch die Website für niemanden erreichbar ist.",
|
"ai_companies_explanation": "Diese Seite wird angezeigt, weil der Betreiber dieser Website Anubis eingerichtet hat, um den Server vor aggressivem Scraping durch KI-Unternehmen zu schützen. Dieses Scraping kann Ausfälle verursachen, wodurch die Website für niemanden erreichbar ist.",
|
||||||
"anubis_compromise": "Anubis stellt einen Kompromiss dar. Es verwendet eine Proof-of-Work-Methode nach dem Hashcash-Prinzip, das ursprünglich zur Bekämpfung von E-Mail-Spam entwickelt wurde. Die Idee dahinter: Für einen einzelnen Besucher ist die Verzögerung vernachlässigbar, aber massenhaftes Scraping wird dadurch aufwändig und teuer.",
|
"anubis_compromise": "Anubis ist ein Kompromiss. Es verwendet ein Proof-of-Work-Verfahren nach dem Vorbild von Hashcash, das ursprünglich zur Reduzierung von E-Mail-Spam entwickelt wurde. Die Idee dahinter ist, dass die zusätzliche Last für einzelne Nutzer vernachlässigbar ist, sich aber auf der Ebene von Massen-Scrapern summiert und das Scraping deutlich teurer macht.",
|
||||||
"hack_purpose": "Letztendlich ist dies eine Übergangslösung, um mehr Zeit für Browser-Fingerprinting und die Identifizierung von Headless-Browsern (z. B. anhand ihrer Schriftwiedergabe) zu gewinnen. So muss die Proof-of-Work-Seite nicht Nutzern angezeigt werden, die sehr wahrscheinlich legitim sind.",
|
"hack_purpose": "Letztlich ist dies eine Übergangslösung, damit mehr Zeit in das Fingerprinting und die Erkennung von Headless-Browsern investiert werden kann (z. B. anhand ihrer Schriftart-Darstellung), sodass die Proof-of-Work-Seite Nutzern, die mit hoher Wahrscheinlichkeit legitim sind, nicht mehr angezeigt werden muss.",
|
||||||
"simplified_explanation": "Dies ist eine Maßnahme gegen Bots und bösartige Anfragen, ähnlich einem CAPTCHA. Anstatt jedoch selbst arbeiten zu müssen, erhält dein Browser eine Rechenaufgabe, um sicherzustellen, dass es sich um einen gültigen Client handelt. Dieses Konzept nennt sich <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Die Aufgabe wird in wenigen Sekunden berechnet und du erhältst Zugriff auf die Website. Danke für deine Geduld.",
|
"simplified_explanation": "Dies ist eine Schutzmaßnahme gegen Bots und schädliche Anfragen, ähnlich einem CAPTCHA. Anstatt selbst eine Aufgabe lösen zu müssen, bekommt dein Browser eine Rechenaufgabe, die er lösen muss, um sicherzustellen, dass es sich um einen gültigen Client handelt. Dieses Konzept nennt sich <a href=\"https://de.wikipedia.org/wiki/Proof_of_Work\">Proof of Work</a>. Die Aufgabe wird innerhalb weniger Sekunden berechnet und du erhältst Zugang zur Website. Danke für dein Verständnis und deine Geduld.",
|
||||||
"jshelter_note": "Anubis benötigt moderne JavaScript-Features, die von Plugins wie JShelter deaktiviert werden. Bitte deaktiviere JShelter oder ähnliche Plugins für diese Domain.",
|
"jshelter_note": "Anubis benötigt moderne JavaScript-Funktionen, die von Plugins wie JShelter deaktiviert werden. Bitte deaktiviere JShelter oder ähnliche Plugins für diese Domain.",
|
||||||
"version_info": "Diese Website läuft mit Anubis-Version",
|
"version_info": "Diese Website nutzt Anubis Version",
|
||||||
"try_again": "Erneut versuchen",
|
"try_again": "Erneut versuchen",
|
||||||
"go_home": "Zur Startseite",
|
"go_home": "Zur Startseite",
|
||||||
"contact_webmaster": "Falls du glaubst, dass es sich um einen Fehler handelt, kontaktiere bitte den Administrator unter",
|
"contact_webmaster": "oder kontaktiere den Webmaster unter, falls du glaubst, dass du nicht blockiert werden solltest:",
|
||||||
"connection_security": "Bitte warte einen Moment, während wir die Sicherheit deiner Verbindung prüfen.",
|
"connection_security": "Bitte warte einen Moment, während wir die Sicherheit deiner Verbindung überprüfen.",
|
||||||
"javascript_required": "Du musst JavaScript aktivieren, um diese Prüfung durchführen zu können. Dies ist notwendig, da KI-Unternehmen die bisherigen Regeln für das Hosting von Websites nicht mehr respektieren. Eine Lösung ohne JavaScript ist in Entwicklung.",
|
"javascript_required": "Du musst JavaScript aktivieren, um diese Prüfung zu bestehen. Dies ist notwendig, da KI-Unternehmen den Gesellschaftsvertrag rund um Webhosting verändert haben. Eine Lösung ohne JavaScript ist in Arbeit.",
|
||||||
"benchmark_requires_js": "Für die Nutzung des Benchmark-Tools muss JavaScript aktiviert sein.",
|
"benchmark_requires_js": "Für das Benchmark-Tool muss JavaScript aktiviert sein.",
|
||||||
"difficulty": "Schwierigkeit:",
|
"difficulty": "Schwierigkeit:",
|
||||||
"algorithm": "Algorithmus:",
|
"algorithm": "Algorithmus:",
|
||||||
"compare": "Vergleich:",
|
"compare": "Vergleichen:",
|
||||||
"time": "Zeit",
|
"time": "Zeit",
|
||||||
"iters": "Iterationen",
|
"iters": "Iterationen",
|
||||||
"time_a": "Zeit A",
|
"time_a": "Zeit A",
|
||||||
"iters_a": "Iterationen A",
|
"iters_a": "Iterationen A",
|
||||||
"time_b": "Zeit B",
|
"time_b": "Zeit B",
|
||||||
"iters_b": "Iterationen B",
|
"iters_b": "Iterationen B",
|
||||||
"static_check_endpoint": "Dies ist ein Endpunkt zur Prüfung durch einen Reverse-Proxy.",
|
"static_check_endpoint": "Dies ist nur ein Prüf-Endpunkt für deinen Reverse-Proxy.",
|
||||||
"authorization_required": "Autorisierung erforderlich",
|
"authorization_required": "Autorisierung erforderlich",
|
||||||
"cookies_disabled": "Cookies sind in deinem Browser deaktiviert. Anubis benötigt Cookies, um sicherzustellen, dass es sich um einen legitimen Zugriff handelt. Bitte aktiviere Cookies für diese Domain.",
|
"cookies_disabled": "Cookies sind in deinem Browser deaktiviert. Anubis benötigt Cookies im berechtigten Interesse, sicherzustellen, dass es sich um einen gültigen Client handelt. Bitte aktiviere Cookies für diese Domain.",
|
||||||
"access_denied": "Zugriff verweigert – Fehlercode",
|
"access_denied": "Zugriff verweigert: Fehlercode",
|
||||||
"dronebl_entry": "Eintrag in DroneBL",
|
"dronebl_entry": "DroneBL hat einen Eintrag gemeldet",
|
||||||
"see_dronebl_lookup": "anzeigen",
|
"see_dronebl_lookup": "anzeigen",
|
||||||
"internal_server_error": "Interner Serverfehler: Der Administrator hat Anubis fehlerhaft konfiguriert. Bitte kontaktiere den Administrator und bitte ihn, die Logs zu prüfen.",
|
"internal_server_error": "Interner Serverfehler: Der Administrator hat Anubis fehlerhaft konfiguriert. Bitte kontaktiere den Administrator und bitte ihn, die Logs im Zeitraum um folgenden Zeitpunkt zu prüfen:",
|
||||||
"invalid_redirect": "Ungültige Weiterleitung",
|
"invalid_redirect": "Ungültige Weiterleitung",
|
||||||
"redirect_not_parseable": "Weiterleitungs-URL kann nicht verarbeitet werden",
|
"redirect_not_parseable": "Weiterleitungs-URL kann nicht verarbeitet werden",
|
||||||
"redirect_domain_not_allowed": "Weiterleitungs-Domain nicht erlaubt",
|
"redirect_domain_not_allowed": "Weiterleitungs-Domain nicht erlaubt",
|
||||||
@@ -41,27 +41,26 @@
|
|||||||
"invalid_invocation": "Ungültiger Aufruf von MakeChallenge",
|
"invalid_invocation": "Ungültiger Aufruf von MakeChallenge",
|
||||||
"client_error_browser": "Client-Fehler: Bitte stelle sicher, dass dein Browser aktuell ist, und versuche es später erneut.",
|
"client_error_browser": "Client-Fehler: Bitte stelle sicher, dass dein Browser aktuell ist, und versuche es später erneut.",
|
||||||
"oh_noes": "Oh nein!",
|
"oh_noes": "Oh nein!",
|
||||||
"benchmarking_anubis": "Benchmark wird durchgeführt!",
|
"benchmarking_anubis": "Anubis-Benchmark wird durchgeführt!",
|
||||||
"you_are_not_a_bot": "Du bist kein Bot!",
|
"you_are_not_a_bot": "Du bist kein Bot!",
|
||||||
"making_sure_not_bot": "Dein Browser wird geprüft!",
|
"making_sure_not_bot": "Dein Browser wird geprüft!",
|
||||||
"celphase": "CELPHASE",
|
"celphase": "CELPHASE",
|
||||||
"js_web_crypto_error": "Dein Browser verfügt nicht über ein funktionierendes web.crypto-Element. Wird eine sichere Verbindung verwendet?",
|
"js_web_crypto_error": "Dein Browser verfügt nicht über ein funktionierendes web.crypto-Element. Wird diese Seite in einem sicheren Kontext angezeigt?",
|
||||||
"js_web_workers_error": "Dein Browser unterstützt keine Web-Worker (Anubis verwendet diese, damit der Browser nicht einfriert). Ist ein Plugin wie JShelter installiert?",
|
"js_web_workers_error": "Dein Browser unterstützt keine Web Workers (Anubis verwendet diese, damit dein Browser nicht einfriert). Hast du ein Plugin wie JShelter installiert?",
|
||||||
"js_cookies_error": "Dein Browser speichert keine Cookies. Anubis verwendet Cookies, um nach bestandener Prüfung ein signiertes Token abzulegen. Bitte aktiviere Cookies für diese Domain. Die Cookie-Namen von Anubis können sich jederzeit ändern. Cookie-Namen und gespeicherte Werte sind nicht Teil der öffentlichen API.",
|
"js_cookies_error": "Dein Browser speichert keine Cookies. Anubis verwendet Cookies, um nach bestandener Prüfung ein signiertes Token abzulegen. Bitte aktiviere Cookies für diese Domain. Die Cookie-Namen von Anubis können sich jederzeit ohne Vorankündigung ändern. Cookie-Namen und -Werte sind nicht Teil der öffentlichen API.",
|
||||||
"js_context_not_secure": "Diese Verbindung ist nicht sicher!",
|
"js_context_not_secure": "Diese Verbindung ist nicht sicher!",
|
||||||
"js_context_not_secure_msg": "Bitte versuche, dich über HTTPS zu verbinden, oder weise den Administrator darauf hin, HTTPS einzurichten. Mehr Informationen: <a href=\"https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#when_is_a_context_considered_secure\">MDN</a>.",
|
"js_context_not_secure_msg": "Versuche, dich über HTTPS zu verbinden, oder informiere den Administrator, HTTPS einzurichten. Weitere Informationen unter <a href=\"https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#when_is_a_context_considered_secure\">MDN</a>.",
|
||||||
"js_calculating": "Berechnung läuft...",
|
"js_calculating": "Berechnung läuft …",
|
||||||
"js_missing_feature": "Fehlendes Feature",
|
"js_missing_feature": "Fehlendes Feature",
|
||||||
"js_challenge_error": "Prüfung fehlgeschlagen!",
|
"js_challenge_error": "Prüfung fehlgeschlagen!",
|
||||||
"js_challenge_error_msg": "Der Prüf-Algorithmus konnte nicht geladen werden. Bitte lade die Seite neu.",
|
"js_challenge_error_msg": "Der Prüfalgorithmus konnte nicht aufgelöst werden. Bitte lade die Seite neu.",
|
||||||
"js_calculating_difficulty": "Berechnung läuft...<br/>Schwierigkeit:",
|
"js_calculating_difficulty": "Berechnung läuft …<br/>Schwierigkeit:",
|
||||||
"js_speed": "Geschwindigkeit:",
|
"js_speed": "Geschwindigkeit:",
|
||||||
"js_verification_longer": "Die Prüfung dauert länger als erwartet. Bitte warte und lade die Seite nicht neu.",
|
"js_verification_longer": "Die Verifizierung dauert länger als erwartet. Bitte bleibe auf der Seite und lade sie nicht neu.",
|
||||||
"js_success": "Erfolgreich!",
|
"js_success": "Geschafft!",
|
||||||
"js_done_took": "Fertig! Dauer:",
|
"js_done_took": "Fertig! Dauer:",
|
||||||
"js_iterations": "Iterationen",
|
"js_iterations": "Iterationen",
|
||||||
"js_finished_reading": "Fertig gelesen – weiter zur Seite →",
|
"js_finished_reading": "Fertig gelesen, weiter zur Seite →",
|
||||||
"js_calculation_error": "Berechnungsfehler!",
|
"js_calculation_error": "Berechnungsfehler!",
|
||||||
"js_calculation_error_msg": "Fehler bei der Berechnung der Prüfung:",
|
"js_calculation_error_msg": "Fehler bei der Berechnung der Prüfung:"
|
||||||
"js_challenge_data_missing": "Die Prüfungsdaten fehlen. Bitte laden Sie die Seite neu."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_iterations": "iterations",
|
"js_iterations": "iterations",
|
||||||
"js_finished_reading": "I've finished reading, continue →",
|
"js_finished_reading": "I've finished reading, continue →",
|
||||||
"js_calculation_error": "Calculation error!",
|
"js_calculation_error": "Calculation error!",
|
||||||
"js_calculation_error_msg": "Failed to calculate challenge:",
|
"js_calculation_error_msg": "Failed to calculate challenge:"
|
||||||
"js_challenge_data_missing": "Challenge data is missing. Please reload the page."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "¡Error de cálculo!",
|
"js_calculation_error": "¡Error de cálculo!",
|
||||||
"js_calculation_error_msg": "Falló al calcular el desafío:",
|
"js_calculation_error_msg": "Falló al calcular el desafío:",
|
||||||
"missing_required_forwarded_headers": "Faltan los encabezados X-Forwarded-* requeridos",
|
"missing_required_forwarded_headers": "Faltan los encabezados X-Forwarded-* requeridos",
|
||||||
"simplified_explanation": "Esta es una medida contra bots y solicitudes maliciosas similar a un CAPTCHA. Sin embargo, en lugar de tener que hacer el trabajo usted mismo, a su navegador se le asigna una tarea de cálculo que debe resolver para garantizar que es un cliente válido. Este concepto se llama <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Prueba de trabajo</a>. La tarea se calcula en unos segundos y se le concede acceso al sitio web. Gracias por su comprensión y paciencia.",
|
"simplified_explanation": "Esta es una medida contra bots y solicitudes maliciosas similar a un CAPTCHA. Sin embargo, en lugar de tener que hacer el trabajo usted mismo, a su navegador se le asigna una tarea de cálculo que debe resolver para garantizar que es un cliente válido. Este concepto se llama <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Prueba de trabajo</a>. La tarea se calcula en unos segundos y se le concede acceso al sitio web. Gracias por su comprensión y paciencia."
|
||||||
"js_challenge_data_missing": "Faltan los datos del desafío. Por favor, recargue la página."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Arvutamise viga!",
|
"js_calculation_error": "Arvutamise viga!",
|
||||||
"js_calculation_error_msg": "Ei suutnud kontrolli arvutada:",
|
"js_calculation_error_msg": "Ei suutnud kontrolli arvutada:",
|
||||||
"missing_required_forwarded_headers": "Puuduvad nõutud X-Forwarded-* päised",
|
"missing_required_forwarded_headers": "Puuduvad nõutud X-Forwarded-* päised",
|
||||||
"simplified_explanation": "See on meede robotite ja pahatahtlike päringute vastu, mis sarnaneb CAPTCHA-le. Kuid selle asemel, et peaksite ise tööd tegema, antakse teie brauserile arvutusülesanne, mille see peab lahendama, et tagada selle kehtivus kliendina. Seda kontseptsiooni nimetatakse <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Töötõendiks</a>. Ülesanne arvutatakse mõne sekundiga ja teile antakse juurdepääs veebisaidile. Täname teid mõistva suhtumise ja kannatlikkuse eest.",
|
"simplified_explanation": "See on meede robotite ja pahatahtlike päringute vastu, mis sarnaneb CAPTCHA-le. Kuid selle asemel, et peaksite ise tööd tegema, antakse teie brauserile arvutusülesanne, mille see peab lahendama, et tagada selle kehtivus kliendina. Seda kontseptsiooni nimetatakse <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Töötõendiks</a>. Ülesanne arvutatakse mõne sekundiga ja teile antakse juurdepääs veebisaidile. Täname teid mõistva suhtumise ja kannatlikkuse eest."
|
||||||
"js_challenge_data_missing": "Kontrollülesande andmed puuduvad. Palun laadige leht uuesti."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Laskentavirhe!",
|
"js_calculation_error": "Laskentavirhe!",
|
||||||
"js_calculation_error_msg": "Haasteen laskenta ei onnistunut:",
|
"js_calculation_error_msg": "Haasteen laskenta ei onnistunut:",
|
||||||
"missing_required_forwarded_headers": "Puuttuvat vaaditut X-Forwarded-* otsikot",
|
"missing_required_forwarded_headers": "Puuttuvat vaaditut X-Forwarded-* otsikot",
|
||||||
"simplified_explanation": "Tämä on toimenpide botteja ja haitallisia pyyntöjä vastaan, joka on samanlainen kuin CAPTCHA. Sen sijaan, että joutuisit tekemään työtä itse, selaimesi saa laskentatehtävän, joka sen on ratkaistava varmistaakseen, että se on kelvollinen asiakas. Tätä käsitettä kutsutaan nimellä <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Työtodistus</a>. Tehtävä lasketaan muutamassa sekunnissa ja saat pääsyn verkkosivustolle. Kiitos ymmärryksestäsi ja kärsivällisyydestäsi.",
|
"simplified_explanation": "Tämä on toimenpide botteja ja haitallisia pyyntöjä vastaan, joka on samanlainen kuin CAPTCHA. Sen sijaan, että joutuisit tekemään työtä itse, selaimesi saa laskentatehtävän, joka sen on ratkaistava varmistaakseen, että se on kelvollinen asiakas. Tätä käsitettä kutsutaan nimellä <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Työtodistus</a>. Tehtävä lasketaan muutamassa sekunnissa ja saat pääsyn verkkosivustolle. Kiitos ymmärryksestäsi ja kärsivällisyydestäsi."
|
||||||
"js_challenge_data_missing": "Haastetiedot puuttuvat. Lataa sivu uudelleen."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Error sa pagkalkula!",
|
"js_calculation_error": "Error sa pagkalkula!",
|
||||||
"js_calculation_error_msg": "Nabigong ikalkula ang hamon:",
|
"js_calculation_error_msg": "Nabigong ikalkula ang hamon:",
|
||||||
"missing_required_forwarded_headers": "Nawawala ang kinakailangang X-Forwarded-* na mga header",
|
"missing_required_forwarded_headers": "Nawawala ang kinakailangang X-Forwarded-* na mga header",
|
||||||
"simplified_explanation": "Ito ay isang panukala laban sa mga bot at malisyosong mga kahilingan na katulad ng isang CAPTCHA. Gayunpaman, sa halip na ikaw mismo ang gumawa ng trabaho, binibigyan ang iyong browser ng isang gawain sa pagkalkula na kailangan nitong lutasin upang matiyak na ito ay isang wastong kliyente. Ang konseptong ito ay tinatawag na <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Ang gawain ay kinakalkula sa loob ng ilang segundo at binibigyan ka ng access sa website. Salamat sa iyong pag-unawa at pasensya.",
|
"simplified_explanation": "Ito ay isang panukala laban sa mga bot at malisyosong mga kahilingan na katulad ng isang CAPTCHA. Gayunpaman, sa halip na ikaw mismo ang gumawa ng trabaho, binibigyan ang iyong browser ng isang gawain sa pagkalkula na kailangan nitong lutasin upang matiyak na ito ay isang wastong kliyente. Ang konseptong ito ay tinatawag na <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Ang gawain ay kinakalkula sa loob ng ilang segundo at binibigyan ka ng access sa website. Salamat sa iyong pag-unawa at pasensya."
|
||||||
"js_challenge_data_missing": "Nawawala ang data ng hamon. Mangyaring i-reload ang pahina."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Erreur de calcul !",
|
"js_calculation_error": "Erreur de calcul !",
|
||||||
"js_calculation_error_msg": "Échec du calcul du défi :",
|
"js_calculation_error_msg": "Échec du calcul du défi :",
|
||||||
"missing_required_forwarded_headers": "En-têtes X-Forwarded-* manquants",
|
"missing_required_forwarded_headers": "En-têtes X-Forwarded-* manquants",
|
||||||
"simplified_explanation": "Ceci est une mesure contre les robots et les requêtes malveillantes, similaire à un CAPTCHA. Cependant, au lieu d'avoir à faire le travail vous-même, votre navigateur se voit confier une tâche de calcul qu'il doit résoudre pour confirmer qu'il est un client valide. Ce concept est nommé <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Preuve de travail</a>. La tâche s'effectue en quelques secondes, puis vous avez accès au site Web. Merci pour votre compréhension et votre patience.",
|
"simplified_explanation": "Ceci est une mesure contre les robots et les requêtes malveillantes, similaire à un CAPTCHA. Cependant, au lieu d'avoir à faire le travail vous-même, votre navigateur se voit confier une tâche de calcul qu'il doit résoudre pour confirmer qu'il est un client valide. Ce concept est nommé <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Preuve de travail</a>. La tâche s'effectue en quelques secondes, puis vous avez accès au site Web. Merci pour votre compréhension et votre patience."
|
||||||
"js_challenge_data_missing": "Les données du défi sont manquantes. Veuillez recharger la page."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Reiknivilla!",
|
"js_calculation_error": "Reiknivilla!",
|
||||||
"js_calculation_error_msg": "Mistókst að reikna áskorun:",
|
"js_calculation_error_msg": "Mistókst að reikna áskorun:",
|
||||||
"missing_required_forwarded_headers": "Vantar nauðsynleg X-Forwarded-* hausar",
|
"missing_required_forwarded_headers": "Vantar nauðsynleg X-Forwarded-* hausar",
|
||||||
"simplified_explanation": "Þetta er ráðstöfun gegn vélmennum og illa meinandi beiðnum, sem virkar svipað og CAPTCHA-mennskupróf. Hins vegar; í stað þess að þurfa að vinna sjálfur, fær vafrinn þinn útreikningsverkefni sem hann þarf að leysa til að tryggja að hann sé gildur biðlari. Þetta hugtak er kallað <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Sönnun-á-vinnu</a>. Verkefnið er reiknað á nokkrum sekúndum og þú færð aðgang að vefsíðunni. Takk fyrir skilninginn og þolinmæðina.",
|
"simplified_explanation": "Þetta er ráðstöfun gegn vélmennum og illa meinandi beiðnum, sem virkar svipað og CAPTCHA-mennskupróf. Hins vegar; í stað þess að þurfa að vinna sjálfur, fær vafrinn þinn útreikningsverkefni sem hann þarf að leysa til að tryggja að hann sé gildur biðlari. Þetta hugtak er kallað <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Sönnun-á-vinnu</a>. Verkefnið er reiknað á nokkrum sekúndum og þú færð aðgang að vefsíðunni. Takk fyrir skilninginn og þolinmæðina."
|
||||||
"js_challenge_data_missing": "Áskorunargögn vantar. Vinsamlegast endurhlaðið síðuna."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Errore nel calcolo!",
|
"js_calculation_error": "Errore nel calcolo!",
|
||||||
"js_calculation_error_msg": "Impossibile superare il test:",
|
"js_calculation_error_msg": "Impossibile superare il test:",
|
||||||
"missing_required_forwarded_headers": "Mancano gli header X-Forwarded-* richiesti",
|
"missing_required_forwarded_headers": "Mancano gli header X-Forwarded-* richiesti",
|
||||||
"simplified_explanation": "Questa è una misura contro bot e richieste dannose simile a un CAPTCHA. Tuttavia, invece di dover lavorare tu stesso, al tuo browser viene assegnato un compito di calcolo che deve risolvere per garantire che sia un client valido. Questo concetto è chiamato <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Il compito viene calcolato in pochi secondi e ti viene concesso l'accesso al sito web. Grazie per la tua comprensione e pazienza.",
|
"simplified_explanation": "Questa è una misura contro bot e richieste dannose simile a un CAPTCHA. Tuttavia, invece di dover lavorare tu stesso, al tuo browser viene assegnato un compito di calcolo che deve risolvere per garantire che sia un client valido. Questo concetto è chiamato <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Il compito viene calcolato in pochi secondi e ti viene concesso l'accesso al sito web. Grazie per la tua comprensione e pazienza."
|
||||||
"js_challenge_data_missing": "I dati della sfida sono mancanti. Ricarica la pagina."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"anubis_compromise": "Anubisは妥協策です。AnubisはHashcashのようなProof-of-Work方式を採用しており、これは元々メールスパムを減らすために提案された仕組みです。個人レベルでは追加の負荷は無視できる程度ですが、大規模なスクレイピングでは負荷が積み重なり、スクレイピングのコストが大幅に増加します。",
|
"anubis_compromise": "Anubisは妥協策です。AnubisはHashcashのようなProof-of-Work方式を採用しており、これは元々メールスパムを減らすために提案された仕組みです。個人レベルでは追加の負荷は無視できる程度ですが、大規模なスクレイピングでは負荷が積み重なり、スクレイピングのコストが大幅に増加します。",
|
||||||
"hack_purpose": "最終的に、これはヘッドレスブラウザのフィンガープリントと識別に時間を費やすためのプレースホルダーソリューションです(例:フォントレンダリングの方法による)。これにより、正当なユーザーにはチャレンジのプルーフオブワークページを提示する必要がなくなります。",
|
"hack_purpose": "最終的に、これはヘッドレスブラウザのフィンガープリントと識別に時間を費やすためのプレースホルダーソリューションです(例:フォントレンダリングの方法による)。これにより、正当なユーザーにはチャレンジのプルーフオブワークページを提示する必要がなくなります。",
|
||||||
"jshelter_note": "Anubisは、JShelterのようなプラグインが無効化する最新のJavaScript機能を必要とします。このドメインではJShelterや同様のプラグインを無効にしてください。",
|
"jshelter_note": "Anubisは、JShelterのようなプラグインが無効化する最新のJavaScript機能を必要とします。このドメインではJShelterや同様のプラグインを無効にしてください。",
|
||||||
"version_info": "このウェブサイトはAnubisバージョンで動作しています",
|
"version_info": "このウェブサイトはAnubisで動作しています バージョン",
|
||||||
"try_again": "再試行",
|
"try_again": "再試行",
|
||||||
"go_home": "ホームに戻る",
|
"go_home": "ホームに戻る",
|
||||||
"contact_webmaster": "もしブロックされるべきでないと思われる場合は、ウェブマスターにご連絡ください:",
|
"contact_webmaster": "もしブロックされるべきでないと思われる場合は、ウェブマスターにご連絡ください:",
|
||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "計算エラー!",
|
"js_calculation_error": "計算エラー!",
|
||||||
"js_calculation_error_msg": "チャレンジの計算に失敗しました:",
|
"js_calculation_error_msg": "チャレンジの計算に失敗しました:",
|
||||||
"missing_required_forwarded_headers": "必要な X-Forwarded-* ヘッダーがありません",
|
"missing_required_forwarded_headers": "必要な X-Forwarded-* ヘッダーがありません",
|
||||||
"simplified_explanation": "これは、CAPTCHAと同様の、ボットや悪意のあるリクエストに対する対策です。ただし、自分で作業する代わりに、ブラウザに計算タスクが与えられ、それを解決して有効なクライアントであることを確認する必要があります。この概念は<a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>と呼ばれます。タスクは数秒で計算され、ウェブサイトへのアクセスが許可されます。ご理解とご協力をお願いいたします。",
|
"simplified_explanation": "これは、CAPTCHAと同様の、ボットや悪意のあるリクエストに対する対策です。ただし、自分で作業する代わりに、ブラウザに計算タスクが与えられ、それを解決して有効なクライアントであることを確認する必要があります。この概念は<a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>と呼ばれます。タスクは数秒で計算され、ウェブサイトへのアクセスが許可されます。ご理解とご協力をお願いいたします。"
|
||||||
"js_challenge_data_missing": "チャレンジデータがありません。ページを再読み込みしてください。"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
"invalid_redirect": "Netinkamas nukreipimas",
|
"invalid_redirect": "Netinkamas nukreipimas",
|
||||||
"redirect_not_parseable": "Nukreipimo adreso nepavyko išanalizuoti",
|
"redirect_not_parseable": "Nukreipimo adreso nepavyko išanalizuoti",
|
||||||
"redirect_domain_not_allowed": "Nukreipimo domenas neleistinas",
|
"redirect_domain_not_allowed": "Nukreipimo domenas neleistinas",
|
||||||
"missing_required_forwarded_headers": "Trūksta privalomų X-Forwarded-* antraščių",
|
"missing_required_forwarded_headers": "Trūksta būtinų „X-Forwarded-*“ antraščių",
|
||||||
"failed_to_sign_jwt": "nepavyko pasirašyti JWT",
|
"failed_to_sign_jwt": "nepavyko pasirašyti JWT",
|
||||||
"invalid_invocation": "Netinkamas kreipinys į „MakeChallenge“",
|
"invalid_invocation": "Netinkamas kreipinys į „MakeChallenge“",
|
||||||
"client_error_browser": "Problema klientinėje dalyje: įsitikinkite, jog jūsų naršyklė nepasenusi ir bandykite dar kartą.",
|
"client_error_browser": "Problema klientinėje dalyje: įsitikinkite, jog jūsų naršyklė nepasenusi ir bandykite dar kartą.",
|
||||||
@@ -63,5 +63,5 @@
|
|||||||
"js_finished_reading": "Viską perskaičiau, tęskime →",
|
"js_finished_reading": "Viską perskaičiau, tęskime →",
|
||||||
"js_calculation_error": "Skaičiavimo klaida!",
|
"js_calculation_error": "Skaičiavimo klaida!",
|
||||||
"js_calculation_error_msg": "Nepavyko įveikti iššūkio:",
|
"js_calculation_error_msg": "Nepavyko įveikti iššūkio:",
|
||||||
"js_challenge_data_missing": "Trūksta iššūkio duomenų. Prašome perkrauti puslapį."
|
"missing_required_forwarded_headers": "Trūksta privalomų X-Forwarded-* antraščių"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"vi",
|
"vi",
|
||||||
"zh-CN",
|
"zh-CN",
|
||||||
"zh-TW",
|
"zh-TW",
|
||||||
"sv"
|
"sv",
|
||||||
|
"bg"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Beregningsfeil!",
|
"js_calculation_error": "Beregningsfeil!",
|
||||||
"js_calculation_error_msg": "Mislyktes i å beregne utfordring:",
|
"js_calculation_error_msg": "Mislyktes i å beregne utfordring:",
|
||||||
"missing_required_forwarded_headers": "Mangler nødvendige X-Forwarded-* header",
|
"missing_required_forwarded_headers": "Mangler nødvendige X-Forwarded-* header",
|
||||||
"simplified_explanation": "Dette er et tiltak mot roboter og ondsinnede forespørsler som ligner på en CAPTCHA. Men i stedet for å måtte gjøre arbeidet selv, får nettleseren din en beregningsoppgave som den må løse for å sikre at den er en gyldig klient. Dette konseptet kalles <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Oppgaven beregnes på noen få sekunder, og du får tilgang til nettstedet. Takk for din forståelse og tålmodighet.",
|
"simplified_explanation": "Dette er et tiltak mot roboter og ondsinnede forespørsler som ligner på en CAPTCHA. Men i stedet for å måtte gjøre arbeidet selv, får nettleseren din en beregningsoppgave som den må løse for å sikre at den er en gyldig klient. Dette konseptet kalles <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a>. Oppgaven beregnes på noen få sekunder, og du får tilgang til nettstedet. Takk for din forståelse og tålmodighet."
|
||||||
"js_challenge_data_missing": "Utfordringsdata mangler. Vennligst last inn siden på nytt."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Rekenfout!",
|
"js_calculation_error": "Rekenfout!",
|
||||||
"js_calculation_error_msg": "Uitdaging niet berekend:",
|
"js_calculation_error_msg": "Uitdaging niet berekend:",
|
||||||
"missing_required_forwarded_headers": "Ontbrekende vereiste X-Forwarded-* headers",
|
"missing_required_forwarded_headers": "Ontbrekende vereiste X-Forwarded-* headers",
|
||||||
"simplified_explanation": "Dit is een maatregel tegen bots en kwaadwillende verzoeken, vergelijkbaar met een CAPTCHA. In plaats van dat je zelf werk moet verrichten, krijgt je browser een rekentaak die moet worden opgelost om ervoor te zorgen dat het een geldige client is. Dit concept wordt <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a> genoemd. De taak wordt in een paar seconden berekend en u krijgt toegang tot de website. Bedankt voor je begrip en geduld.",
|
"simplified_explanation": "Dit is een maatregel tegen bots en kwaadwillende verzoeken, vergelijkbaar met een CAPTCHA. In plaats van dat je zelf werk moet verrichten, krijgt je browser een rekentaak die moet worden opgelost om ervoor te zorgen dat het een geldige client is. Dit concept wordt <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Proof of Work</a> genoemd. De taak wordt in een paar seconden berekend en u krijgt toegang tot de website. Bedankt voor je begrip en geduld."
|
||||||
"js_challenge_data_missing": "Uitdagingsgegevens ontbreken. Herlaad de pagina."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Rekningsfeil!",
|
"js_calculation_error": "Rekningsfeil!",
|
||||||
"js_calculation_error_msg": "Mislukkast i å rekna utfordring:",
|
"js_calculation_error_msg": "Mislukkast i å rekna utfordring:",
|
||||||
"missing_required_forwarded_headers": "Vantande naudsynte «X-Forwarded-*»-overskrifter",
|
"missing_required_forwarded_headers": "Vantande naudsynte «X-Forwarded-*»-overskrifter",
|
||||||
"simplified_explanation": "Dette er eit tiltak mot robotar og ondsinna førespurnader som liknar på ein CAPTCHA. Men i staden for å måtte gjera arbeidet sjølv, får netlesaren din ei utrekningsoppgåve som han må løysa for å stadfesta at han er ein gyldig klient. Dette konseptet vert kalla <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">arbeidsstadfesting</a>. Oppgåva vert rekna ut på nokre få sekund, og du får tilgang til nettstaden. Takk for forståinga di og tolmodet ditt.",
|
"simplified_explanation": "Dette er eit tiltak mot robotar og ondsinna førespurnader som liknar på ein CAPTCHA. Men i staden for å måtte gjera arbeidet sjølv, får netlesaren din ei utrekningsoppgåve som han må løysa for å stadfesta at han er ein gyldig klient. Dette konseptet vert kalla <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">arbeidsstadfesting</a>. Oppgåva vert rekna ut på nokre få sekund, og du får tilgang til nettstaden. Takk for forståinga di og tolmodet ditt."
|
||||||
"js_challenge_data_missing": "Utfordringsdata manglar. Last inn sida på nytt."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_iterations": "iteracji",
|
"js_iterations": "iteracji",
|
||||||
"js_finished_reading": "Skończyłem czytać, kontynuuj →",
|
"js_finished_reading": "Skończyłem czytać, kontynuuj →",
|
||||||
"js_calculation_error": "Błąd obliczeń!",
|
"js_calculation_error": "Błąd obliczeń!",
|
||||||
"js_calculation_error_msg": "Nie udało się obliczyć zadania:",
|
"js_calculation_error_msg": "Nie udało się obliczyć zadania:"
|
||||||
"js_challenge_data_missing": "Brak danych wyzwania. Proszę odświeżyć stronę."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Erro de cálculo!",
|
"js_calculation_error": "Erro de cálculo!",
|
||||||
"js_calculation_error_msg": "Falha ao calcular a validação:",
|
"js_calculation_error_msg": "Falha ao calcular a validação:",
|
||||||
"missing_required_forwarded_headers": "Faltam os cabeçalhos X-Forwarded-* obrigatórios",
|
"missing_required_forwarded_headers": "Faltam os cabeçalhos X-Forwarded-* obrigatórios",
|
||||||
"simplified_explanation": "Esta é uma medida contra bots e solicitações maliciosas, semelhante a um CAPTCHA. No entanto, em vez de você mesmo ter que fazer o trabalho, seu navegador recebe uma tarefa de cálculo que ele deve resolver para garantir que seja um cliente válido. Esse conceito é chamado de <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Prova de Trabalho</a>. A tarefa é calculada em poucos segundos e você tem acesso ao site. Obrigado pela sua compreensão e paciência.",
|
"simplified_explanation": "Esta é uma medida contra bots e solicitações maliciosas, semelhante a um CAPTCHA. No entanto, em vez de você mesmo ter que fazer o trabalho, seu navegador recebe uma tarefa de cálculo que ele deve resolver para garantir que seja um cliente válido. Esse conceito é chamado de <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Prova de Trabalho</a>. A tarefa é calculada em poucos segundos e você tem acesso ao site. Obrigado pela sua compreensão e paciência."
|
||||||
"js_challenge_data_missing": "Os dados do desafio estão ausentes. Por favor, recarregue a página."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Ошибка расчёта!",
|
"js_calculation_error": "Ошибка расчёта!",
|
||||||
"js_calculation_error_msg": "Не удалось рассчитать задачу:",
|
"js_calculation_error_msg": "Не удалось рассчитать задачу:",
|
||||||
"missing_required_forwarded_headers": "Отсутствуют требуемые заголовки X-Forwarded-*",
|
"missing_required_forwarded_headers": "Отсутствуют требуемые заголовки X-Forwarded-*",
|
||||||
"simplified_explanation": "Это мера против ботов и вредоносных запросов, аналогичная CAPTCHA. Однако вместо того, чтобы вам приходилось работать самостоятельно, вашему браузеру дается задача вычисления, которую он должен решить, чтобы убедиться, что он является действительным клиентом. Эта концепция называется <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Доказательство выполнения работы</a>. Задача рассчитывается за несколько секунд, и вам предоставляется доступ к веб-сайту. Спасибо за понимание и терпение.",
|
"simplified_explanation": "Это мера против ботов и вредоносных запросов, аналогичная CAPTCHA. Однако вместо того, чтобы вам приходилось работать самостоятельно, вашему браузеру дается задача вычисления, которую он должен решить, чтобы убедиться, что он является действительным клиентом. Эта концепция называется <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Доказательство выполнения работы</a>. Задача рассчитывается за несколько секунд, и вам предоставляется доступ к веб-сайту. Спасибо за понимание и терпение."
|
||||||
"js_challenge_data_missing": "Данные проверки отсутствуют. Пожалуйста, перезагрузите страницу."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Beräkningsfel!",
|
"js_calculation_error": "Beräkningsfel!",
|
||||||
"js_calculation_error_msg": "Misslyckades att kalkylera utmaning:",
|
"js_calculation_error_msg": "Misslyckades att kalkylera utmaning:",
|
||||||
"missing_required_forwarded_headers": "Saknar nödvändiga X-Forwarded-* headers",
|
"missing_required_forwarded_headers": "Saknar nödvändiga X-Forwarded-* headers",
|
||||||
"simplified_explanation": "Detta är en åtgärd mot botar och skadliga förfrågningar som liknar en CAPTCHA. Men i stället för att du själv måste göra jobbet får din webbläsare en beräkningsuppgift som den måste lösa för att säkerställa att den är en giltig klient. Detta koncept kallas <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Arbetsbevis</a>. Uppgiften beräknas på några sekunder och du beviljas tillgång till webbplatsen. Tack för din förståelse och ditt tålamod.",
|
"simplified_explanation": "Detta är en åtgärd mot botar och skadliga förfrågningar som liknar en CAPTCHA. Men i stället för att du själv måste göra jobbet får din webbläsare en beräkningsuppgift som den måste lösa för att säkerställa att den är en giltig klient. Detta koncept kallas <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Arbetsbevis</a>. Uppgiften beräknas på några sekunder och du beviljas tillgång till webbplatsen. Tack för din förståelse och ditt tålamod."
|
||||||
"js_challenge_data_missing": "Utmaningsdata saknas. Vänligen ladda om sidan."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,5 @@
|
|||||||
"js_iterations": "รอบ",
|
"js_iterations": "รอบ",
|
||||||
"js_finished_reading": "อ่านจบแล้ว ดำเนินการต่อ →",
|
"js_finished_reading": "อ่านจบแล้ว ดำเนินการต่อ →",
|
||||||
"js_calculation_error": "เกิดข้อผิดพลาดในการคำนวณ!",
|
"js_calculation_error": "เกิดข้อผิดพลาดในการคำนวณ!",
|
||||||
"js_calculation_error_msg": "ไม่สามารถคำนวณการท้าทายได้:",
|
"js_calculation_error_msg": "ไม่สามารถคำนวณการท้าทายได้:"
|
||||||
"js_challenge_data_missing": "ข้อมูลการท้าทายหายไป กรุณาโหลดหน้าใหม่"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "Hesaplama hatası!",
|
"js_calculation_error": "Hesaplama hatası!",
|
||||||
"js_calculation_error_msg": "Zorluk hesaplaması başarısız oldu:",
|
"js_calculation_error_msg": "Zorluk hesaplaması başarısız oldu:",
|
||||||
"missing_required_forwarded_headers": "Gerekli X-Forwarded-* başlıkları eksik",
|
"missing_required_forwarded_headers": "Gerekli X-Forwarded-* başlıkları eksik",
|
||||||
"simplified_explanation": "Bu, botlara ve kötü niyetli isteklere karşı CAPTCHA'ya benzer bir önlemdir. Ancak, kendiniz çalışmak yerine, tarayıcınıza geçerli bir istemci olduğundan emin olmak için çözmesi gereken bir hesaplama görevi verilir. Bu kavrama <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">İş Kanıtı</a> denir. Görev birkaç saniye içinde hesaplanır ve web sitesine erişim hakkı kazanırsınız. Anlayışınız ve sabrınız için teşekkür ederiz.",
|
"simplified_explanation": "Bu, botlara ve kötü niyetli isteklere karşı CAPTCHA'ya benzer bir önlemdir. Ancak, kendiniz çalışmak yerine, tarayıcınıza geçerli bir istemci olduğundan emin olmak için çözmesi gereken bir hesaplama görevi verilir. Bu kavrama <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">İş Kanıtı</a> denir. Görev birkaç saniye içinde hesaplanır ve web sitesine erişim hakkı kazanırsınız. Anlayışınız ve sabrınız için teşekkür ederiz."
|
||||||
"js_challenge_data_missing": "Doğrulama verileri eksik. Lütfen sayfayı yeniden yükleyin."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_iterations": "ітерацій",
|
"js_iterations": "ітерацій",
|
||||||
"js_finished_reading": "Читання завершено, продовжити →",
|
"js_finished_reading": "Читання завершено, продовжити →",
|
||||||
"js_calculation_error": "Помилка обчислення!",
|
"js_calculation_error": "Помилка обчислення!",
|
||||||
"js_calculation_error_msg": "Не вдалося обчислити перевірку:",
|
"js_calculation_error_msg": "Не вдалося обчислити перевірку:"
|
||||||
"js_challenge_data_missing": "Дані перевірки відсутні. Будь ласка, перезавантажте сторінку."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"loading": "Đang nạp...",
|
"loading": "Đang tải...",
|
||||||
"why_am_i_seeing": "Tại sao tôi đang thấy trang này?",
|
"why_am_i_seeing": "Tại sao tôi thấy trang này?",
|
||||||
"protected_by": "Bảo vệ bởi",
|
"protected_by": "Bảo vệ bởi",
|
||||||
"protected_from": "từ",
|
"protected_from": "từ",
|
||||||
"made_with": "Tạo ra bằng ❤️ tại 🇨🇦",
|
"made_with": "Lập trình bằng ❤️ ở 🇨🇦",
|
||||||
"mascot_design": "Thiết kế mascot bởi",
|
"mascot_design": "Mascot thiết kế bởi",
|
||||||
"ai_companies_explanation": "Bạn đang thấy trang này do quản trị viên của trang web này đã thiết lập Anubis để bảo vệ máy chủ của họ khỏi quấy rầy từ những công ty AI hung hãn cóp nhặt nội dung khắp Internet. Điều này có thể và đã dẫn tới tình trạng gián đoạn hoạt động trên nhiều trang web, khiến tài nguyên tại đó nằm ngoài tầm với của mọi người.",
|
"ai_companies_explanation": "Bạn thấy trang này do quản trị viên của trang web này đã thiết lập Anubis để bảo vệ máy chủ của họ khỏi quấy rầy từ những công ty AI hung hãn cóp nhặt nội dung khắp Internet. Điều này dẫn tới tình trạng gián đoạn hoạt động trên nhiều trang web, khiến tài nguyên ở đó nằm ngoài tầm với của mọi người.",
|
||||||
"anubis_compromise": "Anubis là giải pháp thỏa hiệp. Anubis sử dụng cơ chế Proof-of-Work dựa trên Hashcash, được thiết kế ban đầu để giảm bớt email spam. Ý tưởng đằng sau đó là với người dùng cá nhân phần nạp thêm sẽ không đáng kể, nhưng ở tầm mức quy mô lớn sẽ cộng dồn và dẫn tới chi phí tiêu hao hơn rất nhiều.",
|
"anubis_compromise": "Anubis là giải pháp thỏa hiệp. Anubis sử dụng cơ chế Proof-of-Work dựa trên Hashcash, được thiết kế ban đầu để giảm bớt email spam. Ý tưởng đằng sau đó là với người dùng cá nhân phần nạp thêm sẽ không đáng kể, nhưng ở tầm mức quy mô lớn sẽ cộng dồn và dẫn tới chi phí tiêu hao hơn rất nhiều.",
|
||||||
"hack_purpose": "Chốt lại, đây cũng chỉ là giải pháp \"tạm ổn\" với mục đích thực sự là để giành thêm thời gian nhận diện và fingerprint những trình duyệt headless (VD: cách dựng font ra sao), sao cho hạn chế tối đa các yêu cầu tính toán trang thử thách Proof-of-Work tới nhóm người dùng có khả năng cao là con người hơn.",
|
"hack_purpose": "Chốt lại, đây cũng chỉ là giải pháp \"tạm ổn\" với mục đích thực sự là để giành thêm thời gian nhận diện và truy vết những trình duyệt headless (VD: cách dựng font ra sao), sao cho hạn chế tối đa các yêu cầu tính toán trang thử thách Proof-of-Work tới nhóm người dùng có khả năng cao là con người hơn.",
|
||||||
"simplified_explanation": "Đây là một biện pháp chống lại bot và các yêu cầu độc hại tương tự như CAPTCHA. Tuy nhiên, thay vì bạn phải tự mình thực hiện, trình duyệt của bạn sẽ được giao một nhiệm vụ tính toán mà nó phải giải quyết để đảm bảo rằng nó là một máy khách hợp lệ. Khái niệm này được gọi là <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Bằng chứng Công việc</a>. Nhiệm vụ được tính toán trong vài giây và bạn được cấp quyền truy cập vào trang web. Cảm ơn sự thông cảm và kiên nhẫn của bạn.",
|
"simplified_explanation": "Đây là một biện pháp chống lại bot và các yêu cầu độc hại tương tự như CAPTCHA. Tuy nhiên, thay vì bạn phải tự mình thực hiện, trình duyệt của bạn sẽ được giao một nhiệm vụ tính toán mà nó phải giải quyết để đảm bảo rằng nó là một máy khách hợp lệ. Khái niệm này được gọi là <a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">Bằng chứng Công việc</a>. Nhiệm vụ được tính toán trong vài giây và bạn được cấp quyền truy cập vào trang web. Cảm ơn sự thông cảm và kiên nhẫn của bạn.",
|
||||||
"jshelter_note": "Vui lòng lưu ý Anubis cần sử dụng những tính năng JavaScript hiện đại mà một số phần mở rộng như JShelter sẽ tắt. Vui lòng vô hiệu hóa JShelter hoặc những phần mở rộng tương tự cho tên miền này.",
|
"jshelter_note": "Vui lòng lưu ý Anubis cần sử dụng những tính năng JavaScript hiện đại mà một số phần mở rộng như JShelter sẽ tắt. Vui lòng vô hiệu hóa JShelter hoặc những phần mở rộng tương tự cho tên miền này.",
|
||||||
"version_info": "Trang web này đang chạy Anubis phiên bản",
|
"version_info": "Trang web này dùng Anubis bản",
|
||||||
"try_again": "Thử lại",
|
"try_again": "Thử lại",
|
||||||
"go_home": "Về trang chủ",
|
"go_home": "Về trang chủ",
|
||||||
"contact_webmaster": "hoặc nếu bạn tin rằng mình không nên bị chặn, vui lòng liên hệ chủ trang web tại",
|
"contact_webmaster": "hoặc nếu bạn tin rằng mình không nên bị chặn, vui lòng liên hệ chủ trang web tại",
|
||||||
"connection_security": "Vui lòng chờ một chút trong khi chúng tôi kiểm tra an ninh kết nối của bạn.",
|
"connection_security": "Vui lòng chờ một chút trong lúc chúng tôi kiểm tra kết nối của bạn.",
|
||||||
"javascript_required": "Rất tiếc, bạn phải bật JavaScript để vượt qua thử thách này. Điều này bắt buộc do những công ty AI đã thay đổi luật ngầm quanh việc hoạt động máy chủ web ra sao. Giải pháp không có JavaScript đang được phát triển.",
|
"javascript_required": "Rất tiếc, bạn phải bật JavaScript để vượt qua thử thách này. Điều này bắt buộc do những công ty AI đã thay đổi luật ngầm quanh việc hoạt động máy chủ web ra sao. Giải pháp không có JavaScript đang được phát triển.",
|
||||||
"benchmark_requires_js": "Bắt buộc phải bật JavaScript để chạy công cụ benchmark.",
|
"benchmark_requires_js": "Bắt buộc phải bật JavaScript để chạy công cụ benchmark.",
|
||||||
"difficulty": "Độ khó:",
|
"difficulty": "Độ khó:",
|
||||||
@@ -28,14 +28,14 @@
|
|||||||
"iters_b": "Lặp lại kiểu B",
|
"iters_b": "Lặp lại kiểu B",
|
||||||
"static_check_endpoint": "Đây là điểm cuối cho reverse proxy của bạn sử dụng.",
|
"static_check_endpoint": "Đây là điểm cuối cho reverse proxy của bạn sử dụng.",
|
||||||
"authorization_required": "Bắt buộc xác thực",
|
"authorization_required": "Bắt buộc xác thực",
|
||||||
"cookies_disabled": "Trình duyệt của bạn được thiết lập để vô hiệu hóa cookie. Anubis cần cookie cho mục đích chính đáng để kiểm tra chắc chắn bạn là người dùng hợp lệ. Vui lòng bật cookie cho tên miền này",
|
"cookies_disabled": "Trình duyệt của bạn đã vô hiệu hóa cookie. Anubis cần cookie cho mục đích chính đáng để kiểm tra chắc chắn bạn là người dùng hợp lệ. Vui lòng bật cookie cho tên miền này",
|
||||||
"access_denied": "Truy cập bị từ chối: mã lỗi",
|
"access_denied": "Truy cập bị từ chối: mã lỗi",
|
||||||
"dronebl_entry": "DroneBL báo cáo truy cập",
|
"dronebl_entry": "DroneBL báo cáo truy cập",
|
||||||
"see_dronebl_lookup": "xem",
|
"see_dronebl_lookup": "xem",
|
||||||
"internal_server_error": "Lỗi máy chủ nội bộ: quản trị viên đã thiết lập sai Anubis. Vui lòng liên hệ quản trị viên và yêu cầu họ kiểm tra log",
|
"internal_server_error": "Lỗi nội bộ máy chủ: quản trị viên đã thiết lập sai Anubis. Vui lòng liên hệ quản trị viên và yêu cầu họ kiểm tra log",
|
||||||
"invalid_redirect": "Điều hướng không hợp lệ",
|
"invalid_redirect": "Điều hướng không hợp lệ",
|
||||||
"redirect_not_parseable": "Liên kết điều hướng không thể xử lý",
|
"redirect_not_parseable": "Không thể xử lý liên kết điều hướng",
|
||||||
"redirect_domain_not_allowed": "Tên miền điều hướng không được phép",
|
"redirect_domain_not_allowed": "Không được phép điều hướng tên miền",
|
||||||
"missing_required_forwarded_headers": "Thiếu các tiêu đề X-Forwarded-* bắt buộc",
|
"missing_required_forwarded_headers": "Thiếu các tiêu đề X-Forwarded-* bắt buộc",
|
||||||
"failed_to_sign_jwt": "không thể ký JWT",
|
"failed_to_sign_jwt": "không thể ký JWT",
|
||||||
"invalid_invocation": "Gọi hàm MakeChallenge không hợp lệ",
|
"invalid_invocation": "Gọi hàm MakeChallenge không hợp lệ",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
"oh_noes": "Ôi không!",
|
"oh_noes": "Ôi không!",
|
||||||
"benchmarking_anubis": "Đang benchmark Anubis!",
|
"benchmarking_anubis": "Đang benchmark Anubis!",
|
||||||
"you_are_not_a_bot": "Bạn không phải là bot!",
|
"you_are_not_a_bot": "Bạn không phải là bot!",
|
||||||
"making_sure_not_bot": "Đang kiểm tra bạn không phải là bot!",
|
"making_sure_not_bot": "Đảm bảo bạn không phải là bot!",
|
||||||
"celphase": "CELPHASE",
|
"celphase": "CELPHASE",
|
||||||
"js_web_crypto_error": "Trình duyệt của bạn không có web.crypto hoạt động. Liệu bạn có đang xem trang này với kết nối bảo mật không?",
|
"js_web_crypto_error": "Trình duyệt của bạn không có web.crypto hoạt động. Liệu bạn có đang xem trang này với kết nối bảo mật không?",
|
||||||
"js_web_workers_error": "Trình duyệt của bạn không hỗ trợ tính năng web worker (Anubis sử dụng để trình duyệt của bạn bị đơ). Bạn có cài đặt và sử dụng phần mở rộng như JShelter hay không?",
|
"js_web_workers_error": "Trình duyệt của bạn không hỗ trợ tính năng web worker (Anubis sử dụng để trình duyệt của bạn bị đơ). Bạn có cài đặt và sử dụng phần mở rộng như JShelter hay không?",
|
||||||
@@ -53,15 +53,14 @@
|
|||||||
"js_calculating": "Đang tính toán...",
|
"js_calculating": "Đang tính toán...",
|
||||||
"js_missing_feature": "Thiếu tính năng",
|
"js_missing_feature": "Thiếu tính năng",
|
||||||
"js_challenge_error": "Lỗi thử thách!",
|
"js_challenge_error": "Lỗi thử thách!",
|
||||||
"js_challenge_error_msg": "Không thể xử lý thuật toán kiểm tra. Bạn nên nạp lại trang này.",
|
"js_challenge_error_msg": "Không thể xử lý thuật toán kiểm tra. Bạn nên tải lại trang này.",
|
||||||
"js_calculating_difficulty": "Đang tính...<br/>Độ khó:",
|
"js_calculating_difficulty": "Đang tính toán...<br/>Độ khó:",
|
||||||
"js_speed": "Tốc độ:",
|
"js_speed": "Tốc độ:",
|
||||||
"js_verification_longer": "Quá trình kiểm tra đang kéo dài lâu hơn dự kiến. Vui lòng không nạp lại trang này.",
|
"js_verification_longer": "Quá trình kiểm tra hơi lâu hơn dự kiến. Vui lòng không tải lại trang này.",
|
||||||
"js_success": "Thành công!",
|
"js_success": "Thành công!",
|
||||||
"js_done_took": "Hoàn tất! Mất",
|
"js_done_took": "Xong rồi! Vào",
|
||||||
"js_iterations": "lần lặp lại",
|
"js_iterations": "lần lặp lại",
|
||||||
"js_finished_reading": "Tôi đã đọc xong, tiếp tục →",
|
"js_finished_reading": "Tôi đã đọc xong, tiếp tục →",
|
||||||
"js_calculation_error": "Lỗi tính toán!",
|
"js_calculation_error": "Lỗi tính toán!",
|
||||||
"js_calculation_error_msg": "Không thể tính toán thử thách:",
|
"js_calculation_error_msg": "Không thể tính toán thử thách:"
|
||||||
"js_challenge_data_missing": "Thiếu dữ liệu thử thách. Vui lòng tải lại trang."
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "计算错误!",
|
"js_calculation_error": "计算错误!",
|
||||||
"js_calculation_error_msg": "计算挑战失败:",
|
"js_calculation_error_msg": "计算挑战失败:",
|
||||||
"missing_required_forwarded_headers": "缺少必要的 X-Forwarded-* 头",
|
"missing_required_forwarded_headers": "缺少必要的 X-Forwarded-* 头",
|
||||||
"simplified_explanation": "这是一种类似于验证码的措施,用于防止机器人和恶意请求。但是,您无需自己动手,您的浏览器会收到一个计算任务,必须解决该任务以确保它是有效的客户端。这个概念称为<a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">工作量证明</a>。该任务在几秒钟内计算完毕,您将被授予访问网站的权限。感谢您的理解和耐心。",
|
"simplified_explanation": "这是一种类似于验证码的措施,用于防止机器人和恶意请求。但是,您无需自己动手,您的浏览器会收到一个计算任务,必须解决该任务以确保它是有效的客户端。这个概念称为<a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">工作量证明</a>。该任务在几秒钟内计算完毕,您将被授予访问网站的权限。感谢您的理解和耐心。"
|
||||||
"js_challenge_data_missing": "验证数据缺失。请重新加载页面。"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,6 +62,5 @@
|
|||||||
"js_calculation_error": "計算錯誤!",
|
"js_calculation_error": "計算錯誤!",
|
||||||
"js_calculation_error_msg": "計算挑戰失敗:",
|
"js_calculation_error_msg": "計算挑戰失敗:",
|
||||||
"missing_required_forwarded_headers": "缺少必要的 X-Forwarded-* 標頭",
|
"missing_required_forwarded_headers": "缺少必要的 X-Forwarded-* 標頭",
|
||||||
"simplified_explanation": "這是一種類似於驗證碼的措施,用於防止機器人和惡意請求。但是,您無需自己動手,您的瀏覽器會收到一個計算任務,必須解決該任務以確保它是有效的客戶端。這個概念稱為<a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">工作量證明</a>。該任務在幾秒鐘內計算完畢,您將被授予訪問網站的權限。感謝您的理解和耐心。",
|
"simplified_explanation": "這是一種類似於驗證碼的措施,用於防止機器人和惡意請求。但是,您無需自己動手,您的瀏覽器會收到一個計算任務,必須解決該任務以確保它是有效的客戶端。這個概念稱為<a href=\"https://en.wikipedia.org/wiki/Proof_of_work\">工作量證明</a>。該任務在幾秒鐘內計算完畢,您將被授予訪問網站的權限。感謝您的理解和耐心。"
|
||||||
"js_challenge_data_missing": "驗證資料遺失。請重新載入頁面。"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ func TestLocalizationService(t *testing.T) {
|
|||||||
service := NewLocalizationService()
|
service := NewLocalizationService()
|
||||||
|
|
||||||
loadingStrMap := map[string]string{
|
loadingStrMap := map[string]string{
|
||||||
"de": "Ladevorgang...",
|
"de": "Wird geladen …",
|
||||||
"en": "Loading...",
|
"en": "Loading...",
|
||||||
"es": "Cargando...",
|
"es": "Cargando...",
|
||||||
"et": "Laadin...",
|
"et": "Laadin...",
|
||||||
@@ -30,10 +30,11 @@ func TestLocalizationService(t *testing.T) {
|
|||||||
"tr": "Yükleniyor...",
|
"tr": "Yükleniyor...",
|
||||||
"ru": "Загрузка...",
|
"ru": "Загрузка...",
|
||||||
"uk": "Завантаження...",
|
"uk": "Завантаження...",
|
||||||
"vi": "Đang nạp...",
|
"vi": "Đang tải...",
|
||||||
"zh-CN": "加载中...",
|
"zh-CN": "加载中...",
|
||||||
"zh-TW": "載入中...",
|
"zh-TW": "載入中...",
|
||||||
"sv": "Laddar...",
|
"sv": "Laddar...",
|
||||||
|
"bg": "Зареждане...",
|
||||||
}
|
}
|
||||||
|
|
||||||
var keys []string
|
var keys []string
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package policy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/TecharoHQ/anubis/internal/dns"
|
||||||
|
"github.com/TecharoHQ/anubis/lib/config"
|
||||||
|
"github.com/TecharoHQ/anubis/lib/store/memory"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTestDNS(t *testing.T) *dns.Dns {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
ctx := t.Context()
|
||||||
|
memStore := memory.New(ctx)
|
||||||
|
cache := dns.NewDNSCache(300, 300, memStore)
|
||||||
|
return dns.New(ctx, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCELChecker_MapIterationWrappers(t *testing.T) {
|
||||||
|
cfg := &config.ExpressionOrList{
|
||||||
|
Expression: `headers.exists(k, k == "Accept") && query.exists(k, k == "format")`,
|
||||||
|
}
|
||||||
|
|
||||||
|
checker, err := NewCELChecker(cfg, newTestDNS(t))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("creating CEL checker failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, "https://example.com/?format=json", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("making request failed: %v", err)
|
||||||
|
}
|
||||||
|
req.Header.Set("Accept", "application/json")
|
||||||
|
|
||||||
|
got, err := checker.Check(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("checking expression failed: %v", err)
|
||||||
|
}
|
||||||
|
if !got {
|
||||||
|
t.Fatal("expected expression to evaluate true")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,7 +66,9 @@ func (h HTTPHeaders) Get(key ref.Val) ref.Val {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h HTTPHeaders) Iterator() traits.Iterator { panic("TODO(Xe): implement me") }
|
func (h HTTPHeaders) Iterator() traits.Iterator {
|
||||||
|
return newMapIterator(h.Header)
|
||||||
|
}
|
||||||
|
|
||||||
func (h HTTPHeaders) IsZeroValue() bool {
|
func (h HTTPHeaders) IsZeroValue() bool {
|
||||||
return len(h.Header) == 0
|
return len(h.Header) == 0
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package expressions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"maps"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
|
||||||
|
"github.com/google/cel-go/common/types"
|
||||||
|
"github.com/google/cel-go/common/types/ref"
|
||||||
|
"github.com/google/cel-go/common/types/traits"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrNotImplemented = errors.New("expressions: not implemented")
|
||||||
|
|
||||||
|
type stringSliceIterator struct {
|
||||||
|
keys []string
|
||||||
|
idx int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) Value() any {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) ConvertToNative(typeDesc reflect.Type) (any, error) {
|
||||||
|
return nil, ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) ConvertToType(typeValue ref.Type) ref.Val {
|
||||||
|
return types.NewErr("can't convert from %q to %q", types.IteratorType, typeValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) Equal(other ref.Val) ref.Val {
|
||||||
|
return types.NewErr("can't compare %q to %q", types.IteratorType, other.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) Type() ref.Type {
|
||||||
|
return types.IteratorType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) HasNext() ref.Val {
|
||||||
|
return types.Bool(s.idx < len(s.keys))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceIterator) Next() ref.Val {
|
||||||
|
if s.HasNext() != types.True {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
val := s.keys[s.idx]
|
||||||
|
s.idx++
|
||||||
|
return types.String(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMapIterator(m map[string][]string) traits.Iterator {
|
||||||
|
return &stringSliceIterator{
|
||||||
|
keys: slices.Collect(maps.Keys(m)),
|
||||||
|
idx: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package expressions
|
package expressions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -11,8 +10,6 @@ import (
|
|||||||
"github.com/google/cel-go/common/types/traits"
|
"github.com/google/cel-go/common/types/traits"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrNotImplemented = errors.New("expressions: not implemented")
|
|
||||||
|
|
||||||
// URLValues is a type wrapper to expose url.Values into CEL programs.
|
// URLValues is a type wrapper to expose url.Values into CEL programs.
|
||||||
type URLValues struct {
|
type URLValues struct {
|
||||||
url.Values
|
url.Values
|
||||||
@@ -69,7 +66,9 @@ func (u URLValues) Get(key ref.Val) ref.Val {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u URLValues) Iterator() traits.Iterator { panic("TODO(Xe): implement me") }
|
func (u URLValues) Iterator() traits.Iterator {
|
||||||
|
return newMapIterator(u.Values)
|
||||||
|
}
|
||||||
|
|
||||||
func (u URLValues) IsZeroValue() bool {
|
func (u URLValues) IsZeroValue() bool {
|
||||||
return len(u.Values) == 0
|
return len(u.Values) == 0
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ func ParseConfig(ctx context.Context, fin io.Reader, fname string, defaultDiffic
|
|||||||
|
|
||||||
switch c.Logging.Sink {
|
switch c.Logging.Sink {
|
||||||
case config.LogSinkStdio:
|
case config.LogSinkStdio:
|
||||||
result.Logger = internal.InitSlog(logLevel, os.Stderr)
|
result.Logger = internal.InitSlog(logLevel, os.Stderr, c.Logging.HideSource)
|
||||||
case config.LogSinkFile:
|
case config.LogSinkFile:
|
||||||
out := &logrotate.Logger{
|
out := &logrotate.Logger{
|
||||||
Filename: c.Logging.Parameters.Filename,
|
Filename: c.Logging.Parameters.Filename,
|
||||||
@@ -87,7 +87,7 @@ func ParseConfig(ctx context.Context, fin io.Reader, fname string, defaultDiffic
|
|||||||
Compress: c.Logging.Parameters.Compress,
|
Compress: c.Logging.Parameters.Compress,
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Logger = internal.InitSlog(logLevel, out)
|
result.Logger = internal.InitSlog(logLevel, out, c.Logging.HideSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
lg := result.Logger.With("at", "config-validate")
|
lg := result.Logger.With("at", "config-validate")
|
||||||
|
|||||||
+3
-10
@@ -41,22 +41,15 @@ cp ../lib/localization/locales/*.json static/locales/
|
|||||||
|
|
||||||
shopt -s nullglob globstar
|
shopt -s nullglob globstar
|
||||||
|
|
||||||
for file in js/**/*.ts js/**/*.tsx js/**/*.mjs; do
|
for file in js/**/*.ts js/**/*.mjs; do
|
||||||
out="static/${file}"
|
out="static/${file}"
|
||||||
if [[ "$file" == *.tsx ]]; then
|
if [[ "$file" == *.ts ]]; then
|
||||||
out="static/${file%.tsx}.mjs"
|
|
||||||
elif [[ "$file" == *.ts ]]; then
|
|
||||||
out="static/${file%.ts}.mjs"
|
out="static/${file%.ts}.mjs"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$(dirname "$out")"
|
mkdir -p "$(dirname "$out")"
|
||||||
|
|
||||||
JSX_FLAGS=""
|
esbuild "$file" --sourcemap --bundle --minify --outfile="$out" --banner:js="$LICENSE"
|
||||||
if [[ "$file" == *.tsx ]]; then
|
|
||||||
JSX_FLAGS="--jsx=automatic --jsx-import-source=preact"
|
|
||||||
fi
|
|
||||||
|
|
||||||
esbuild "$file" --sourcemap --bundle --minify --outfile="$out" $JSX_FLAGS --banner:js="$LICENSE"
|
|
||||||
gzip -f -k -n "$out"
|
gzip -f -k -n "$out"
|
||||||
zstd -f -k --ultra -22 "$out"
|
zstd -f -k --ultra -22 "$out"
|
||||||
brotli -fZk "$out"
|
brotli -fZk "$out"
|
||||||
|
|||||||
+281
@@ -0,0 +1,281 @@
|
|||||||
|
import algorithms from "./algorithms";
|
||||||
|
|
||||||
|
// from Xeact
|
||||||
|
const u = (url: string = "", params: Record<string, any> = {}) => {
|
||||||
|
let result = new URL(url, window.location.href);
|
||||||
|
Object.entries(params).forEach(([k, v]) => result.searchParams.set(k, v));
|
||||||
|
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) =>
|
||||||
|
u(`${basePrefix}/.within.website/x/cmd/anubis/static/img/${mood}.webp`, {
|
||||||
|
cacheBuster,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Detect available languages by loading the manifest
|
||||||
|
const getAvailableLanguages = async () => {
|
||||||
|
const basePrefix = j("anubis_base_prefix");
|
||||||
|
if (basePrefix === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${basePrefix}/.within.website/x/cmd/anubis/static/locales/manifest.json`,
|
||||||
|
);
|
||||||
|
if (response.ok) {
|
||||||
|
const manifest = await response.json();
|
||||||
|
return manifest.supportedLanguages || ["en"];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(
|
||||||
|
"Failed to load language manifest, falling back to default languages",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to default languages if manifest loading fails
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Load translations from JSON files
|
||||||
|
const loadTranslations = async (lang) => {
|
||||||
|
const basePrefix = j("anubis_base_prefix");
|
||||||
|
if (basePrefix === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${basePrefix}/.within.website/x/cmd/anubis/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");
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRedirectUrl = () => {
|
||||||
|
const publicUrl = j("anubis_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 window.location.href;
|
||||||
|
};
|
||||||
|
|
||||||
|
let translations = {};
|
||||||
|
let currentLang;
|
||||||
|
|
||||||
|
// Initialize translations
|
||||||
|
const initTranslations = async () => {
|
||||||
|
currentLang = await getBrowserLanguage();
|
||||||
|
translations = await loadTranslations(currentLang);
|
||||||
|
};
|
||||||
|
|
||||||
|
const t = (key) => translations[`js_${key}`] || translations[key] || key;
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
// Initialize translations first
|
||||||
|
await initTranslations();
|
||||||
|
|
||||||
|
const dependencies = [
|
||||||
|
{
|
||||||
|
name: "Web Workers",
|
||||||
|
msg: t("web_workers_error"),
|
||||||
|
value: window.Worker,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cookies",
|
||||||
|
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 anubisVersion = j("anubis_version");
|
||||||
|
const basePrefix = j("anubis_base_prefix");
|
||||||
|
const details = document.querySelector("details");
|
||||||
|
let userReadDetails = false;
|
||||||
|
|
||||||
|
if (details) {
|
||||||
|
details.addEventListener("toggle", () => {
|
||||||
|
if (details.open) {
|
||||||
|
userReadDetails = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const ohNoes = ({ titleMsg, statusMsg, imageSrc }) => {
|
||||||
|
title.innerHTML = titleMsg;
|
||||||
|
status.innerHTML = statusMsg;
|
||||||
|
image.src = imageSrc;
|
||||||
|
progress.style.display = "none";
|
||||||
|
};
|
||||||
|
|
||||||
|
status.innerHTML = t("calculating");
|
||||||
|
|
||||||
|
for (const { value, name, msg } of dependencies) {
|
||||||
|
if (!value) {
|
||||||
|
ohNoes({
|
||||||
|
titleMsg: `${t("missing_feature")} ${name}`,
|
||||||
|
statusMsg: msg,
|
||||||
|
imageSrc: imageURL("reject", anubisVersion, basePrefix),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { challenge, rules } = j("anubis_challenge");
|
||||||
|
|
||||||
|
const process = algorithms[rules.algorithm];
|
||||||
|
if (!process) {
|
||||||
|
ohNoes({
|
||||||
|
titleMsg: t("challenge_error"),
|
||||||
|
statusMsg: t("challenge_error_msg"),
|
||||||
|
imageSrc: imageURL("reject", anubisVersion, basePrefix),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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`);
|
||||||
|
status.appendChild(rateText);
|
||||||
|
|
||||||
|
let lastSpeedUpdate = 0;
|
||||||
|
let showingApology = false;
|
||||||
|
const likelihood = Math.pow(16, -rules.difficulty);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const t0 = Date.now();
|
||||||
|
const { hash, nonce } = await process(
|
||||||
|
{ basePrefix, version: anubisVersion },
|
||||||
|
challenge.randomData,
|
||||||
|
rules.difficulty,
|
||||||
|
null,
|
||||||
|
(iters) => {
|
||||||
|
const delta = Date.now() - t0;
|
||||||
|
// 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`;
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
// apply a polynomial ease-out function to move faster in the beginning
|
||||||
|
// and then slow down as things get increasingly unlikely. quadratic felt
|
||||||
|
// the best in testing, but this may need adjustment in the future.
|
||||||
|
|
||||||
|
const probability = Math.pow(1 - likelihood, iters);
|
||||||
|
const distance = (1 - Math.pow(probability, 2)) * 100;
|
||||||
|
progress["aria-valuenow"] = distance;
|
||||||
|
if (progress.firstElementChild !== null) {
|
||||||
|
(progress.firstElementChild as HTMLElement).style.width =
|
||||||
|
`${distance}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (probability < 0.1 && !showingApology) {
|
||||||
|
status.append(
|
||||||
|
document.createElement("br"),
|
||||||
|
document.createTextNode(t("verification_longer")),
|
||||||
|
);
|
||||||
|
showingApology = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const t1 = Date.now();
|
||||||
|
console.log({ hash, nonce });
|
||||||
|
|
||||||
|
if (userReadDetails) {
|
||||||
|
const container: HTMLDivElement = document.getElementById(
|
||||||
|
"progress",
|
||||||
|
) as HTMLDivElement;
|
||||||
|
|
||||||
|
// Style progress bar as a continue button
|
||||||
|
container.style.display = "flex";
|
||||||
|
container.style.alignItems = "center";
|
||||||
|
container.style.justifyContent = "center";
|
||||||
|
container.style.height = "2rem";
|
||||||
|
container.style.borderRadius = "1rem";
|
||||||
|
container.style.cursor = "pointer";
|
||||||
|
container.style.background = "#b16286";
|
||||||
|
container.style.color = "white";
|
||||||
|
container.style.fontWeight = "bold";
|
||||||
|
container.style.outline = "4px solid #b16286";
|
||||||
|
container.style.outlineOffset = "2px";
|
||||||
|
container.style.width = "min(20rem, 90%)";
|
||||||
|
container.style.margin = "1rem auto 2rem";
|
||||||
|
container.innerHTML = t("finished_reading");
|
||||||
|
|
||||||
|
function onDetailsExpand() {
|
||||||
|
const redir = getRedirectUrl();
|
||||||
|
window.location.replace(
|
||||||
|
u(`${basePrefix}/.within.website/x/cmd/anubis/api/pass-challenge`, {
|
||||||
|
id: challenge.id,
|
||||||
|
response: hash,
|
||||||
|
nonce,
|
||||||
|
redir,
|
||||||
|
elapsedTime: t1 - t0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
container.onclick = onDetailsExpand;
|
||||||
|
setTimeout(onDetailsExpand, 30000);
|
||||||
|
} else {
|
||||||
|
const redir = getRedirectUrl();
|
||||||
|
window.location.replace(
|
||||||
|
u(`${basePrefix}/.within.website/x/cmd/anubis/api/pass-challenge`, {
|
||||||
|
id: challenge.id,
|
||||||
|
response: hash,
|
||||||
|
nonce,
|
||||||
|
redir,
|
||||||
|
elapsedTime: t1 - t0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ohNoes({
|
||||||
|
titleMsg: t("calculation_error"),
|
||||||
|
statusMsg: `${t("calculation_error_msg")} ${err.message}`,
|
||||||
|
imageSrc: imageURL("reject", anubisVersion, basePrefix),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
-336
@@ -1,336 +0,0 @@
|
|||||||
import { render } from "preact";
|
|
||||||
import { useState, useEffect, useRef } from "preact/hooks";
|
|
||||||
import algorithms from "./algorithms";
|
|
||||||
|
|
||||||
// from Xeact
|
|
||||||
const u = (url: string = "", params: Record<string, any> = {}) => {
|
|
||||||
let result = new URL(url, window.location.href);
|
|
||||||
Object.entries(params).forEach(([k, v]) => result.searchParams.set(k, v));
|
|
||||||
return result.toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
const j = (id: string): any | null => {
|
|
||||||
const elem = document.getElementById(id);
|
|
||||||
if (elem === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const text = elem.textContent;
|
|
||||||
if (text == null || text.trim() === "") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSON.parse(text);
|
|
||||||
};
|
|
||||||
|
|
||||||
const imageURL = (
|
|
||||||
mood: string,
|
|
||||||
cacheBuster: string,
|
|
||||||
basePrefix: string,
|
|
||||||
): string =>
|
|
||||||
u(`${basePrefix}/.within.website/x/cmd/anubis/static/img/${mood}.webp`, {
|
|
||||||
cacheBuster,
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Load translations from JSON files
|
|
||||||
const loadTranslations = async (lang: string) => {
|
|
||||||
const basePrefix = j("anubis_base_prefix");
|
|
||||||
if (basePrefix === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`${basePrefix}/.within.website/x/cmd/anubis/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");
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getRedirectUrl = () => {
|
|
||||||
const publicUrl = j("anubis_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 window.location.href;
|
|
||||||
};
|
|
||||||
|
|
||||||
let translations: Record<string, string> = {};
|
|
||||||
|
|
||||||
// Initialize translations
|
|
||||||
const initTranslations = async () => {
|
|
||||||
const currentLang = await getBrowserLanguage();
|
|
||||||
translations = await loadTranslations(currentLang);
|
|
||||||
};
|
|
||||||
|
|
||||||
const t = (key: string): string =>
|
|
||||||
translations[`js_${key}`] || translations[key] || key;
|
|
||||||
|
|
||||||
interface AppProps {
|
|
||||||
anubisVersion: string;
|
|
||||||
basePrefix: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function App({ anubisVersion, basePrefix }: AppProps) {
|
|
||||||
const [phase, setPhase] = useState<
|
|
||||||
"loading" | "computing" | "reading" | "error"
|
|
||||||
>("loading");
|
|
||||||
|
|
||||||
// Error info
|
|
||||||
const [errorTitle, setErrorTitle] = useState("");
|
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
|
||||||
const [errorImage, setErrorImage] = useState("");
|
|
||||||
|
|
||||||
// Computing info
|
|
||||||
const [difficulty, setDifficulty] = useState(0);
|
|
||||||
const [speed, setSpeed] = useState("0kH/s");
|
|
||||||
const [progress, setProgress] = useState(0);
|
|
||||||
const [showApology, setShowApology] = useState(false);
|
|
||||||
|
|
||||||
// Reading redirect callback
|
|
||||||
const redirectFn = useRef<(() => void) | null>(null);
|
|
||||||
const detailsRead = useRef(false);
|
|
||||||
|
|
||||||
// Sync <h1 id="title"> when entering error state (it's outside the Preact tree)
|
|
||||||
useEffect(() => {
|
|
||||||
if (phase === "error") {
|
|
||||||
const titleEl = document.getElementById("title");
|
|
||||||
if (titleEl) {
|
|
||||||
titleEl.textContent = errorTitle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [phase, errorTitle]);
|
|
||||||
|
|
||||||
// Main initialization
|
|
||||||
useEffect(() => {
|
|
||||||
const details = document.querySelector("details");
|
|
||||||
if (details) {
|
|
||||||
details.addEventListener("toggle", () => {
|
|
||||||
if (details.open) {
|
|
||||||
detailsRead.current = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const showError = (title: string, message: string, imageSrc: string) => {
|
|
||||||
setErrorTitle(title);
|
|
||||||
setErrorMessage(message);
|
|
||||||
setErrorImage(imageSrc);
|
|
||||||
setPhase("error");
|
|
||||||
};
|
|
||||||
|
|
||||||
const dependencies = [
|
|
||||||
{
|
|
||||||
name: "Web Workers",
|
|
||||||
msg: t("web_workers_error"),
|
|
||||||
value: window.Worker,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Cookies",
|
|
||||||
msg: t("cookies_error"),
|
|
||||||
value: navigator.cookieEnabled,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const { value, name, msg } of dependencies) {
|
|
||||||
if (!value) {
|
|
||||||
showError(
|
|
||||||
`${t("missing_feature")} ${name}`,
|
|
||||||
msg,
|
|
||||||
imageURL("reject", anubisVersion, basePrefix),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const challengeData = j("anubis_challenge");
|
|
||||||
if (!challengeData) {
|
|
||||||
showError(
|
|
||||||
t("challenge_error"),
|
|
||||||
t("challenge_data_missing"),
|
|
||||||
imageURL("reject", anubisVersion, basePrefix),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { challenge, rules } = challengeData;
|
|
||||||
|
|
||||||
const process = algorithms[rules.algorithm];
|
|
||||||
if (!process) {
|
|
||||||
showError(
|
|
||||||
t("challenge_error"),
|
|
||||||
t("challenge_error_msg"),
|
|
||||||
imageURL("reject", anubisVersion, basePrefix),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setPhase("computing");
|
|
||||||
setDifficulty(rules.difficulty);
|
|
||||||
|
|
||||||
const likelihood = Math.pow(16, -rules.difficulty);
|
|
||||||
let lastSpeedUpdate = 0;
|
|
||||||
let apologyShown = false;
|
|
||||||
const t0 = Date.now();
|
|
||||||
|
|
||||||
process(
|
|
||||||
{ basePrefix, version: anubisVersion },
|
|
||||||
challenge.randomData,
|
|
||||||
rules.difficulty,
|
|
||||||
null,
|
|
||||||
(iters: number) => {
|
|
||||||
const delta = Date.now() - t0;
|
|
||||||
// only update the speed every second so it's less visually distracting
|
|
||||||
if (delta - lastSpeedUpdate > 1000) {
|
|
||||||
lastSpeedUpdate = delta;
|
|
||||||
setSpeed(`${(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
|
|
||||||
// apply a polynomial ease-out function to move faster in the beginning
|
|
||||||
// and then slow down as things get increasingly unlikely. quadratic felt
|
|
||||||
// the best in testing, but this may need adjustment in the future.
|
|
||||||
|
|
||||||
const probability = Math.pow(1 - likelihood, iters);
|
|
||||||
const distance = (1 - Math.pow(probability, 2)) * 100;
|
|
||||||
setProgress(distance);
|
|
||||||
|
|
||||||
if (probability < 0.1 && !apologyShown) {
|
|
||||||
apologyShown = true;
|
|
||||||
setShowApology(true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.then((result: any) => {
|
|
||||||
const t1 = Date.now();
|
|
||||||
const { hash, nonce } = result;
|
|
||||||
console.log({ hash, nonce });
|
|
||||||
|
|
||||||
const doRedirect = () => {
|
|
||||||
const redir = getRedirectUrl();
|
|
||||||
window.location.replace(
|
|
||||||
u(`${basePrefix}/.within.website/x/cmd/anubis/api/pass-challenge`, {
|
|
||||||
id: challenge.id,
|
|
||||||
response: hash,
|
|
||||||
nonce,
|
|
||||||
redir,
|
|
||||||
elapsedTime: t1 - t0,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (detailsRead.current) {
|
|
||||||
redirectFn.current = doRedirect;
|
|
||||||
setPhase("reading");
|
|
||||||
setTimeout(doRedirect, 30000);
|
|
||||||
} else {
|
|
||||||
doRedirect();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err: Error) => {
|
|
||||||
showError(
|
|
||||||
t("calculation_error"),
|
|
||||||
`${t("calculation_error_msg")} ${err.message}`,
|
|
||||||
imageURL("reject", anubisVersion, basePrefix),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const pensiveURL = imageURL("pensive", anubisVersion, basePrefix);
|
|
||||||
|
|
||||||
if (phase === "error") {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<img style="width:100%;max-width:256px;" src={errorImage} />
|
|
||||||
<p id="status">{errorMessage}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phase === "loading") {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<img style="width:100%;max-width:256px;" src={pensiveURL} />
|
|
||||||
<p id="status">{t("calculating")}</p>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// computing or reading
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<img style="width:100%;max-width:256px;" src={pensiveURL} />
|
|
||||||
<p id="status">
|
|
||||||
{`${t("calculating_difficulty")} ${difficulty}, `}
|
|
||||||
{`${t("speed")} ${speed}`}
|
|
||||||
{showApology && (
|
|
||||||
<>
|
|
||||||
<br />
|
|
||||||
{t("verification_longer")}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
{phase === "reading" ? (
|
|
||||||
<button
|
|
||||||
id="progress"
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
height: "2rem",
|
|
||||||
borderRadius: "1rem",
|
|
||||||
cursor: "pointer",
|
|
||||||
background: "#b16286",
|
|
||||||
color: "white",
|
|
||||||
fontWeight: "bold",
|
|
||||||
outline: "4px solid #b16286",
|
|
||||||
outlineOffset: "2px",
|
|
||||||
width: "min(20rem, 90%)",
|
|
||||||
margin: "1rem auto 2rem",
|
|
||||||
border: "none",
|
|
||||||
fontSize: "inherit",
|
|
||||||
fontFamily: "inherit",
|
|
||||||
}}
|
|
||||||
onClick={() => redirectFn.current?.()}
|
|
||||||
>
|
|
||||||
{t("finished_reading")}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
id="progress"
|
|
||||||
role="progressbar"
|
|
||||||
aria-labelledby="status"
|
|
||||||
aria-valuenow={progress}
|
|
||||||
style={{ display: "inline-block" }}
|
|
||||||
>
|
|
||||||
<div class="bar-inner" style={{ width: `${progress}%` }}></div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bootstrap: init translations, then mount Preact
|
|
||||||
(async () => {
|
|
||||||
await initTranslations();
|
|
||||||
const anubisVersion = j("anubis_version");
|
|
||||||
const basePrefix = j("anubis_base_prefix");
|
|
||||||
const root = document.getElementById("app");
|
|
||||||
if (root) {
|
|
||||||
render(<App anubisVersion={anubisVersion} basePrefix={basePrefix} />, root);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ES2020",
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"jsxImportSource": "preact",
|
|
||||||
"noEmit": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"strict": false
|
|
||||||
},
|
|
||||||
"include": ["js/**/*.ts", "js/**/*.tsx"]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user