2026-04-14 21:07:54 +02:00
|
|
|
/**
|
|
|
|
|
* This file is part of the SplendidBear Websites' projects.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2026 @ www.splendidbear.org
|
|
|
|
|
*
|
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
|
*/
|
2026-04-19 21:31:08 +02:00
|
|
|
|
|
|
|
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
2026-04-14 21:07:54 +02:00
|
|
|
|
|
|
|
|
const CAPTCHA_STORAGE_KEY = 'mineseeker_captcha_verified';
|
|
|
|
|
const CAPTCHA_TOKEN_KEY = 'mineseeker_captcha_token';
|
|
|
|
|
const RECAPTCHA_ACTION = 'mineseeker_play';
|
|
|
|
|
|
|
|
|
|
const CaptchaOverlay = ({ siteKey, onVerified, children }) => {
|
|
|
|
|
const [verified, setVerified] = useState(false);
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [error, setError] = useState(false);
|
|
|
|
|
|
2026-04-19 21:31:08 +02:00
|
|
|
const handleToken = useCallback(token => {
|
|
|
|
|
const wrapper = document.getElementById('mine-wrapper');
|
|
|
|
|
if (wrapper) {
|
|
|
|
|
wrapper.dataset.captchaToken = token;
|
|
|
|
|
}
|
|
|
|
|
sessionStorage.setItem(CAPTCHA_TOKEN_KEY, token);
|
|
|
|
|
sessionStorage.setItem(CAPTCHA_STORAGE_KEY, Date.now().toString());
|
|
|
|
|
setVerified(true);
|
|
|
|
|
onVerified?.();
|
|
|
|
|
}, [onVerified]);
|
|
|
|
|
|
|
|
|
|
const buttonClasses = useMemo(() => [
|
|
|
|
|
'captcha-button',
|
|
|
|
|
error && 'captcha-button--error',
|
|
|
|
|
loading && 'captcha-button--loading',
|
|
|
|
|
].filter(Boolean).join(' '), [error, loading]);
|
|
|
|
|
|
2026-04-14 21:07:54 +02:00
|
|
|
useEffect(() => {
|
|
|
|
|
const storedToken = sessionStorage.getItem(CAPTCHA_TOKEN_KEY);
|
|
|
|
|
const storedTime = sessionStorage.getItem(CAPTCHA_STORAGE_KEY);
|
|
|
|
|
|
|
|
|
|
if (storedToken && storedTime) {
|
|
|
|
|
const elapsed = (Date.now() - parseInt(storedTime)) / 1000;
|
|
|
|
|
if (110 > elapsed) {
|
|
|
|
|
const wrapper = document.getElementById('mine-wrapper');
|
|
|
|
|
if (wrapper) {
|
|
|
|
|
wrapper.dataset.captchaToken = storedToken;
|
|
|
|
|
}
|
|
|
|
|
setVerified(true);
|
|
|
|
|
onVerified?.();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (window.grecaptcha) {
|
|
|
|
|
window.grecaptcha.ready(() => {
|
|
|
|
|
window.grecaptcha
|
|
|
|
|
.execute(siteKey, { action: RECAPTCHA_ACTION })
|
|
|
|
|
.then(token => {
|
|
|
|
|
handleToken(token);
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
setError(true);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-04-19 21:04:15 +02:00
|
|
|
}, [siteKey, onVerified, handleToken]);
|
2026-04-14 21:07:54 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
const handleClick = () => {
|
|
|
|
|
setLoading(true);
|
|
|
|
|
setError(false);
|
|
|
|
|
|
|
|
|
|
window.grecaptcha.ready(() => {
|
|
|
|
|
window.grecaptcha
|
|
|
|
|
.execute(siteKey, { action: RECAPTCHA_ACTION })
|
|
|
|
|
.then(token => {
|
|
|
|
|
handleToken(token);
|
|
|
|
|
setLoading(false);
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
setError(true);
|
|
|
|
|
setTimeout(() => setError(false), 2000);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (verified) {
|
|
|
|
|
return <>{children}</>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2026-04-19 21:31:08 +02:00
|
|
|
<div className="captcha-overlay">
|
|
|
|
|
<div className="captcha-content">
|
|
|
|
|
<div className="captcha-icon">
|
2026-04-14 21:07:54 +02:00
|
|
|
<i className="fa fa-shield-halved" />
|
|
|
|
|
</div>
|
2026-04-19 21:31:08 +02:00
|
|
|
<h1 className="captcha-title">Ready to Play?</h1>
|
|
|
|
|
<p className="captcha-description">
|
2026-04-14 21:07:54 +02:00
|
|
|
Click below to verify you're human and start playing.
|
|
|
|
|
</p>
|
|
|
|
|
<button
|
2026-04-19 21:31:08 +02:00
|
|
|
className={buttonClasses}
|
2026-04-14 21:07:54 +02:00
|
|
|
onClick={handleClick}
|
|
|
|
|
disabled={loading}
|
|
|
|
|
>
|
|
|
|
|
<i className={`fa ${loading ? 'fa-spinner fa-spin' : error ? 'fa-exclamation-circle' : 'fa-play'}`} />
|
|
|
|
|
{loading ? 'Verifying...' : error ? 'Try Again' : 'Start Playing'}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default CaptchaOverlay;
|