this is a big slop that might backfire lol... new config system and UI!

This commit is contained in:
legop3
2026-09-14 02:31:12 -04:00
parent 17b1404157
commit bfdb6555d8
108 changed files with 3212 additions and 701 deletions
@@ -0,0 +1,36 @@
// Discord Bot Configuration
// Purpose: Defines the optional bot connection and its guild channel and role mappings.
// Scope: Contains configuration metadata only and never logs in to Discord.
const { strictObject, string, boolean } = require('../../configuration/schemaHelpers');
module.exports = {
key: 'discord',
feature: true,
defaultValue: {
enabled: false,
token: '',
guildId: '',
siteUrl: '',
channels: { general: '', announcements: '', adminAlerts: '', replay: '', humanAlerts: '' },
roles: { stalkerPing: '', announcementPing: '', adminPing: '', humanAlertPing: '' },
},
schema: strictObject({
enabled: boolean(),
token: string({ title: 'Bot token', writeOnly: true, maxLength: 10000 }),
guildId: string({ title: 'Guild id', maxLength: 100 }),
siteUrl: string({ title: 'Public site URL', maxLength: 2048 }),
channels: strictObject({
general: string({ maxLength: 100 }),
announcements: string({ maxLength: 100 }),
adminAlerts: string({ maxLength: 100 }),
replay: string({ maxLength: 100 }),
humanAlerts: string({ maxLength: 100 }),
}, { required: ['general', 'announcements', 'adminAlerts', 'replay', 'humanAlerts'] }),
roles: strictObject({
stalkerPing: string({ maxLength: 100 }),
announcementPing: string({ maxLength: 100 }),
adminPing: string({ maxLength: 100 }),
humanAlertPing: string({ maxLength: 100 }),
}, { required: ['stalkerPing', 'announcementPing', 'adminPing', 'humanAlertPing'] }),
}, { title: 'Discord', required: ['enabled', 'token', 'guildId', 'siteUrl', 'channels', 'roles'] }),
};
@@ -27,7 +27,14 @@ function formatNumber(value, digits = 1) {
function createFleetDailyReports({ logger, discordConfig, fleetConfig, fleetReportService, roverManager, sendToChannel }) {
let timer = null;
const reportConfig = fleetConfig?.discord || {};
const enabled = fleetReportService?.enabled && reportConfig.enabled !== false;
const enabled = Boolean(reportConfig.enabled);
/*
Keep the configured choice separate from runtime availability. An operator
can enable Discord delivery while the parent fleet collector is unhealthy
or disabled; that dependency prevents work but does not rewrite the meaning
of this switch.
*/
const fleetReportsAvailable = Boolean(fleetReportService?.enabled);
const channelId = discordConfig?.channels?.adminAlerts;
const zone = String(reportConfig.timezone || 'America/New_York');
const { hour, minute } = parseSendTime(reportConfig.sendAt);
@@ -85,7 +92,7 @@ function createFleetDailyReports({ logger, discordConfig, fleetConfig, fleetRepo
}
async function deliverPreviousDay() {
if (!enabled || !channelId) return;
if (!enabled || !fleetReportsAvailable || !channelId) return;
const range = completedDayRange();
const existing = fleetReportService.storage.getDailyReport(range.reportDate);
if (existing?.discordDeliveredAt) return;
@@ -116,7 +123,7 @@ function createFleetDailyReports({ logger, discordConfig, fleetConfig, fleetRepo
}
function scheduleNext() {
if (!enabled || !channelId) return;
if (!enabled || !fleetReportsAvailable || !channelId) return;
const next = nextRunAt({ zone, hour, minute });
const delay = Math.max(1000, next.toMillis() - Date.now());
timer = setTimeout(async () => {
@@ -9,8 +9,7 @@ const {
} = require('discord.js');
const logger = require('../../globals/logger').child('discordBot');
const io = require('../../globals/io');
const { loadConfig } = require('../../helpers/configLoader');
const { isFeatureEnabled } = require('../../helpers/features');
const { loadConfig, getConfigurationDatabase, isFeatureEnabled } = require('../../configuration');
const { parseCommandText } = require('../operatorCommandService/config');
const roverManager = require('../roverManager');
const { getRoster, lockRover, rovers } = roverManager;
@@ -82,15 +81,16 @@ const {
const config = loadConfig();
const discordConfig = config.discord || {};
const enabled = isFeatureEnabled('discord');
const enabled = Boolean(discordConfig.enabled);
// These normalized command names mirror the command router. Bridge-channel
// command replies are mirrored into web chat, so this entrypoint needs to know
// the configured command names before it wraps message.reply.
const adminIds = new Set((config.admins || []).map((a) => String(a.discord_id || '').trim()).filter(Boolean));
const lockdownAdminIds = new Set((config.admins || []).filter((admin) => admin.lockdown).map((admin) => String(admin.discord_id || '').trim()).filter(Boolean));
const configuredAdministrators = getConfigurationDatabase().listAdministrators();
const adminIds = new Set(configuredAdministrators.map((admin) => String(admin.discordId || '').trim()).filter(Boolean));
const lockdownAdminIds = new Set(configuredAdministrators.filter((admin) => admin.role === 'lockdown').map((admin) => String(admin.discordId || '').trim()).filter(Boolean));
if (!enabled) {
logger.info('Discord feature disabled or missing required token');
logger.info('Discord disabled by config');
return;
}