Improve appearance and affordance of challenge pages with some template and js tweaks

This commit is contained in:
Thomas Lynch
2023-03-19 13:07:12 +11:00
parent 9478892614
commit 94567f69ff
4 changed files with 63 additions and 41 deletions

View File

@ -0,0 +1,2 @@
127.0.0.1 1
127.0.0.1/captcha 2

View File

@ -1 +0,0 @@
localhost cp.basedflare.com

View File

@ -1,6 +1,11 @@
function updateElem(selector, text) { function updateElem(selector, text, color) {
document.querySelector(selector) const updateElem = document.querySelector(selector);
.innerText = text; if (updateElem) {
updateElem.innerText = text;
if (color) {
updateElem.style.color = color;
}
}
} }
function insertError(str) { function insertError(str) {
@ -17,6 +22,13 @@ function finishRedirect() {
window.location=location.search.slice(1)+location.hash || "/"; window.location=location.search.slice(1)+location.hash || "/";
} }
function makeLoaderGreen() {
const dots = document.querySelectorAll('.b');
if (dots && dots.length > 0) {
dots.forEach(dot => dot.classList.add('green'));
}
}
const wasmSupported = (() => { const wasmSupported = (() => {
try { try {
if (typeof WebAssembly === "object" if (typeof WebAssembly === "object"
@ -49,14 +61,14 @@ function postResponse(powResponse, captchaResponse) {
}).then(res => { }).then(res => {
const s = res.status; const s = res.status;
if (s >= 400 && s < 500) { if (s >= 400 && s < 500) {
return insertError('bad challenge response request.'); return insertError('Server rejected your submission.');
} else if (s >= 500) { } else if (s >= 500) {
return insertError('server responded with error.'); return insertError('Server encountered an error.');
} }
window.localStorage.setItem('basedflare-redirect', Math.random()); window.localStorage.setItem('basedflare-redirect', Math.random());
finishRedirect(); finishRedirect();
}).catch(() => { }).catch(() => {
insertError('failed to send challenge response.'); insertError('Failed to send request to server.');
}); });
} }
@ -68,7 +80,12 @@ const powFinished = new Promise(resolve => {
const stopPow = () => { const stopPow = () => {
finished = true; finished = true;
const hasCaptcha = document.getElementById('captcha'); const hasCaptcha = document.getElementById('captcha');
updateElem('.powstatus', `Found proof-of-work solution.${!hasCaptcha?' Submitting...':''}`); if (hasCaptcha) {
updateElem('.powstatus', 'Proof-of-work completed.', '#31cc31');
} else {
updateElem('.powstatus', 'Proof-of-work completed. Submitting...', '#31cc31');
makeLoaderGreen();
}
workers.forEach(w => w.terminate()); workers.forEach(w => w.terminate());
}; };
const submitPow = (answer) => { const submitPow = (answer) => {
@ -106,7 +123,7 @@ const powFinished = new Promise(resolve => {
mode: mode, mode: mode,
}; };
console.log('Got pow', pow, 'with difficulty', diff); console.log('Got pow', pow, 'with difficulty', diff);
const eHashes = Math.pow(16, Math.floor(diff/8)) * ((diff%8)*2); const eHashes = Math.pow(16, Math.floor(diff/8)) * (((diff%8)*2)||1);
const diffString = '0'.repeat(Math.floor(diff/8)); const diffString = '0'.repeat(Math.floor(diff/8));
const [userkey, challenge] = pow.split("#"); const [userkey, challenge] = pow.split("#");
if (window.Worker) { if (window.Worker) {
@ -122,7 +139,8 @@ const powFinished = new Promise(resolve => {
const hps = Math.floor(totalHashes/elapsedSec); const hps = Math.floor(totalHashes/elapsedSec);
const requiredSec = Math.floor(eHashes/hps) * 1.5; //estimate 1.5x time const requiredSec = Math.floor(eHashes/hps) * 1.5; //estimate 1.5x time
const remainingSec = Math.max(0, Math.floor(requiredSec-elapsedSec)); //dont show negative time const remainingSec = Math.max(0, Math.floor(requiredSec-elapsedSec)); //dont show negative time
return updateElem('.powstatus', `Proof-of-work: ${hps}H/s, ~${remainingSec}s remaining`); console.log(`Proof-of-work: ${hps}H/s, ${remainingSec}s remaining`);
return updateElem('.powstatus', `Working... ≈${remainingSec}s remaining`);
} }
if (finished) { return; } if (finished) { return; }
const [workerId, answer] = e.data; const [workerId, answer] = e.data;
@ -158,6 +176,8 @@ function onCaptchaSubmit(captchaResponse) {
captchaElem.insertAdjacentHTML('afterend', `<div id="loader"><div class="b"></div><div class="b"></div><div class="b"></div></div>`); captchaElem.insertAdjacentHTML('afterend', `<div id="loader"><div class="b"></div><div class="b"></div><div class="b"></div></div>`);
captchaElem.remove(); captchaElem.remove();
powFinished.then(powResponse => { powFinished.then(powResponse => {
updateElem('.powstatus', 'Submitting...', '#31cc31');
makeLoaderGreen();
postResponse(powResponse, captchaResponse); postResponse(powResponse, captchaResponse);
}); });
} }

View File

@ -8,30 +8,31 @@ _M.body = [[
<meta name='viewport' content='width=device-width initial-scale=1'> <meta name='viewport' content='width=device-width initial-scale=1'>
<title>Hold on...</title> <title>Hold on...</title>
<style> <style>
:root{--text-color:#c5c8c6;--bg-color:#1d1f21} :root{--text-color:#c5c8c6;--bg-color:#1d1f21}
@media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#fff}} @media (prefers-color-scheme:light){:root{--text-color:#333;--bg-color:#fff}}
.h-captcha,.g-recaptcha{min-height:85px;display:block} .h-captcha,.g-recaptcha{min-height:85px;display:block}
.red{color:red;font-weight:bold} .red{color:red;font-weight:bold}
.left{text-align:left} .left{text-align:left}
.powstatus{color:green;font-size:small;} .powstatus{color:#6b93f7;font-size:small;}
a,a:visited{color:var(--text-color)} a,a:visited{color:var(--text-color)}
body,html{height:100%%;text-align:center;} body,html{height:100%%;text-align:center;}
body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Helvetica,Arial,sans-serif;max-width:60em;margin:0 auto;padding: 0 20px} body{display:flex;flex-direction:column;background-color:var(--bg-color);color:var(--text-color);font-family:Helvetica,Arial,sans-serif;max-width:60em;margin:0 auto;padding: 0 20px}
details{transition: border-left-color 0.5s;max-width:1200px;text-align:left;border-left: 2px solid var(--text-color);padding:10px} details{transition: border-left-color 0.5s;max-width:1200px;text-align:left;border-left: 2px solid var(--text-color);padding:10px}
code{background-color:#dfdfdf30;border-radius:4px;padding:0 3px;color:#ff6590} code{background-color:#dfdfdf30;border-radius:4px;padding:0 3px;color:#ff6590}
img,h3{margin:0 0 5px 0;font-weight:normal} img,h3{margin:0 0 5px 0;}
li{margin-bottom: 1em} li{margin-bottom: 1em}
footer{font-size:x-small;margin-top:auto;padding:10px;text-align:center;border-top:1px solid #80808040;padding:10px} footer{font-size:x-small;margin-top:auto;padding:10px;text-align:center;border-top:1px solid #80808040;padding:10px}
img{display:inline} img{display:inline}
textarea,input{background:var(--bg-color);color:var(--text-color);border:1px solid var(--text-color);width:100%%;box-sizing: border-box;resize:none;padding:0.5em;font-family:inherit} textarea,input{background:var(--bg-color);color:var(--text-color);border:1px solid var(--text-color);width:100%%;box-sizing: border-box;resize:none;padding:0.5em;font-family:inherit}
.pt{padding-top:30vh;display:flex;align-items:center;word-break:break-all;justify-content: center;} .pt{padding-top:30vh;word-wrap: break-word;}
.pt img{margin-right:10px} .pt img{margin-right:10px}
details[open]{border-left-color: #1400ff} details[open]{border-left-color: #1400ff}
.b{display:inline-block;background:#6b93f7;border-radius:50%%;margin:10px;height:16px;width:16px;box-shadow:0 0 0 0 #6b93f720;transform:scale(1)} .b{display:inline-block;border-radius:50%%;margin:10px;height:16px;width:16px;transform:scale(1);box-shadow:0 0 0 0 #6b93f720;background:#6b93f7;--shadow1:#6b93f790;--shadow2:#6b93f700;--shadow3:#6b93f700;}
.b:nth-of-type(1){animation:p 3s infinite} .b.green {background:#31cc31;box-shadow:0 0 0 0 #31cc3120;--shadow1:#31cc3190;--shadow2:#31cc3100;--shadow3:#31cc3100;}
.b:nth-of-type(2){animation:p 3s .5s infinite} .b:nth-of-type(1){animation:p 3s infinite}
.b:nth-of-type(3){animation:p 3s 1s infinite} .b:nth-of-type(2){animation:p 3s .5s infinite}
@keyframes p{0%%{transform:scale(.95);box-shadow:0 0 0 0 #6b93f790}70%%{transform:scale(1);box-shadow:0 0 0 10px #6b93f700}100%%{transform:scale(.95);box-shadow:0 0 0 0 #6b93f700}} .b:nth-of-type(3){animation:p 3s 1s infinite}
@keyframes p{0%%{transform:scale(.95);box-shadow:0 0 0 0 var(--shadow1)}70%%{transform:scale(1);box-shadow:0 0 0 10px var(--shadow2)}100%%{transform:scale(.95);box-shadow:0 0 0 0 var(--shadow3)}}
</style> </style>
<noscript> <noscript>
<style>.jsonly{display:none}</style> <style>.jsonly{display:none}</style>
@ -96,16 +97,16 @@ _M.noscript_extra_sha256 = [[
-- title with favicon and hostname -- title with favicon and hostname
_M.site_name_section = [[ _M.site_name_section = [[
<h3 class="pt"> <h3 class="pt">
<!-- img src="/favicon.ico" width="32" height="32" alt=" "> --> <!-- <img src="/favicon.ico" width="32" height="32" alt=" "> -->
%s Checking your browser before accessing %s
</h3> </h3>
]] ]]
-- animation while waiting -- animation while waiting
_M.pow_section = [[ _M.pow_section = [[
<h3> <p>
Checking your browser for robots 🤖 This process is automatic. Your browser will redirect to your requested content shortly.
</h3> </p>
<div class="jsonly"> <div class="jsonly">
<div id="loader"><div class="b"></div><div class="b"></div><div class="b"></div></div> <div id="loader"><div class="b"></div><div class="b"></div><div class="b"></div></div>
</div> </div>
@ -123,9 +124,9 @@ _M.pow_section = [[
-- message, captcha form and submit button -- message, captcha form and submit button
_M.captcha_section = [[ _M.captcha_section = [[
<h3> <p>
Please solve the captcha to continue. Please solve the captcha to continue.
</h3> </p>
<div id="captcha" class="jsonly"> <div id="captcha" class="jsonly">
<div class="%s" data-sitekey="%s" data-callback="onCaptchaSubmit"></div> <div class="%s" data-sitekey="%s" data-callback="onCaptchaSubmit"></div>
<script src="%s" async defer></script> <script src="%s" async defer></script>