74 lines
2.9 KiB
JavaScript
74 lines
2.9 KiB
JavaScript
const form = document.querySelector('#access-form');
|
|
const input = document.querySelector('#access-number');
|
|
const button = document.querySelector('#enter-button');
|
|
const label = document.querySelector('#button-label');
|
|
const status = document.querySelector('#form-status');
|
|
const codeLength = Number(form.dataset.codeLength);
|
|
let waiting = false;
|
|
let cooldown;
|
|
|
|
function announce(message, success = false) {
|
|
status.textContent = message;
|
|
status.classList.toggle('success', success);
|
|
status.hidden = false;
|
|
}
|
|
|
|
input.addEventListener('input', () => {
|
|
input.removeAttribute('aria-invalid');
|
|
if (!waiting) status.hidden = true;
|
|
});
|
|
|
|
form.addEventListener('submit', async event => {
|
|
event.preventDefault();
|
|
if (waiting) return;
|
|
const code = input.value.replace(/\s/g, '');
|
|
if (!new RegExp(`^\\d{${codeLength}}$`).test(code)) {
|
|
input.setAttribute('aria-invalid', 'true');
|
|
announce(`Enter the ${codeLength}-digit number from your bot DM.`);
|
|
input.focus();
|
|
return;
|
|
}
|
|
waiting = true;
|
|
button.disabled = true;
|
|
form.setAttribute('aria-busy', 'true');
|
|
label.textContent = 'CHECKING YOUR NUMBER…';
|
|
status.hidden = true;
|
|
let retryAfter = 0;
|
|
let approved = false;
|
|
try {
|
|
const params = new URLSearchParams(location.search);
|
|
const next = location.pathname.startsWith('/_access') ? params.get('next') || '/' : location.pathname + location.search + location.hash;
|
|
const response = await fetch('/_access/login', {
|
|
method: 'POST', credentials: 'same-origin', headers: { 'content-type': 'application/json' },
|
|
body: JSON.stringify({ code, next }), signal: AbortSignal.timeout(15000),
|
|
});
|
|
const data = await response.json();
|
|
if (!response.ok) {
|
|
retryAfter = response.status === 429 ? Number(data.retryAfter) || 60 : 0;
|
|
if (response.status === 401) input.setAttribute('aria-invalid', 'true');
|
|
throw new Error(data.error || 'We could not check your number. Please try again.');
|
|
}
|
|
approved = true;
|
|
input.value = '';
|
|
announce('Access granted. Your next chapter is opening…', true);
|
|
label.textContent = 'OPENING THE GROUND…';
|
|
location.assign(data.next);
|
|
} catch (error) {
|
|
announce(error.name === 'TimeoutError' || error instanceof TypeError ? 'Connection interrupted. Check your connection and try again.' : error.message);
|
|
status.focus();
|
|
} finally {
|
|
form.removeAttribute('aria-busy');
|
|
if (retryAfter > 0) {
|
|
const deadline = Date.now() + retryAfter * 1000;
|
|
const tick = () => {
|
|
const seconds = Math.max(0, Math.ceil((deadline - Date.now()) / 1000));
|
|
label.textContent = `TRY AGAIN IN ${seconds}s`;
|
|
if (seconds === 0) { clearInterval(cooldown); waiting = false; button.disabled = false; label.textContent = 'ENTER THE ALPHA'; }
|
|
};
|
|
tick(); cooldown = setInterval(tick, 1000);
|
|
} else if (!approved) {
|
|
waiting = false; button.disabled = false; label.textContent = 'ENTER THE ALPHA';
|
|
}
|
|
}
|
|
});
|