#!/usr/bin/env node /** * User lookup using a dedicated minimal-permissions bot * * This bot: * - Has NO server permissions * - Only needs to be in the server * - Uses separate token from main bot * - Won't affect your main bot's rate limits * * Usage: * LOOKUP_BOT_TOKEN=your_token node scripts/lookup-with-dedicated-bot.js */ const fs = require('fs'); const path = require('path'); const { Client, GatewayIntentBits } = require('discord.js'); // Load environment require('dotenv').config({ path: path.join(__dirname, '../../.env') }); // Use dedicated bot token OR fall back to main bot const TOKEN = process.env.MEMBER_BOT_TOKEN || process.env.LOOKUP_BOT_TOKEN || process.env.DISCORD_BOT_TOKEN; if (!TOKEN) { console.error('āŒ Error: No bot token found'); console.error(' Set MEMBER_BOT_TOKEN in .env or use DISCORD_BOT_TOKEN'); process.exit(1); } const args = process.argv.slice(2); if (args.length < 2) { console.error('Usage: node scripts/lookup-with-dedicated-bot.js '); process.exit(1); } const inputFile = args[0]; const outputFile = args[1]; // Read user IDs const userIds = fs.readFileSync(inputFile, 'utf-8') .split('\n') .map(line => line.trim()) .filter(line => line.length > 0); console.log(`āœ… Loaded ${userIds.length} user IDs`); // Load existing results let results = {}; let processed = 0; let errors = 0; if (fs.existsSync(outputFile)) { try { const existing = JSON.parse(fs.readFileSync(outputFile, 'utf-8')); results = existing.users || {}; processed = Object.keys(results).length; errors = existing.errors || 0; console.log(`šŸ“‚ Found existing: ${processed} users`); } catch (e) { console.log(`āš ļø Starting fresh`); } } // Create bot with MINIMAL intents const client = new Client({ intents: [ GatewayIntentBits.Guilds // Only need this to stay in server // NO other intents needed! ] }); async function lookupUser(userId) { if (results[userId]) return results[userId]; try { const user = await client.users.fetch(userId); return { success: true, id: user.id, username: user.username, globalName: user.globalName || user.username, tag: user.tag, bot: user.bot, avatar: user.displayAvatarURL() }; } catch (error) { return { success: false, id: userId, error: error.message, username: null, globalName: null, tag: null, bot: false }; } } function saveResults() { const output = { timestamp: new Date().toISOString(), total_users: userIds.length, processed: processed, successful: processed - errors, errors: errors, bot_type: (process.env.MEMBER_BOT_TOKEN || process.env.LOOKUP_BOT_TOKEN) ? 'dedicated' : 'main', users: results }; fs.writeFileSync(outputFile, JSON.stringify(output, null, 2)); } async function processUsers() { console.log('\nšŸš€ Starting lookups...'); const isDedicated = !!(process.env.MEMBER_BOT_TOKEN || process.env.LOOKUP_BOT_TOKEN); console.log(` Bot type: ${isDedicated ? 'āœ… Dedicated lookup bot' : 'āš ļø Main bot'}`); console.log(` Rate: SLOW (1 user/second for safety)`); console.log(); const startTime = Date.now(); const toProcess = userIds.filter(id => !results[id]); console.log(` ${toProcess.length} users remaining\n`); for (let i = 0; i < toProcess.length; i++) { const userId = toProcess[i]; const result = await lookupUser(userId); results[result.id] = result; if (!result.success) errors++; processed++; // Save every 10 users for frequent updates if (processed % 10 === 0) { saveResults(); const elapsed = (Date.now() - startTime) / 1000; const rate = (processed - (userIds.length - toProcess.length)) / elapsed; const remaining = (toProcess.length - i - 1) / rate; console.log(`šŸ’¾ ${processed}/${userIds.length} (${errors} errors) - saved - ~${remaining.toFixed(0)}s left`); } // Very slow to avoid rate limits (1/second) await new Promise(resolve => setTimeout(resolve, 1000)); } saveResults(); const totalTime = (Date.now() - startTime) / 1000; console.log(`\n${'='.repeat(60)}`); console.log(`āœ… Complete!`); console.log(`${'='.repeat(60)}`); console.log(` Time: ${totalTime.toFixed(1)}s`); console.log(` Processed: ${processed}/${userIds.length}`); console.log(` Successful: ${processed - errors}`); console.log(` Errors: ${errors}`); console.log(`\nšŸ’¾ Saved to: ${outputFile}\n`); process.exit(0); } client.once('ready', () => { const isDedicated = !!(process.env.MEMBER_BOT_TOKEN || process.env.LOOKUP_BOT_TOKEN); const botType = isDedicated ? 'DEDICATED LOOKUP BOT' : 'Main Bot'; console.log(`āœ… Logged in as ${client.user.tag}`); console.log(` Type: ${botType}`); console.log(); processUsers(); }); client.on('error', (error) => { console.error('āŒ Error:', error.message); }); process.on('SIGINT', () => { console.log('\n\nāš ļø Interrupted! Saving...'); saveResults(); console.log('āœ… Saved. Resume by running same command.\n'); process.exit(0); }); console.log('šŸ”Œ Connecting to Discord...'); client.login(TOKEN);