184 lines
5.5 KiB
JavaScript
184 lines
5.5 KiB
JavaScript
#!/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 <input_file> <output_file>
|
||
*/
|
||
|
||
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 <input_file> <output_file>');
|
||
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);
|