Files
broccolini-bot/scripts/find-transcript-by-owner.js
2026-02-17 21:49:58 -06:00

93 lines
3.8 KiB
JavaScript

#!/usr/bin/env node
/**
* Find transcript messages whose embed "Ticket Owner" is a given user ID.
* Usage: node scripts/find-transcript-by-owner.js <channelId> <ownerId> [totalMessages] [maxMessages]
* If totalMessages is given, only show messages where "Users in transcript" sum equals that.
* Example: node scripts/find-transcript-by-owner.js 1335424071227281520 241129484483297280 5 10000
*/
const path = require('path');
const { Client, GatewayIntentBits } = require('discord.js');
require('dotenv').config({ path: path.join(__dirname, '../.env') });
require('dotenv').config({ path: path.join(__dirname, '../../.env') });
const TOKEN = process.env.MEMBER_BOT_TOKEN || process.env.DISCORD_BOT_TOKEN;
const channelId = process.argv[2];
const ownerId = process.argv[3];
const totalMessages = parseInt(process.argv[4], 10) || null;
const maxMessages = parseInt(process.argv[5], 10) || 10000;
const PAGE = 100;
function parseUsersTotal(value) {
let total = 0;
(value || '').split(/\n/).forEach((line) => {
const m = line.trim().match(/^(\d+)\s+-\s+<@!?\d+>/);
if (m) total += parseInt(m[1], 10);
});
return total;
}
if (!TOKEN || !channelId || !ownerId) {
console.error('Usage: node scripts/find-transcript-by-owner.js <channelId> <ownerId> [totalMessages] [maxMessages]');
process.exit(1);
}
const ownerRef = `<@${ownerId}>`;
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
});
client.once('ready', async () => {
try {
const channel = await client.channels.fetch(channelId).catch(() => null);
if (!channel) {
console.error('Channel not found or bot cannot access it.');
process.exit(1);
}
console.error('Channel:', channel.name, '(' + channel.id + ')');
console.error('Looking for Ticket Owner', ownerId, totalMessages != null ? 'and total=' + totalMessages : '');
let totalScanned = 0;
let before = undefined;
let found = 0;
while (totalScanned < maxMessages) {
const limit = Math.min(PAGE, maxMessages - totalScanned);
const options = before ? { limit, before } : { limit };
const messages = await channel.messages.fetch(options);
if (messages.size === 0) break;
totalScanned += messages.size;
for (const [, m] of messages.sort((a, b) => b.createdTimestamp - a.createdTimestamp)) {
if (!m.embeds?.length) continue;
for (const emb of m.embeds) {
const ownerField = emb.fields?.find((f) => f.name && f.name.toLowerCase().includes('ticket owner'));
if (!ownerField?.value || !ownerField.value.includes(ownerRef)) continue;
const usersField = emb.fields?.find((f) => f.name && f.name.toLowerCase().includes('users in transcript'));
const total = usersField?.value ? parseUsersTotal(usersField.value) : 0;
if (totalMessages != null && total !== totalMessages) continue;
const ticketNameField = emb.fields?.find((f) => f.name && f.name.toLowerCase().includes('ticket name'));
const ticketName = ticketNameField?.value?.trim() || '';
console.log('Message ID:', m.id);
console.log('Created:', m.createdAt.toISOString());
console.log('Ticket Name:', ticketName);
console.log('Total messages:', total);
console.log('---');
found++;
}
}
const oldestMsg = messages.reduce((a, msg) => (msg.createdTimestamp < (a?.createdTimestamp ?? Infinity) ? msg : a), null);
before = oldestMsg?.id;
if (messages.size < PAGE) break;
}
console.error('Scanned', totalScanned, 'messages, matches:', found);
} catch (e) {
console.error(e.message || e);
} finally {
client.destroy();
process.exit(0);
}
});
client.login(TOKEN).catch((e) => {
console.error('Login failed:', e.message);
process.exit(1);
});