82 lines
2.7 KiB
TypeScript
82 lines
2.7 KiB
TypeScript
import { getConfig, setConfig } from '../db';
|
|
|
|
export interface SchedulerState {
|
|
job_sleep_seconds: number;
|
|
schedule_enabled: boolean;
|
|
schedule_start: string; // "HH:MM"
|
|
schedule_end: string; // "HH:MM"
|
|
}
|
|
|
|
export function getSchedulerState(): SchedulerState {
|
|
return {
|
|
job_sleep_seconds: parseInt(getConfig('job_sleep_seconds') ?? '0', 10),
|
|
schedule_enabled: getConfig('schedule_enabled') === '1',
|
|
schedule_start: getConfig('schedule_start') ?? '01:00',
|
|
schedule_end: getConfig('schedule_end') ?? '07:00',
|
|
};
|
|
}
|
|
|
|
export function updateSchedulerState(updates: Partial<SchedulerState>): void {
|
|
if (updates.job_sleep_seconds != null) setConfig('job_sleep_seconds', String(updates.job_sleep_seconds));
|
|
if (updates.schedule_enabled != null) setConfig('schedule_enabled', updates.schedule_enabled ? '1' : '0');
|
|
if (updates.schedule_start != null) setConfig('schedule_start', updates.schedule_start);
|
|
if (updates.schedule_end != null) setConfig('schedule_end', updates.schedule_end);
|
|
}
|
|
|
|
/** Check if current time is within the schedule window. */
|
|
export function isInScheduleWindow(): boolean {
|
|
const state = getSchedulerState();
|
|
if (!state.schedule_enabled) return true; // no schedule = always allowed
|
|
|
|
const now = new Date();
|
|
const minutes = now.getHours() * 60 + now.getMinutes();
|
|
const start = parseTime(state.schedule_start);
|
|
const end = parseTime(state.schedule_end);
|
|
|
|
// Handle overnight windows (e.g., 23:00 → 07:00)
|
|
if (start <= end) {
|
|
return minutes >= start && minutes < end;
|
|
} else {
|
|
return minutes >= start || minutes < end;
|
|
}
|
|
}
|
|
|
|
/** Returns milliseconds until the next schedule window opens. */
|
|
export function msUntilWindow(): number {
|
|
const state = getSchedulerState();
|
|
const now = new Date();
|
|
const minutes = now.getHours() * 60 + now.getMinutes();
|
|
const start = parseTime(state.schedule_start);
|
|
|
|
if (minutes < start) {
|
|
return (start - minutes) * 60_000;
|
|
} else {
|
|
// Next day
|
|
return (24 * 60 - minutes + start) * 60_000;
|
|
}
|
|
}
|
|
|
|
/** Returns the schedule_start time as "HH:MM" for display. */
|
|
export function nextWindowTime(): string {
|
|
return getSchedulerState().schedule_start;
|
|
}
|
|
|
|
function parseTime(hhmm: string): number {
|
|
const [h, m] = hhmm.split(':').map(Number);
|
|
return h * 60 + m;
|
|
}
|
|
|
|
/** Sleep for the configured duration between jobs. */
|
|
export function sleepBetweenJobs(): Promise<void> {
|
|
const seconds = getSchedulerState().job_sleep_seconds;
|
|
if (seconds <= 0) return Promise.resolve();
|
|
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
|
|
}
|
|
|
|
/** Wait until the schedule window opens. Resolves immediately if already in window. */
|
|
export function waitForWindow(): Promise<void> {
|
|
if (isInScheduleWindow()) return Promise.resolve();
|
|
const ms = msUntilWindow();
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|