Add script for importing match schedule and logging
Some checks failed
Code Analysis and Production Deploy / analyze (push) Has been skipped
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Successful in 2m2s
Code Analysis and Production Deploy / analyze (pull_request) Failing after 33s
Code Analysis and Production Deploy / deploy-production (pull_request) Has been skipped
Code Analysis and Production Deploy / deploy-test (pull_request) Has been skipped
Require Package Version Change / check (pull_request) Failing after 10s
Some checks failed
Code Analysis and Production Deploy / analyze (push) Has been skipped
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Successful in 2m2s
Code Analysis and Production Deploy / analyze (pull_request) Failing after 33s
Code Analysis and Production Deploy / deploy-production (pull_request) Has been skipped
Code Analysis and Production Deploy / deploy-test (pull_request) Has been skipped
Require Package Version Change / check (pull_request) Failing after 10s
- Created `import-spielplan.js` to fetch and parse the match schedule from the specified URL, saving the output as JSON. - Added `run-spielplan-import.sh` to automate the execution of the import script and log output. - Introduced `spielplan.html` file to store the downloaded HTML content for further processing.
This commit is contained in:
107
server/plugins/spielplan-import-scheduler.js
Normal file
107
server/plugins/spielplan-import-scheduler.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import { importSpielplan } from '../utils/spielplan-import.js'
|
||||
|
||||
const TIME_ZONE = 'Europe/Berlin'
|
||||
const RUN_HOUR = 7
|
||||
const RUN_MINUTE = 0
|
||||
const MAX_TIMEOUT = 2_147_483_647
|
||||
|
||||
let timer = null
|
||||
let running = false
|
||||
|
||||
function getTimeParts(date) {
|
||||
const parts = new Intl.DateTimeFormat('en-CA', {
|
||||
timeZone: TIME_ZONE,
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
hour12: false
|
||||
}).formatToParts(date)
|
||||
|
||||
return Object.fromEntries(parts.map((part) => [part.type, part.value]))
|
||||
}
|
||||
|
||||
function getTimeZoneOffset(date) {
|
||||
const parts = getTimeParts(date)
|
||||
const zonedAsUtc = Date.UTC(
|
||||
Number(parts.year),
|
||||
Number(parts.month) - 1,
|
||||
Number(parts.day),
|
||||
Number(parts.hour),
|
||||
Number(parts.minute),
|
||||
Number(parts.second)
|
||||
)
|
||||
|
||||
return zonedAsUtc - date.getTime()
|
||||
}
|
||||
|
||||
function zonedDateToUtc(year, month, day, hour, minute) {
|
||||
const utcGuess = new Date(Date.UTC(year, month - 1, day, hour, minute, 0))
|
||||
const offset = getTimeZoneOffset(utcGuess)
|
||||
return new Date(utcGuess.getTime() - offset)
|
||||
}
|
||||
|
||||
function nextRunAt(now = new Date()) {
|
||||
const parts = getTimeParts(now)
|
||||
let year = Number(parts.year)
|
||||
let month = Number(parts.month)
|
||||
let day = Number(parts.day)
|
||||
let candidate = zonedDateToUtc(year, month, day, RUN_HOUR, RUN_MINUTE)
|
||||
|
||||
if (candidate <= now) {
|
||||
const nextDay = zonedDateToUtc(year, month, day + 1, 12, 0)
|
||||
const nextParts = getTimeParts(nextDay)
|
||||
year = Number(nextParts.year)
|
||||
month = Number(nextParts.month)
|
||||
day = Number(nextParts.day)
|
||||
candidate = zonedDateToUtc(year, month, day, RUN_HOUR, RUN_MINUTE)
|
||||
}
|
||||
|
||||
return candidate
|
||||
}
|
||||
|
||||
async function runImport(reason) {
|
||||
if (running) return
|
||||
|
||||
running = true
|
||||
try {
|
||||
const result = await importSpielplan()
|
||||
console.log(`[spielplan-import] ${reason}: ${result.matchCount} Spiele importiert (${result.source.season.dateStart} bis ${result.source.season.dateEnd})`)
|
||||
} catch (error) {
|
||||
console.error('[spielplan-import] Import fehlgeschlagen:', error)
|
||||
} finally {
|
||||
running = false
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleNext() {
|
||||
const runAt = nextRunAt()
|
||||
const delay = Math.min(Math.max(runAt.getTime() - Date.now(), 1_000), MAX_TIMEOUT)
|
||||
|
||||
timer = setTimeout(async () => {
|
||||
await runImport('taeglicher Lauf')
|
||||
scheduleNext()
|
||||
}, delay)
|
||||
|
||||
timer.unref?.()
|
||||
console.log(`[spielplan-import] Naechster Lauf: ${runAt.toISOString()} (${TIME_ZONE} ${String(RUN_HOUR).padStart(2, '0')}:${String(RUN_MINUTE).padStart(2, '0')})`)
|
||||
}
|
||||
|
||||
export default defineNitroPlugin((nitroApp) => {
|
||||
if (process.env.SPIELPLAN_IMPORT_DISABLED === 'true') {
|
||||
console.log('[spielplan-import] Scheduler deaktiviert')
|
||||
return
|
||||
}
|
||||
|
||||
scheduleNext()
|
||||
|
||||
if (process.env.SPIELPLAN_IMPORT_RUN_ON_START === 'true') {
|
||||
runImport('Startlauf')
|
||||
}
|
||||
|
||||
nitroApp.hooks.hookOnce('close', () => {
|
||||
if (timer) clearTimeout(timer)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user