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) {
document.querySelector(selector)
.innerText = text;
function updateElem(selector, text, color) {
const updateElem = document.querySelector(selector);
if (updateElem) {
updateElem.innerText = text;
if (color) {
updateElem.style.color = color;
}
}
}
function insertError(str) {
@ -17,6 +22,13 @@ function finishRedirect() {
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 = (() => {
try {
if (typeof WebAssembly === "object"
@ -49,14 +61,14 @@ function postResponse(powResponse, captchaResponse) {
}).then(res => {
const s = res.status;
if (s >= 400 && s < 500) {
return insertError('bad challenge response request.');
return insertError('Server rejected your submission.');
} else if (s >= 500) {
return insertError('server responded with error.');
return insertError('Server encountered an error.');
}
window.localStorage.setItem('basedflare-redirect', Math.random());
finishRedirect();
}).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 = () => {
finished = true;
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());
};
const submitPow = (answer) => {
@ -106,7 +123,7 @@ const powFinished = new Promise(resolve => {
mode: mode,
};
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 [userkey, challenge] = pow.split("#");
if (window.Worker) {
@ -122,7 +139,8 @@ const powFinished = new Promise(resolve => {
const hps = Math.floor(totalHashes/elapsedSec);
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
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; }
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.remove();
powFinished.then(powResponse => {
updateElem('.powstatus', 'Submitting...', '#31cc31');
makeLoaderGreen();
postResponse(powResponse, captchaResponse);
});
}

View File

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