html: add noto sans subset

This commit is contained in:
Vaxry
2025-04-13 16:53:17 +01:00
parent 5a0d332466
commit b5ee8880ff
6 changed files with 20 additions and 3 deletions

View File

@@ -12,7 +12,7 @@ AI scrapers are everywhere. This will stop them. `robots.txt` won't.
- Protect your endpoint from AI bots with a cryptographic challenge
- Easy configuration in jsonc
- Support for cloudflare
- Minimal. The waiting page is a single file with no links that weighs 4kB
- Minimal. The waiting page is tiny and light on network usage.
### Planned features
- Dynamic challenge amount (aka difficulty)

BIN
html/NotoSans.woff Normal file

Binary file not shown.

View File

@@ -7,8 +7,13 @@
<body style="background-color: #0e0e0e; overflow: hidden;">
<style>
@font-face {
font-family: "Noto Sans";
src: url("/checkpoint/NotoSans.woff");
}
* {
font-family: serif;
font-family: "Noto Sans";
}
.middle-box {

View File

@@ -1,2 +1,2 @@
<!DOCTYPE html><head><title>STOP! - Checkpoint</title></head><body style="background-color:#0e0e0e;overflow:hidden"><style>*{font-family:serif}.middle-box{display:block;position:absolute;width:30rem;height:calc(100% - 2rem);left:calc(50% - 15rem);top:1rem;background-color:#111;border-radius:.5rem;border:1px solid #280d0e}.big-icon{margin:0;padding:0;font-size:8rem;color:#fff;width:100%;text-align:center}.subtext{margin:0;padding:0;font-size:3rem;color:#d9d9d9;width:100%;text-align:center}.text-hr{margin:auto;margin-top:1rem;margin-bottom:1rem;padding:0;background-color:#444;width:50%;box-shadow:none;text-align:center;height:1px;border:none}.text-hr-small{margin:auto;margin-top:1rem;margin-bottom:1rem;padding:0;background-color:#444;width:25%;box-shadow:none;text-align:center;height:1px;border:none}.text-description{margin:0;padding:0;font-size:1rem;color:#d9d9d9;width:85%;margin-left:7.5%;text-align:center}.text-question{margin:0;margin-top:4rem;padding:0;font-size:1.4rem;color:#d9d9d9;width:85%;margin-left:7.5%;text-align:center}.bottom-bar{position:absolute;width:100%;height:auto;bottom:.4rem;left:0}.bottom-hash-text{margin:0;padding:0;font-size:1rem;color:#d9d9d9;width:85%;margin-left:7.5%;text-align:center}.bottom-credit-text{display:block;margin:0;padding:0;font-size:.5rem;color:#4b4b4b;width:98%;text-align:right;transition:ease-in-out .1s;margin-top:.2rem}.bottom-credit-text:hover,.bottom-credit-text:link:hover,.bottom-credit-text:visited:hover{color:#764343;cursor:pointer}.bottom-credit-text:link,.bottom-credit-text:visited{color:#4b4b4b}.bottom-progress{position:relative;height:3px;background-color:#222;width:80%;margin-left:10%;margin-bottom:.8rem}.bottom-progress-light{position:absolute;left:0;top:0;width:0%;height:3px;background-color:#692225;transition:ease-in-out .1s}@media (pointer:none),(pointer:coarse){.big-icon{margin-top:10rem}.middle-box{width:90%;left:5%}.subtext{font-size:6rem}.text-description{font-size:3rem}.text-hr{height:3px}.bottom-hash-text{font-size:2.5rem}.bottom-credit-text{font-size:1rem}}</style><div class="middle-box"><p class="big-icon">&#128721;</p><p class="subtext" id="subtext">STOP!</p><hr class="text-hr"><p class="text-description">Verifying that you are not a bot. This might take a short moment.<br><br>You do not need to do anything.</p><p class="text-question">Why am I seeing this?</p><hr class="text-hr-small"><p class="text-description">This website protects itself from AI bots and scrapers by asking you to complete a cryptographic challenge before allowing you entry.</p><div class="bottom-bar"><div class="bottom-progress"><div class="bottom-progress-light" name="progress-light"></div></div><p class="bottom-hash-text" id="results">Difficulty {{ tl:text challengeDifficulty }}, elapsed 0ms, 0h, 0h/s</p><a class="bottom-credit-text"><i>Powered by checkpoint v{{ tl:text checkpointVersion }}</i></a></div></div>
<!DOCTYPE html><head><title>STOP! - Checkpoint</title></head><body style="background-color:#0e0e0e;overflow:hidden"><style>@font-face{font-family:"Noto Sans";src:url(/checkpoint/NotoSans.woff)}*{font-family:"Noto Sans"}.middle-box{display:block;position:absolute;width:30rem;height:calc(100% - 2rem);left:calc(50% - 15rem);top:1rem;background-color:#111;border-radius:.5rem;border:1px solid #280d0e}.big-icon{margin:0;padding:0;font-size:8rem;color:#fff;width:100%;text-align:center}.subtext{margin:0;padding:0;font-size:3rem;color:#d9d9d9;width:100%;text-align:center}.text-hr{margin:auto;margin-top:1rem;margin-bottom:1rem;padding:0;background-color:#444;width:50%;box-shadow:none;text-align:center;height:1px;border:none}.text-hr-small{margin:auto;margin-top:1rem;margin-bottom:1rem;padding:0;background-color:#444;width:25%;box-shadow:none;text-align:center;height:1px;border:none}.text-description{margin:0;padding:0;font-size:1rem;color:#d9d9d9;width:85%;margin-left:7.5%;text-align:center}.text-question{margin:0;margin-top:4rem;padding:0;font-size:1.4rem;color:#d9d9d9;width:85%;margin-left:7.5%;text-align:center}.bottom-bar{position:absolute;width:100%;height:auto;bottom:.4rem;left:0}.bottom-hash-text{margin:0;padding:0;font-size:1rem;color:#d9d9d9;width:85%;margin-left:7.5%;text-align:center}.bottom-credit-text{display:block;margin:0;padding:0;font-size:.5rem;color:#4b4b4b;width:98%;text-align:right;transition:ease-in-out .1s;margin-top:.2rem}.bottom-credit-text:hover,.bottom-credit-text:link:hover,.bottom-credit-text:visited:hover{color:#764343;cursor:pointer}.bottom-credit-text:link,.bottom-credit-text:visited{color:#4b4b4b}.bottom-progress{position:relative;height:3px;background-color:#222;width:80%;margin-left:10%;margin-bottom:.8rem}.bottom-progress-light{position:absolute;left:0;top:0;width:0%;height:3px;background-color:#692225;transition:ease-in-out .1s}@media (pointer:none),(pointer:coarse){.big-icon{margin-top:10rem}.middle-box{width:90%;left:5%}.subtext{font-size:6rem}.text-description{font-size:3rem}.text-hr{height:3px}.bottom-hash-text{font-size:2.5rem}.bottom-credit-text{font-size:1rem}}</style><div class="middle-box"><p class="big-icon">&#128721;</p><p class="subtext" id="subtext">STOP!</p><hr class="text-hr"><p class="text-description">Verifying that you are not a bot. This might take a short moment.<br><br>You do not need to do anything.</p><p class="text-question">Why am I seeing this?</p><hr class="text-hr-small"><p class="text-description">This website protects itself from AI bots and scrapers by asking you to complete a cryptographic challenge before allowing you entry.</p><div class="bottom-bar"><div class="bottom-progress"><div class="bottom-progress-light" name="progress-light"></div></div><p class="bottom-hash-text" id="results">Difficulty {{ tl:text challengeDifficulty }}, elapsed 0ms, 0h, 0h/s</p><a class="bottom-credit-text"><i>Powered by checkpoint v{{ tl:text checkpointVersion }}</i></a></div></div>
<script type="text/javascript">setTimeout(async function(){var e=0,t=Date.now();let n="{{ tl:text challengeNonce }}",o=parseInt("{{ tl:text challengeDifficulty }}");function $(e){let t=o;for(let n=0;n<t;n+=1)if("0"!=e[n])return!1;return!0}function l(e){return e>1e6?parseInt(e/1e5)/10+"M":parseInt(e/100)/10+"k"}function r(e){return e>1e3?parseInt(e/100)/10+"s":e+"ms"}function i(e){return Math.floor((1-1/(Math.pow(e/Math.pow(2,4*o)*3,2)+1))*100)}function s(e){document.getElementById("results").innerHTML="Success! Completed challenge after "+l(e)+" iterations, in "+r(Math.floor(Date.now()-t))+".",document.getElementsByName("progress-light")[0].style.width="100%";let o=JSON.stringify({challenge:n,solution:e});fetch("/checkpoint/challenge",{headers:{"Content-Type":"application/json"},method:"POST",body:o}).then(e=>{200==e.status?(console.log("Got token."),e.json().then(e=>{document.cookie="CheckpointToken="+e.token+"; path=/",window.location.reload()})):console.log("Server error")})}let c=new TextEncoder;for(;;){let _=c.encode(n+e),a=await window.crypto.subtle.digest("SHA-256",_),u=Array.from(new Uint8Array(a)),f=u.map(e=>e.toString(16).padStart(2,"0")).join("");if($(f)){s(e),console.log("Success: it "+e+": "+f);break}if(++e%11377==0){let g=Math.floor(Date.now()-t),h=e/(g/1e3);document.getElementById("results").innerHTML="Difficulty: "+o+", elapsed "+r(g)+", "+l(e)+"h, "+l(h)+"h/s",document.getElementsByName("progress-light")[0].style.width=i(e)+"%"}}},100);var currentTitle=1;setInterval(()=>{let e=["STOP","HALT","ST&#0211;J","ARR&#0202;T","&#1057;&#1058;&#1030;&#1049;"];document.getElementById("subtext").innerHTML=e[currentTitle]+"!",++currentTitle>=e.length&&(currentTitle=0)},2e3);</script></body>

View File

@@ -145,6 +145,10 @@ std::string CServerHandler::fingerprintForRequest(const Pistache::Http::Request&
return sha256(input);
}
bool CServerHandler::isResourceCheckpoint(const std::string_view& res) {
return res == "/checkpoint/NotoSans.woff";
}
void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Http::ResponseWriter response) {
const auto HEADERS = req.headers();
std::shared_ptr<const Pistache::Http::Header::Host> hostHeader;
@@ -218,6 +222,12 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt
return;
}
if (isResourceCheckpoint(req.resource())) {
response.send(Pistache::Http::Code::Ok,
readFileAsText(g_pGlobalState->cwd + "/" + g_pConfig->m_config.html_dir + "/" + req.resource().substr(req.resource().find("checkpoint/") + 11)));
return;
}
if (g_pConfig->m_config.git_host) {
// TODO: ratelimit this, probably.

View File

@@ -24,6 +24,8 @@ class CServerHandler : public Pistache::Http::Handler {
void challengeSubmitted(const Pistache::Http::Request& req, Pistache::Http::ResponseWriter& response);
std::string fingerprintForRequest(const Pistache::Http::Request& req);
bool isResourceCheckpoint(const std::string_view& res);
struct SChallengeResponse {
std::string challenge;
unsigned long int solution = 0;