fix spectator page, add discord ping filtering

This commit is contained in:
legop3
2025-11-24 02:47:21 -05:00
parent be1b345fbb
commit 59021281e9
12 changed files with 194 additions and 122 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -11,8 +11,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
<title>Multi Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-Bu0ya-aM.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B8zLJlAS.css">
<script type="module" crossorigin src="/assets/index-B4HXdpZh.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B5WmdT7o.css">
</head>
<body>
<div id="root"></div>
+47 -12
View File
@@ -37,6 +37,16 @@ const client = new Client({
const channelCache = new Map();
function sanitizeMentions(text) {
if (!text) return '';
return String(text)
// strip mention tokens
.replace(/<(@[!&]?\d+|#\d+)>/g, '[ping removed]')
// neutralize everyone/here
.replace(/@everyone/gi, '[everyone]')
.replace(/@here/gi, '[here]');
}
function formatRoverStatus(rover) {
if (!rover) return 'Unknown rover';
const percent = rover.batteryState?.percentDisplay;
@@ -80,11 +90,11 @@ async function fetchChannel(id) {
return null;
}
async function sendToChannel(id, content, options = {}) {
async function sendToChannel(id, content, options = {}, allowedMentions = { parse: [] }) {
const channel = await fetchChannel(id);
if (!channel) return;
try {
await channel.send({ content, ...options });
await channel.send({ content: sanitizeMentions(content), allowedMentions, ...options });
} catch (err) {
logger.warn('Failed to send Discord message', { id, error: err.message });
}
@@ -115,37 +125,61 @@ async function handleStatusCommand(message, roverId) {
const roster = getRoster();
if (!roverId) {
const summary = roster.map((r) => formatRoverStatus(r)).join('\n') || 'No rovers online.';
await message.reply(summary.slice(0, 1900));
await message.reply({
content: sanitizeMentions(summary.slice(0, 1900)),
allowedMentions: { parse: [], repliedUser: false },
});
return;
}
const rover = findRover(roverId);
await message.reply(formatRoverStatus(rover).slice(0, 1900));
await message.reply({
content: sanitizeMentions(formatRoverStatus(rover).slice(0, 1900)),
allowedMentions: { parse: [], repliedUser: false },
});
}
async function handleLockCommand(message, roverId, locked) {
if (!roverId) {
await message.reply('Specify a rover ID. Example: `rover lock alpha`');
await message.reply({
content: 'Specify a rover ID. Example: `rs lock alpha`',
allowedMentions: { parse: [], repliedUser: false },
});
return;
}
try {
lockRover(roverId, locked, { reason: 'discord' });
await message.reply(`${locked ? 'Locked' : 'Unlocked'} ${roverId}.`);
await message.reply({
content: sanitizeMentions(`${locked ? 'Locked' : 'Unlocked'} ${roverId}.`),
allowedMentions: { parse: [], repliedUser: false },
});
} catch (err) {
await message.reply(`Failed: ${err.message}`);
await message.reply({
content: sanitizeMentions(`Failed: ${err.message}`),
allowedMentions: { parse: [], repliedUser: false },
});
}
}
async function handleModeCommand(message, mode) {
const next = String(mode || '').toLowerCase();
if (!Object.values(MODES).includes(next)) {
await message.reply('Invalid mode. Use one of: open, turns, admin, lockdown.');
await message.reply({
content: 'Invalid mode. Use one of: open, turns, admin, lockdown.',
allowedMentions: { parse: [], repliedUser: false },
});
return;
}
try {
setMode(next, null, { force: true });
await message.reply(`Mode set to ${next}.`);
await message.reply({
content: sanitizeMentions(`Mode set to ${next}.`),
allowedMentions: { parse: [], repliedUser: false },
});
} catch (err) {
await message.reply(`Failed to set mode: ${err.message}`);
await message.reply({
content: sanitizeMentions(`Failed to set mode: ${err.message}`),
allowedMentions: { parse: [], repliedUser: false },
});
}
}
@@ -224,7 +258,8 @@ async function announce({ channelId, content, pingRoleId, color, title, descript
if (!channelId) return;
const prefix = pingRoleId ? `<@&${pingRoleId}> ` : '';
const embed = buildEmbed({ title, description, color });
await sendToChannel(channelId, `${prefix}${content || ''}`.trim(), { embeds: [embed] });
const allowedMentions = pingRoleId ? { roles: [pingRoleId], parse: [] } : { parse: [] };
await sendToChannel(channelId, `${prefix}${content || ''}`.trim(), { embeds: [embed] }, allowedMentions);
}
function handleBusEvent(event) {
@@ -360,7 +395,7 @@ function handleChatBridgeOutbound(event) {
if (!bridgeChannelId) return;
const line = formatChatLine(payload);
const text = line.length > 1900 ? `${line.slice(0, 1897)}...` : line;
sendToChannel(bridgeChannelId, text);
sendToChannel(bridgeChannelId, text, {}, { parse: [] });
}
client.on('messageCreate', async (message) => {