Files
i-want-to-heal/scripts/manage-ip-allowance.mjs
2026-06-17 20:04:36 -04:00

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()
}