Files
xBot/scheduler.js
Matt Jackson d2ca2d23ba Consolidate schedule config, support multi-post per day
- Schedule config moved to nested schedule object in prompts.json
- Scheduler picks 1-3 random times for personality with 4hr min gap
- shouldRun reads from schedule object

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 23:12:29 +00:00

91 lines
2.6 KiB
JavaScript

import { execFileSync } from "child_process";
import { readFileSync } from "fs";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
const __dirname = dirname(fileURLToPath(import.meta.url));
const promptName = process.argv[2];
if (!promptName) {
console.error("Usage: node scheduler.js <prompt-name>");
process.exit(1);
}
const prompts = JSON.parse(readFileSync(join(__dirname, "prompts.json"), "utf-8"));
const config = prompts.find((p) => p.name === promptName);
if (!config) {
console.error(`Prompt "${promptName}" not found.`);
process.exit(1);
}
const schedule = config.schedule;
const [startHour, endHour] = schedule.window;
const minGap = (schedule.minGapHours || 4) * 60;
function randomMinuteInWindow() {
const windowMinutes = (endHour - startHour) * 60;
return Math.floor(Math.random() * windowMinutes);
}
function pickSpacedTimes(count) {
for (let attempt = 0; attempt < 100; attempt++) {
const times = Array.from({ length: count }, () => randomMinuteInWindow()).sort((a, b) => a - b);
let valid = true;
for (let i = 1; i < times.length; i++) {
if (times[i] - times[i - 1] < minGap) {
valid = false;
break;
}
}
if (valid) return times;
}
const window = (endHour - startHour) * 60;
const gap = Math.floor(window / (count + 1));
return Array.from({ length: count }, (_, i) => gap * (i + 1));
}
function nowPST() {
return new Date(new Date().toLocaleString("en-US", { timeZone: "America/Los_Angeles" }));
}
function runBot() {
try {
execFileSync("node", [join(__dirname, "bot.js"), promptName], { stdio: "inherit" });
} catch {
console.error(`[${promptName}] bot.js failed`);
}
}
const [minPerDay, maxPerDay] = schedule.postsPerDay || [1, 1];
const count = Math.floor(Math.random() * (maxPerDay - minPerDay + 1)) + minPerDay;
const times = pickSpacedTimes(count);
const pad = (n) => String(n).padStart(2, "0");
const scheduled = times.map((m) => `${pad(Math.floor(m / 60) + startHour)}:${pad(m % 60)}`);
console.log(`[${promptName}] ${count} post(s) scheduled at: ${scheduled.join(", ")} PST`);
function scheduleNext(index) {
if (index >= times.length) return;
const minutes = times[index];
const hours = Math.floor(minutes / 60) + startHour;
const mins = minutes % 60;
const now = nowPST();
const target = new Date(now);
target.setHours(hours, mins, 0, 0);
let delayMs = target.getTime() - now.getTime();
if (delayMs < 0) delayMs = 0;
console.log(`[${promptName}] #${index + 1} in ${Math.round(delayMs / 60000)} minutes`);
setTimeout(() => {
runBot();
scheduleNext(index + 1);
}, delayMs);
}
scheduleNext(0);