import { MongoClient, ObjectId } from 'mongodb' import * as dotenv from 'dotenv' import readline from 'readline' dotenv.config() const MONGODB_URI = process.env.MONGODB_URI if (!MONGODB_URI) { console.error('Please define the MONGODB_URI environment variable in .env') process.exit(1) } const colors = { reset: '\x1b[0m', bright: '\x1b[1m', dim: '\x1b[2m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', cyan: '\x1b[36m', } function decorateHeader(text: string) { const line = '='.repeat(60) return `\n${colors.cyan}${line}\n${text}\n${line}${colors.reset}` } async function prompt(question: string) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }) return new Promise((resolve) => { rl.question(question, (ans) => { rl.close() resolve(ans) }) }) } async function main() { const client = new MongoClient(MONGODB_URI!) await client.connect() const db = client.db('pummmpfun') const users = db.collection('users') const trades = db.collection('trades') const comments = db.collection('comments') const normalDomains = [ 'gmail\\.com', 'outlook\\.com', 'hotmail\\.com', 'yahoo\\.com', 'aol\\.com', 'icloud\\.com', 'protonmail\\.com', 'gmx\\.com' ] const normalRegex = new RegExp(`@(?:${normalDomains.join('|')})$`, 'i') console.log(decorateHeader(`${colors.bright}BAN ALTS - NON-NORMAL EMAILS${colors.reset}`)) console.log(`${colors.dim}This script will iterate accounts with non-standard email domains (not common providers) and prompt to delete each user and their trades/comments.${colors.reset}\n`) // Query: either no email, or email not matching normal providers const cursor = users.find({ $or: [ { email: { $exists: false } }, { email: { $not: normalRegex } } ] }) let count = 0 try { while (await cursor.hasNext()) { const user: any = await cursor.next() count += 1 // Display user console.log(`\n${colors.yellow}#${count}${colors.reset} ${colors.bright}${user.name || 'Unnamed'}${colors.reset} — ${colors.cyan}${user.email || 'no-email'}${colors.reset}`) console.log(`${colors.dim}ID: ${user._id.toString()} | Balance: ${user.balance ?? 0} | Created: ${user.createdAt || 'N/A'}${colors.reset}`) console.log('\n' + colors.bright + 'Preview actions:' + colors.reset) console.log(` - Delete user document from 'users'`) console.log(` - Delete trades where userId matches user._id or discordId`) console.log(` - Delete comments where userId matches user._id or discordId\n`) const answer = (await prompt(`${colors.red}Ban/delete this ALT account and associated trades/comments? (y/N): ${colors.reset}`)).trim() if (answer.toLowerCase() === 'y') { const userIdStr = user._id.toString() const discordId = user.discordId // delete user and associated content const delUser = await users.deleteOne({ _id: new ObjectId(user._id) }) const delTrades = await trades.deleteMany({ $or: [{ userId: userIdStr }, { userId: discordId }] }) const delComments = await comments.deleteMany({ $or: [{ userId: userIdStr }, { userId: discordId }] }) console.log(`${colors.green}Deleted user:${colors.reset} ${delUser.deletedCount} | ${colors.green}Trades removed:${colors.reset} ${delTrades.deletedCount} | ${colors.green}Comments removed:${colors.reset} ${delComments.deletedCount}`) } else { console.log(`${colors.dim}Skipped${colors.reset}`) } // small pause await new Promise((r) => setTimeout(r, 120)) } console.log(`\n${colors.bright}Done. Processed ${count} accounts.${colors.reset}`) } catch (e) { console.error('Error during processing:', e) } finally { await client.close() } } main().catch((e) => { console.error(e) process.exit(1) })