Describe what you changed
This commit is contained in:
@@ -1,237 +1,237 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
* Discord user lookup WITH ROLES
|
* Discord user lookup WITH ROLES
|
||||||
*
|
*
|
||||||
* Fetches:
|
* Fetches:
|
||||||
* - User info (username, display name, avatar)
|
* - User info (username, display name, avatar)
|
||||||
* - Guild member info (roles, join date, server nickname)
|
* - Guild member info (roles, join date, server nickname)
|
||||||
* - All Palpocalypse server roles
|
* - All Palpocalypse server roles
|
||||||
*
|
*
|
||||||
* Requires: Server Members Intent enabled in Discord Developer Portal
|
* Requires: Server Members Intent enabled in Discord Developer Portal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { Client, GatewayIntentBits } = require('discord.js');
|
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 TOKEN = process.env.MEMBER_BOT_TOKEN || process.env.DISCORD_BOT_TOKEN;
|
||||||
const GUILD_ID = '798321161082896395'; // Indifferent Broccoli server
|
const GUILD_ID = '798321161082896395'; // Indifferent Broccoli server
|
||||||
|
|
||||||
if (!TOKEN) {
|
if (!TOKEN) {
|
||||||
console.error('❌ Error: No bot token found');
|
console.error('❌ Error: No bot token found');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
if (args.length < 2) {
|
if (args.length < 2) {
|
||||||
console.error('Usage: node scripts/lookup-with-roles.js <input_file> <output_file>');
|
console.error('Usage: node scripts/lookup-with-roles.js <input_file> <output_file>');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputFile = args[0];
|
const inputFile = args[0];
|
||||||
const outputFile = args[1];
|
const outputFile = args[1];
|
||||||
|
|
||||||
const userIds = fs.readFileSync(inputFile, 'utf-8')
|
const userIds = fs.readFileSync(inputFile, 'utf-8')
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(line => line.trim())
|
.map(line => line.trim())
|
||||||
.filter(line => line.length > 0);
|
.filter(line => line.length > 0);
|
||||||
|
|
||||||
console.log(`✅ Loaded ${userIds.length} user IDs`);
|
console.log(`✅ Loaded ${userIds.length} user IDs`);
|
||||||
|
|
||||||
let results = {};
|
let results = {};
|
||||||
let processed = 0;
|
let processed = 0;
|
||||||
let errors = 0;
|
let errors = 0;
|
||||||
|
|
||||||
if (fs.existsSync(outputFile)) {
|
if (fs.existsSync(outputFile)) {
|
||||||
try {
|
try {
|
||||||
const existing = JSON.parse(fs.readFileSync(outputFile, 'utf-8'));
|
const existing = JSON.parse(fs.readFileSync(outputFile, 'utf-8'));
|
||||||
results = existing.users || {};
|
results = existing.users || {};
|
||||||
processed = Object.keys(results).length;
|
processed = Object.keys(results).length;
|
||||||
errors = existing.errors || 0;
|
errors = existing.errors || 0;
|
||||||
console.log(`📂 Found existing: ${processed} users`);
|
console.log(`📂 Found existing: ${processed} users`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`⚠️ Starting fresh`);
|
console.log(`⚠️ Starting fresh`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
intents: [
|
intents: [
|
||||||
GatewayIntentBits.Guilds,
|
GatewayIntentBits.Guilds,
|
||||||
GatewayIntentBits.GuildMembers // Required for roles!
|
GatewayIntentBits.GuildMembers // Required for roles!
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
let guild = null;
|
let guild = null;
|
||||||
|
|
||||||
async function lookupUserWithRoles(userId) {
|
async function lookupUserWithRoles(userId) {
|
||||||
if (results[userId]) return results[userId];
|
if (results[userId]) return results[userId];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Fetch basic user info
|
// Fetch basic user info
|
||||||
const user = await client.users.fetch(userId);
|
const user = await client.users.fetch(userId);
|
||||||
|
|
||||||
// Try to fetch guild member (for roles)
|
// Try to fetch guild member (for roles)
|
||||||
let roles = [];
|
let roles = [];
|
||||||
let serverNickname = null;
|
let serverNickname = null;
|
||||||
let joinedAt = null;
|
let joinedAt = null;
|
||||||
let isInServer = false;
|
let isInServer = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const member = await guild.members.fetch(userId);
|
const member = await guild.members.fetch(userId);
|
||||||
isInServer = true;
|
isInServer = true;
|
||||||
serverNickname = member.nickname;
|
serverNickname = member.nickname;
|
||||||
joinedAt = member.joinedAt ? member.joinedAt.toISOString() : null;
|
joinedAt = member.joinedAt ? member.joinedAt.toISOString() : null;
|
||||||
|
|
||||||
// Get all roles except @everyone
|
// Get all roles except @everyone
|
||||||
roles = member.roles.cache
|
roles = member.roles.cache
|
||||||
.filter(role => role.name !== '@everyone')
|
.filter(role => role.name !== '@everyone')
|
||||||
.map(role => ({
|
.map(role => ({
|
||||||
id: role.id,
|
id: role.id,
|
||||||
name: role.name,
|
name: role.name,
|
||||||
color: role.hexColor,
|
color: role.hexColor,
|
||||||
position: role.position
|
position: role.position
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => b.position - a.position); // Highest role first
|
.sort((a, b) => b.position - a.position); // Highest role first
|
||||||
|
|
||||||
} catch (memberError) {
|
} catch (memberError) {
|
||||||
// User exists but not in this server
|
// User exists but not in this server
|
||||||
isInServer = false;
|
isInServer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
globalName: user.globalName || user.username,
|
globalName: user.globalName || user.username,
|
||||||
tag: user.tag,
|
tag: user.tag,
|
||||||
bot: user.bot,
|
bot: user.bot,
|
||||||
avatar: user.displayAvatarURL(),
|
avatar: user.displayAvatarURL(),
|
||||||
// Server-specific data
|
// Server-specific data
|
||||||
server_nickname: serverNickname,
|
server_nickname: serverNickname,
|
||||||
joined_at: joinedAt,
|
joined_at: joinedAt,
|
||||||
in_server: isInServer,
|
in_server: isInServer,
|
||||||
roles: roles,
|
roles: roles,
|
||||||
role_names: roles.map(r => r.name),
|
role_names: roles.map(r => r.name),
|
||||||
highest_role: roles[0]?.name || null
|
highest_role: roles[0]?.name || null
|
||||||
};
|
};
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
id: userId,
|
id: userId,
|
||||||
error: error.message,
|
error: error.message,
|
||||||
username: null,
|
username: null,
|
||||||
globalName: null,
|
globalName: null,
|
||||||
roles: []
|
roles: []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveResults() {
|
function saveResults() {
|
||||||
const output = {
|
const output = {
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
total_users: userIds.length,
|
total_users: userIds.length,
|
||||||
processed: processed,
|
processed: processed,
|
||||||
successful: processed - errors,
|
successful: processed - errors,
|
||||||
errors: errors,
|
errors: errors,
|
||||||
guild_id: GUILD_ID,
|
guild_id: GUILD_ID,
|
||||||
includes_roles: true,
|
includes_roles: true,
|
||||||
users: results
|
users: results
|
||||||
};
|
};
|
||||||
|
|
||||||
fs.writeFileSync(outputFile, JSON.stringify(output, null, 2));
|
fs.writeFileSync(outputFile, JSON.stringify(output, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function processUsers() {
|
async function processUsers() {
|
||||||
console.log('\n🎭 Starting lookups WITH ROLES...');
|
console.log('\n🎭 Starting lookups WITH ROLES...');
|
||||||
console.log(` Guild ID: ${GUILD_ID}`);
|
console.log(` Guild ID: ${GUILD_ID}`);
|
||||||
console.log(` Rate: 1 user/second\n`);
|
console.log(` Rate: 1 user/second\n`);
|
||||||
|
|
||||||
// Fetch guild
|
// Fetch guild
|
||||||
guild = await client.guilds.fetch(GUILD_ID);
|
guild = await client.guilds.fetch(GUILD_ID);
|
||||||
console.log(`✅ Connected to: ${guild.name}\n`);
|
console.log(`✅ Connected to: ${guild.name}\n`);
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const toProcess = userIds.filter(id => !results[id]);
|
const toProcess = userIds.filter(id => !results[id]);
|
||||||
console.log(` ${toProcess.length} users remaining\n`);
|
console.log(` ${toProcess.length} users remaining\n`);
|
||||||
|
|
||||||
for (let i = 0; i < toProcess.length; i++) {
|
for (let i = 0; i < toProcess.length; i++) {
|
||||||
const userId = toProcess[i];
|
const userId = toProcess[i];
|
||||||
|
|
||||||
const result = await lookupUserWithRoles(userId);
|
const result = await lookupUserWithRoles(userId);
|
||||||
results[result.id] = result;
|
results[result.id] = result;
|
||||||
|
|
||||||
if (!result.success) errors++;
|
if (!result.success) errors++;
|
||||||
processed++;
|
processed++;
|
||||||
|
|
||||||
// Save every 10 users
|
// Save every 10 users
|
||||||
if (processed % 10 === 0) {
|
if (processed % 10 === 0) {
|
||||||
saveResults();
|
saveResults();
|
||||||
const elapsed = (Date.now() - startTime) / 1000;
|
const elapsed = (Date.now() - startTime) / 1000;
|
||||||
const rate = (processed - (userIds.length - toProcess.length)) / elapsed;
|
const rate = (processed - (userIds.length - toProcess.length)) / elapsed;
|
||||||
const remaining = (toProcess.length - i - 1) / rate;
|
const remaining = (toProcess.length - i - 1) / rate;
|
||||||
|
|
||||||
// Show sample with roles
|
// Show sample with roles
|
||||||
if (result.success && result.roles.length > 0) {
|
if (result.success && result.roles.length > 0) {
|
||||||
const rolePreview = result.role_names.slice(0, 2).join(', ');
|
const rolePreview = result.role_names.slice(0, 2).join(', ');
|
||||||
console.log(`💾 ${processed}/${userIds.length} - ${result.globalName} [${rolePreview}] - ~${remaining.toFixed(0)}s left`);
|
console.log(`💾 ${processed}/${userIds.length} - ${result.globalName} [${rolePreview}] - ~${remaining.toFixed(0)}s left`);
|
||||||
} else {
|
} else {
|
||||||
console.log(`💾 ${processed}/${userIds.length} (${errors} errors) - ~${remaining.toFixed(0)}s left`);
|
console.log(`💾 ${processed}/${userIds.length} (${errors} errors) - ~${remaining.toFixed(0)}s left`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
saveResults();
|
saveResults();
|
||||||
|
|
||||||
const totalTime = (Date.now() - startTime) / 1000;
|
const totalTime = (Date.now() - startTime) / 1000;
|
||||||
|
|
||||||
// Stats
|
// Stats
|
||||||
const usersWithRoles = Object.values(results).filter(u => u.success && u.roles.length > 0).length;
|
const usersWithRoles = Object.values(results).filter(u => u.success && u.roles.length > 0).length;
|
||||||
const allRoleNames = new Set();
|
const allRoleNames = new Set();
|
||||||
Object.values(results).forEach(u => {
|
Object.values(results).forEach(u => {
|
||||||
if (u.success) {
|
if (u.success) {
|
||||||
u.role_names?.forEach(r => allRoleNames.add(r));
|
u.role_names?.forEach(r => allRoleNames.add(r));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`\n${'='.repeat(70)}`);
|
console.log(`\n${'='.repeat(70)}`);
|
||||||
console.log(`✅ Complete with Roles!`);
|
console.log(`✅ Complete with Roles!`);
|
||||||
console.log(`${'='.repeat(70)}`);
|
console.log(`${'='.repeat(70)}`);
|
||||||
console.log(` Time: ${totalTime.toFixed(1)}s`);
|
console.log(` Time: ${totalTime.toFixed(1)}s`);
|
||||||
console.log(` Processed: ${processed}/${userIds.length}`);
|
console.log(` Processed: ${processed}/${userIds.length}`);
|
||||||
console.log(` Successful: ${processed - errors}`);
|
console.log(` Successful: ${processed - errors}`);
|
||||||
console.log(` Users with roles: ${usersWithRoles}`);
|
console.log(` Users with roles: ${usersWithRoles}`);
|
||||||
console.log(` Unique roles found: ${allRoleNames.size}`);
|
console.log(` Unique roles found: ${allRoleNames.size}`);
|
||||||
console.log(`\n💾 Saved to: ${outputFile}\n`);
|
console.log(`\n💾 Saved to: ${outputFile}\n`);
|
||||||
|
|
||||||
// Show some roles
|
// Show some roles
|
||||||
if (allRoleNames.size > 0) {
|
if (allRoleNames.size > 0) {
|
||||||
console.log('📋 Sample roles found:');
|
console.log('📋 Sample roles found:');
|
||||||
Array.from(allRoleNames).slice(0, 10).forEach(r => console.log(` • ${r}`));
|
Array.from(allRoleNames).slice(0, 10).forEach(r => console.log(` • ${r}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
client.once('ready', () => {
|
client.once('ready', () => {
|
||||||
console.log(`✅ Logged in as ${client.user.tag}\n`);
|
console.log(`✅ Logged in as ${client.user.tag}\n`);
|
||||||
processUsers();
|
processUsers();
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on('error', (error) => {
|
client.on('error', (error) => {
|
||||||
console.error('❌ Error:', error.message);
|
console.error('❌ Error:', error.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
console.log('\n\n⚠️ Interrupted! Saving...');
|
console.log('\n\n⚠️ Interrupted! Saving...');
|
||||||
saveResults();
|
saveResults();
|
||||||
console.log('✅ Saved. Resume by running same command.\n');
|
console.log('✅ Saved. Resume by running same command.\n');
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('🔌 Connecting to Discord...');
|
console.log('🔌 Connecting to Discord...');
|
||||||
client.login(TOKEN);
|
client.login(TOKEN);
|
||||||
|
|||||||
Reference in New Issue
Block a user