1
0
Fork 0
polaris-task-force/src/bot/config.ts
Z8MB1E d757c58c5d feat(missions): daily ready-check reminders for unfinished side ops
Five days before a player-created side op starts, if it is not yet Ready, the creator gets one in-app notification per day (via mission-tick) plus one Discord DM per day (new bot service). Per-server-local-day dedupe via hidden readyReminderWebSentAt/readyReminderDmSentAt markers. The ready-reminder type is excluded from the notification bridge to avoid double-DMing. Markers are nulled on clone.
2026-09-07 05:07:46 -04:00

53 lines
1.6 KiB
TypeScript

export interface BotConfig {
token: string;
guildId: string;
appUrl: string;
opsChannelId: string | null;
announceChannelId: string | null;
staffRoleIds: string[];
attendancePollMs: number;
notificationPollMs: number;
evaluationPollMs: number;
readyReminderPollMs: number;
}
const required = (name: string): string => {
const value = process.env[name]?.trim();
if (!value) {
throw new Error(`[Bot] Missing required environment variable: ${name}`);
}
return value;
};
const optional = (name: string): string | null => {
const value = process.env[name]?.trim();
return value ? value : null;
};
const pollMs = (name: string, fallback: number): number => {
const raw = process.env[name]?.trim();
if (!raw) {
return fallback;
}
const value = Number.parseInt(raw, 10);
if (!Number.isInteger(value) || value <= 0) {
throw new Error(`[Bot] Invalid ${name}: expected a positive integer, got "${raw}"`);
}
return value;
};
export const botConfig: BotConfig = {
token: required("DISCORD_TOKEN"),
guildId: required("DISCORD_GUILD_ID"),
appUrl: required("APP_URL"),
opsChannelId: optional("DISCORD_OPS_CHANNEL_ID"),
announceChannelId: optional("DISCORD_ANNOUNCE_CHANNEL_ID"),
staffRoleIds: (optional("DISCORD_STAFF_ROLE_IDS") ?? "")
.split(",")
.map((id) => id.trim())
.filter((id) => id.length > 0),
attendancePollMs: pollMs("DISCORD_ATTENDANCE_POLL_MS", 60_000),
notificationPollMs: pollMs("DISCORD_NOTIFICATION_POLL_MS", 20_000),
evaluationPollMs: pollMs("DISCORD_EVALUATION_POLL_MS", 60_000),
readyReminderPollMs: pollMs("DISCORD_READY_REMINDER_POLL_MS", 60_000),
};