2021-07-23 21:30:04 +02:00
|
|
|
import { b64Decode, getQsParam } from './common';
|
2021-06-22 21:35:33 +02:00
|
|
|
|
|
|
|
declare var hcaptcha: any;
|
|
|
|
|
2021-07-23 21:30:04 +02:00
|
|
|
if (window.location.pathname.includes('mobile')) {
|
|
|
|
// tslint:disable-next-line
|
|
|
|
require('./captcha-mobile.scss');
|
|
|
|
} else {
|
|
|
|
// tslint:disable-next-line
|
|
|
|
require('./captcha.scss');
|
|
|
|
}
|
2021-06-22 21:35:33 +02:00
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
init();
|
|
|
|
});
|
|
|
|
|
|
|
|
(window as any).captchaSuccess = captchaSuccess;
|
|
|
|
(window as any).captchaError = captchaError;
|
|
|
|
|
|
|
|
let parentUrl: string = null;
|
|
|
|
let parentOrigin: string = null;
|
2021-07-23 21:30:04 +02:00
|
|
|
let callbackUri: string = null;
|
2021-06-22 21:35:33 +02:00
|
|
|
let sentSuccess = false;
|
|
|
|
|
2021-07-23 21:30:04 +02:00
|
|
|
async function init() {
|
|
|
|
await start();
|
2021-06-22 21:35:33 +02:00
|
|
|
onMessage();
|
|
|
|
}
|
|
|
|
|
2021-07-23 21:30:04 +02:00
|
|
|
async function start() {
|
2021-06-22 21:35:33 +02:00
|
|
|
sentSuccess = false;
|
|
|
|
|
|
|
|
const data = getQsParam('data');
|
|
|
|
if (!data) {
|
|
|
|
error('No data.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
parentUrl = getQsParam('parent');
|
|
|
|
if (!parentUrl) {
|
|
|
|
error('No parent.');
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
parentUrl = decodeURIComponent(parentUrl);
|
|
|
|
parentOrigin = new URL(parentUrl).origin;
|
|
|
|
}
|
|
|
|
|
2021-07-23 21:30:04 +02:00
|
|
|
let decodedData: any;
|
|
|
|
try {
|
|
|
|
decodedData = JSON.parse(b64Decode(data));
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
error('Cannot parse data.');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
callbackUri = decodedData.callbackUri;
|
|
|
|
|
|
|
|
let src = 'https://hcaptcha.com/1/api.js?render=explicit';
|
|
|
|
|
|
|
|
// Set language code
|
|
|
|
if (decodedData.locale) {
|
|
|
|
src += `&hl=${decodedData.locale ?? 'en'}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set captchaRequired subtitle for mobile
|
|
|
|
const subtitleEl = document.getElementById('captchaRequired');
|
|
|
|
if (decodedData.captchaRequiredText && subtitleEl) {
|
|
|
|
subtitleEl.textContent = decodedData.captchaRequiredText;
|
|
|
|
}
|
|
|
|
|
|
|
|
const script = document.createElement('script');
|
|
|
|
script.src = src;
|
|
|
|
script.async = true;
|
|
|
|
script.defer = true;
|
|
|
|
script.addEventListener('load', e => {
|
|
|
|
hcaptcha.render('captcha', {
|
|
|
|
sitekey: decodedData.siteKey,
|
|
|
|
callback: 'captchaSuccess',
|
|
|
|
'error-callback': 'captchaError',
|
|
|
|
});
|
|
|
|
watchHeight();
|
2021-06-22 21:35:33 +02:00
|
|
|
});
|
2021-07-23 21:30:04 +02:00
|
|
|
document.head.appendChild(script);
|
2021-06-22 21:35:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function captchaSuccess(response: string) {
|
2021-07-23 21:30:04 +02:00
|
|
|
if (callbackUri) {
|
|
|
|
document.location.replace(callbackUri + '?token=' + encodeURIComponent(response));
|
2021-08-13 00:01:18 +02:00
|
|
|
} else {
|
|
|
|
success(response);
|
2021-07-23 21:30:04 +02:00
|
|
|
}
|
2021-06-22 21:35:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function captchaError() {
|
|
|
|
error('An error occurred with the captcha. Try again.');
|
|
|
|
}
|
|
|
|
|
|
|
|
function onMessage() {
|
|
|
|
window.addEventListener('message', event => {
|
|
|
|
if (!event.origin || event.origin === '' || event.origin !== parentOrigin) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.data === 'start') {
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
}, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
function error(message: string) {
|
|
|
|
parent.postMessage('error|' + message, parentUrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
function success(data: string) {
|
|
|
|
if (sentSuccess) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
parent.postMessage('success|' + data, parentUrl);
|
|
|
|
sentSuccess = true;
|
|
|
|
}
|
|
|
|
|
2021-07-23 21:30:04 +02:00
|
|
|
function info(message: string | object) {
|
|
|
|
parent.postMessage('info|' + JSON.stringify(message), parentUrl);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function watchHeight() {
|
|
|
|
const imagesDiv = document.body.lastChild as HTMLElement;
|
|
|
|
while (true) {
|
|
|
|
info({
|
|
|
|
height: imagesDiv.style.visibility === 'hidden' ?
|
|
|
|
document.documentElement.offsetHeight :
|
|
|
|
document.documentElement.scrollHeight,
|
|
|
|
width: document.documentElement.scrollWidth,
|
|
|
|
});
|
|
|
|
await sleep(100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function sleep(ms: number) {
|
|
|
|
await new Promise(r => setTimeout(r, ms));
|
2021-06-22 21:35:33 +02:00
|
|
|
}
|
|
|
|
|