110 lines
3.8 KiB
TypeScript
110 lines
3.8 KiB
TypeScript
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<string>((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)
|
|
})
|