- 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>
91 lines
2.6 KiB
JavaScript
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);
|