79 lines
2.6 KiB
JavaScript
79 lines
2.6 KiB
JavaScript
import { isIP } from 'node:net'
|
|
import { DatabaseSync } from 'node:sqlite'
|
|
|
|
const [command, rawIp, rawLimit, ...noteParts] = process.argv.slice(2)
|
|
const database = new DatabaseSync('data/game.db')
|
|
|
|
function normalizeIp(value) {
|
|
const address = String(value ?? '').trim()
|
|
if (address.startsWith('::ffff:') && isIP(address.slice(7)) === 4) {
|
|
return address.slice(7)
|
|
}
|
|
return address
|
|
}
|
|
|
|
function requireIp(value) {
|
|
const address = normalizeIp(value)
|
|
if (!isIP(address)) {
|
|
throw new Error('Provide a valid IPv4 or IPv6 address.')
|
|
}
|
|
return address
|
|
}
|
|
|
|
try {
|
|
if (command === 'set') {
|
|
const ip = requireIp(rawIp)
|
|
const maxAccounts = Number(rawLimit)
|
|
if (!Number.isInteger(maxAccounts) || maxAccounts < 2 || maxAccounts > 100) {
|
|
throw new Error('The allowed account count must be an integer from 2 to 100.')
|
|
}
|
|
const note = noteParts.join(' ').slice(0, 200)
|
|
database.prepare(`
|
|
INSERT INTO account_ip_allowances
|
|
(ip_address, max_accounts, note, updated_at)
|
|
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
|
|
ON CONFLICT(ip_address) DO UPDATE SET
|
|
max_accounts = excluded.max_accounts,
|
|
note = excluded.note,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
`).run(ip, maxAccounts, note)
|
|
console.log(`${ip} may create up to ${maxAccounts} accounts${note ? ` (${note})` : ''}.`)
|
|
} else if (command === 'remove') {
|
|
const ip = requireIp(rawIp)
|
|
const result = database.prepare(`
|
|
DELETE FROM account_ip_allowances WHERE ip_address = ?
|
|
`).run(ip)
|
|
console.log(
|
|
result.changes
|
|
? `${ip} returned to the default one-account limit.`
|
|
: `${ip} had no custom allowance.`,
|
|
)
|
|
} else if (command === 'list') {
|
|
const rows = database.prepare(`
|
|
SELECT
|
|
account_ip_allowances.ip_address AS ip,
|
|
account_ip_allowances.max_accounts AS maxAccounts,
|
|
account_ip_allowances.note,
|
|
account_ip_allowances.updated_at AS updatedAt,
|
|
COUNT(accounts.id) AS existingAccounts
|
|
FROM account_ip_allowances
|
|
LEFT JOIN accounts
|
|
ON accounts.created_ip = account_ip_allowances.ip_address
|
|
GROUP BY account_ip_allowances.ip_address
|
|
ORDER BY account_ip_allowances.updated_at DESC
|
|
`).all()
|
|
console.table(rows)
|
|
} else {
|
|
console.log('Usage:')
|
|
console.log(' npm run accounts:ip -- set <ip> <max-accounts> [note]')
|
|
console.log(' npm run accounts:ip -- remove <ip>')
|
|
console.log(' npm run accounts:ip -- list')
|
|
process.exitCode = command ? 1 : 0
|
|
}
|
|
} catch (error) {
|
|
console.error(error instanceof Error ? error.message : error)
|
|
process.exitCode = 1
|
|
} finally {
|
|
database.close()
|
|
}
|