moon cricket
This commit is contained in:
+31
-8
@@ -66,6 +66,7 @@ const siteGateEnabled = siteGateSetting == null
|
|||||||
const staticDataBase = (import.meta.env.VITE_STATIC_DATA_BASE || '/data').replace(/\/+$/, '')
|
const staticDataBase = (import.meta.env.VITE_STATIC_DATA_BASE || '/data').replace(/\/+$/, '')
|
||||||
const staticDataEnabled = String(import.meta.env.VITE_STATIC_DATA || 'false').toLowerCase() === 'true'
|
const staticDataEnabled = String(import.meta.env.VITE_STATIC_DATA || 'false').toLowerCase() === 'true'
|
||||||
const missingStaticDataPaths = new Set()
|
const missingStaticDataPaths = new Set()
|
||||||
|
const turnstileRequiredEvent = 'tssbot:turnstile-required'
|
||||||
|
|
||||||
const BLOCKED_PLAYER_UIDS = new Set(['165569402', '86157459', '33536334', '41808996', '3651161'])
|
const BLOCKED_PLAYER_UIDS = new Set(['165569402', '86157459', '33536334', '41808996', '3651161'])
|
||||||
const BLOCKED_TEAM_NAMES = new Set(['TPC'])
|
const BLOCKED_TEAM_NAMES = new Set(['TPC'])
|
||||||
@@ -135,6 +136,15 @@ function dataSource(apiPath, staticPath = null) {
|
|||||||
return { apiPath, staticPath }
|
return { apiPath, staticPath }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function turnstileSessionRequiredMessage(error) {
|
||||||
|
return error === 'Turnstile session required' || error === 'Site session required'
|
||||||
|
}
|
||||||
|
|
||||||
|
function promptTurnstileSession(detail) {
|
||||||
|
if (typeof window === 'undefined' || !turnstileSiteKey) return
|
||||||
|
window.dispatchEvent(new CustomEvent(turnstileRequiredEvent, { detail }))
|
||||||
|
}
|
||||||
|
|
||||||
const publicDataSources = {
|
const publicDataSources = {
|
||||||
teams: dataSource(apiEndpoints.teams, staticDataPath('leaderboard-teams.json')),
|
teams: dataSource(apiEndpoints.teams, staticDataPath('leaderboard-teams.json')),
|
||||||
players: dataSource(apiEndpoints.players, staticDataPath('leaderboard-players.json')),
|
players: dataSource(apiEndpoints.players, staticDataPath('leaderboard-players.json')),
|
||||||
@@ -161,6 +171,10 @@ async function fetchJson(path, signal) {
|
|||||||
const error = new Error(body?.error || `Request failed with ${response.status}`)
|
const error = new Error(body?.error || `Request failed with ${response.status}`)
|
||||||
error.status = response.status
|
error.status = response.status
|
||||||
error.path = path
|
error.path = path
|
||||||
|
error.detail = body?.detail
|
||||||
|
if (response.status === 403 && turnstileSessionRequiredMessage(body?.error)) {
|
||||||
|
promptTurnstileSession({ path, error: body?.error, detail: body?.detail })
|
||||||
|
}
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1307,10 +1321,10 @@ function SiteGate({ onVerified }) {
|
|||||||
>
|
>
|
||||||
<div className="flex w-full max-w-sm flex-col items-center gap-4 rounded-md border border-border bg-fury-white p-6 text-center text-text shadow-[0_24px_70px_rgba(0,0,0,0.24)]">
|
<div className="flex w-full max-w-sm flex-col items-center gap-4 rounded-md border border-border bg-fury-white p-6 text-center text-text shadow-[0_24px_70px_rgba(0,0,0,0.24)]">
|
||||||
<h1 id="site-gate-title" className="text-lg font-semibold">
|
<h1 id="site-gate-title" className="text-lg font-semibold">
|
||||||
Verifying you are human
|
Start a protected session
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm text-text-soft">
|
<p className="text-sm text-text-soft">
|
||||||
This quick check protects the site from automated abuse. It usually clears itself.
|
Complete this Turnstile check to continue using protected site data.
|
||||||
</p>
|
</p>
|
||||||
<TurnstileWidget
|
<TurnstileWidget
|
||||||
siteKey={turnstileSiteKey}
|
siteKey={turnstileSiteKey}
|
||||||
@@ -1330,15 +1344,15 @@ function SiteGate({ onVerified }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
if (!siteGateEnabled) return <AppContent />
|
if (!turnstileSiteKey) return <AppContent />
|
||||||
return <GatedAppContent />
|
return <GatedAppContent enforceInitialGate={siteGateEnabled} />
|
||||||
}
|
}
|
||||||
|
|
||||||
function GatedAppContent() {
|
function GatedAppContent({ enforceInitialGate }) {
|
||||||
const embeddedGateState = document
|
const embeddedGateState = document
|
||||||
.querySelector('meta[name="tss-turnstile-session"]')
|
.querySelector('meta[name="tss-turnstile-session"]')
|
||||||
?.getAttribute('content')
|
?.getAttribute('content')
|
||||||
const initialGateState = turnstileSiteKey
|
const initialGateState = enforceInitialGate
|
||||||
? ['verified', 'required'].includes(embeddedGateState)
|
? ['verified', 'required'].includes(embeddedGateState)
|
||||||
? embeddedGateState
|
? embeddedGateState
|
||||||
: 'checking'
|
: 'checking'
|
||||||
@@ -1346,7 +1360,7 @@ function GatedAppContent() {
|
|||||||
const [gateState, setGateState] = useState(initialGateState)
|
const [gateState, setGateState] = useState(initialGateState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!turnstileSiteKey || gateState !== 'checking') return undefined
|
if (!enforceInitialGate || gateState !== 'checking') return undefined
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
fetch('/api/turnstile/session', { headers: { Accept: 'application/json' } })
|
fetch('/api/turnstile/session', { headers: { Accept: 'application/json' } })
|
||||||
.then((response) => (response.ok ? response.json() : { verified: false }))
|
.then((response) => (response.ok ? response.json() : { verified: false }))
|
||||||
@@ -1360,7 +1374,16 @@ function GatedAppContent() {
|
|||||||
return () => {
|
return () => {
|
||||||
cancelled = true
|
cancelled = true
|
||||||
}
|
}
|
||||||
}, [gateState])
|
}, [enforceInitialGate, gateState])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleTurnstileRequired() {
|
||||||
|
setGateState('required')
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener(turnstileRequiredEvent, handleTurnstileRequired)
|
||||||
|
return () => window.removeEventListener(turnstileRequiredEvent, handleTurnstileRequired)
|
||||||
|
}, [])
|
||||||
|
|
||||||
if (gateState === 'checking') {
|
if (gateState === 'checking') {
|
||||||
return <div className="fixed inset-0 bg-bg" aria-hidden="true" />
|
return <div className="fixed inset-0 bg-bg" aria-hidden="true" />
|
||||||
|
|||||||
Reference in New Issue
Block a user