remove embed stuff

This commit is contained in:
legop3
2026-09-18 16:36:19 -04:00
parent b712fb89c6
commit 8e301e7db7
3 changed files with 15 additions and 53 deletions
@@ -32,7 +32,7 @@ module.exports = {
token: string({ title: 'Bot token', description: 'Discord bot token used to log in. The saved value is never returned to the browser.', examples: ['DISCORD_BOT_TOKEN'], writeOnly: true, maxLength: 10000 }),
guildId: string({ title: 'Guild id', description: 'Reserved Discord server identifier. The current bot runtime does not restrict commands or events using this value.', examples: ['123456789012345678'], maxLength: 100 }),
channels: strictObject({
liveStatus: string({ title: 'Live status', description: 'Dedicated live fleet report channel ID. The bot deletes ALL other messages here. Requires View Channel, Read Message History, Send Messages, Embed Links, and Manage Messages. Leave empty to disable.', examples: ['123456789012345678'], maxLength: 100 }),
liveStatus: string({ title: 'Live status', description: 'Dedicated live fleet report channel ID. The bot deletes ALL other messages here. Requires View Channel, Read Message History, Send Messages, and Manage Messages. Leave empty to disable.', examples: ['123456789012345678'], maxLength: 100 }),
general: string({ description: 'Channel ID used by the button-box stalker-role and everyone-ping rewards.', examples: ['123456789012345678'], maxLength: 100 }),
announcements: string({ description: 'Channel ID used for public-mode openings, objective changes, and all-rovers-unlocked announcements.', examples: ['123456789012345678'], maxLength: 100 }),
adminAlerts: string({ description: 'Channel ID used for rover health, battery, dock, help, and daily fleet-report notifications.', examples: ['123456789012345678'], maxLength: 100 }),
@@ -338,8 +338,8 @@ function createDiscordRuntime() {
const integrationHandlers = integrations.register();
const liveStatus = createLiveStatus({
client, logger, discordConfig, roverManager, getActiveDrivers, getNickname,
io, getMode, getGlobalObjective, fetchChannel: channelIO.fetchChannel, sanitizeMentions,
turnEvents, nicknameEvents, subscribe,
io, fetchChannel: channelIO.fetchChannel, sanitizeMentions,
turnEvents, nicknameEvents,
});
function isTextCommand(content) {
@@ -1,10 +1,10 @@
// Owns the single-message live report and the dedicated channel's cleanup.
const { escapeMarkdown, PermissionFlagsBits } = require('discord.js');
const { PermissionFlagsBits } = require('discord.js');
const { buildRoverStatusSnapshot } = require('./batteryEmbeds');
function createLiveStatus({ client, logger, discordConfig, roverManager, getActiveDrivers,
getNickname, io, getMode, getGlobalObjective, fetchChannel, sanitizeMentions,
turnEvents, nicknameEvents, subscribe }) {
getNickname, io, fetchChannel, sanitizeMentions,
turnEvents, nicknameEvents }) {
const COOLDOWN_MS = 3000;
let timer = null;
let sweepTimer = null;
@@ -17,60 +17,26 @@ function createLiveStatus({ client, logger, discordConfig, roverManager, getActi
let running = false;
let channelId = null;
let messageId = null;
let lastSignature = null;
let lastContent = null;
const clean = (value, limit = 120) => sanitizeMentions(String(value ?? ''))
.replace(/[\r\n]+/g, ' ').slice(0, limit);
const rich = (value, limit) => escapeMarkdown(clean(value, limit));
function buildReport() {
const drivers = getActiveDrivers();
const roster = roverManager.getRoster();
const lines = [];
const fields = [];
let budget = 4800;
for (const rover of roster) {
const snapshot = buildRoverStatusSnapshot(roverManager.rovers.get(rover.id));
const driverId = drivers[rover.id];
const driver = driverId ? clean(getNickname(io.sockets.sockets.get(driverId)) || 'Someone', 32) : null;
const status = rover.needsHelp ? 'needs help' : driver ? `${driver} driving`
: snapshot?.docked ? 'docked' : rover.locked ? 'locked' : 'available';
const status = snapshot?.docked ? 'docked' : rover.needsHelp ? 'needs help'
: driver ? `${driver} driving` : rover.locked ? 'locked' : 'available';
lines.push(`${clean(rover.name, 60)}: ${status}`);
const battery = snapshot?.batteryState;
const value = [
`**${rich(status)}**`,
`Driver: ${rich(driver || 'none')}`,
`Battery: ${battery?.percentDisplay == null ? 'unknown' : `${battery.percentDisplay}%`}`,
`Charge: ${battery?.charge ?? '?'} / ${battery?.capacity ?? '?'} mAh`,
`Dock: ${snapshot?.docked ? 'docked' : 'undocked'}`,
`Charging: ${rich(snapshot?.chargingLabel || 'unknown')}`,
`Lock: ${rover.locked ? rich(rover.lockReason || 'locked') : 'unlocked'}`,
`Operating mode: ${rich(snapshot?.oiMode || 'unknown')}`,
].join('\n').slice(0, 1024);
const name = `${rover.needsHelp ? '🆘' : snapshot?.docked ? '🏠' : '🤖'} ${rich(rover.name, 60)}`;
// Leave room for the header/footer and stay within Discord's single-message limits.
if (fields.length < 25 && name.length + value.length <= budget) {
fields.push({ name, value, inline: true });
budget -= name.length + value.length;
}
}
let content = lines.join('\n') || 'No rovers online.';
if (content.length > 2000) content = `${content.slice(0, 1950)}\n… More rovers online.`;
const objective = getGlobalObjective()?.text;
return {
content,
allowedMentions: { parse: [] },
embeds: [{
title: 'Live rover status',
color: roster.some((rover) => rover.needsHelp) ? 0xe74c3c : 0x2ecc71,
description: [`**${rich(getMode(), 60)}** · ${roster.length} online`,
objective ? `Objective: ${rich(objective, 300)}` : null].filter(Boolean).join('\n'),
fields,
footer: { text: fields.length < roster.length
? `${roster.length - fields.length} rover details omitted due to Discord limits · Live updates`
: 'Live updates' },
}],
};
return { content, allowedMentions: { parse: [] } };
}
function schedule() {
@@ -99,7 +65,7 @@ function createLiveStatus({ client, logger, discordConfig, roverManager, getActi
if (target !== channelId) {
channelId = target;
messageId = null;
lastSignature = null;
lastContent = null;
}
if (!target) return;
running = true;
@@ -110,8 +76,7 @@ function createLiveStatus({ client, logger, discordConfig, roverManager, getActi
&& discordConfig.channels?.liveStatus?.trim() === target;
try {
const report = buildReport();
const signature = JSON.stringify(report);
const replace = signature !== lastSignature;
const replace = report.content !== lastContent;
// Sensor events can arrive many times per second. Compare the rendered
// report locally before consuming any Discord API capacity.
if (!replace && !cleanup) return;
@@ -123,8 +88,8 @@ function createLiveStatus({ client, logger, discordConfig, roverManager, getActi
}
const permissions = channel.permissionsFor(client.user);
if (!permissions?.has([PermissionFlagsBits.ViewChannel, PermissionFlagsBits.ReadMessageHistory,
PermissionFlagsBits.SendMessages, PermissionFlagsBits.EmbedLinks, PermissionFlagsBits.ManageMessages])) {
throw new Error('Live status requires View Channel, Read Message History, Send Messages, Embed Links, and Manage Messages');
PermissionFlagsBits.SendMessages, PermissionFlagsBits.ManageMessages])) {
throw new Error('Live status requires View Channel, Read Message History, Send Messages, and Manage Messages');
}
let found = false;
let before;
@@ -150,11 +115,10 @@ function createLiveStatus({ client, logger, discordConfig, roverManager, getActi
}
if (!active()) return;
if (replace || !found) {
report.embeds[0].timestamp = new Date().toISOString();
const message = await channel.send(report);
if (!active()) return;
messageId = message.id;
lastSignature = signature;
lastContent = report.content;
}
} catch (err) {
cleanupNeeded = true;
@@ -196,8 +160,6 @@ function createLiveStatus({ client, logger, discordConfig, roverManager, getActi
() => nicknameEvents.off('change', onChange),
() => client.off('messageDelete', onDelete),
() => client.off('messageDeleteBulk', onBulkDelete),
subscribe('mode.changed', onChange),
subscribe('globalObjective.updated', onChange),
);
}
clearInterval(sweepTimer);