UNPKG

flying-squid

Version:
402 lines (374 loc) 12.8 kB
const moment = require('moment') const needle = require('needle') const UserError = require('flying-squid').UserError module.exports.server = function (serv, settings) { serv.ban = async (uuid, reason) => { if (!serv.bannedPlayers[uuid]) { serv.bannedPlayers[uuid] = { time: +moment(), reason: reason || 'Your account is banned!' } return true } else return false } serv.banIP = async (IP, reason) => { if (!serv.bannedIPs[IP]) { serv.bannedIPs[IP] = { time: +moment(), reason: reason || 'Your IP is banned!' } Object.keys(serv.players) .filter(uuid => serv.players[uuid]._client.socket?.remoteAddress === IP) .forEach(uuid => serv.players[uuid].kick(serv.bannedIPs[serv.players[uuid]._client.socket?.remoteAddress].reason)) return true } else return false } function uuidInParts (plainUUID) { return plainUUID.length === 32 ? plainUUID.substring(0, 8) + '-' + plainUUID.substring(8, 12) + '-' + plainUUID.substring(12, 16) + '-' + plainUUID.substring(16, 20) + '-' + plainUUID.substring(20) : plainUUID } serv.getUUIDFromUsername = async username => { return await new Promise((resolve, reject) => { needle('get', 'https://api.mojang.com/users/profiles/minecraft/' + username, { json: true }) .then((response) => { if (!response.body) throw new Error('username not found') const idstr = response.body.id if (typeof idstr !== 'string') throw new Error('username not found') resolve(uuidInParts(idstr)) }) .catch(err => { throw err }) }) } serv.banUsername = async (username, reason) => { return serv.ban(username, reason) } serv.banUUID = async (username, reason) => { return serv.getUUIDFromUsername(username).then(uuid => serv.ban(uuid, reason)) } serv.pardonUsername = async (username) => { return pardon(username) } serv.pardonUUID = async (username) => { return serv.getUUIDFromUsername(username) .then(pardon) } serv.pardonIP = async (IP) => { return serv.bannedIPs[IP] ? delete serv.bannedIPs[IP] : false } function pardon (uuid) { if (serv.bannedPlayers[uuid]) { delete serv.bannedPlayers[uuid] return true } return false } serv.bannedPlayers = {} serv.bannedIPs = {} serv.commands.add({ base: 'op', info: 'Op a player', usage: '/op <player>', op: true, parse (params) { if (!params.match(/([a-zA-Z0-9_]+)/)) return false return params }, action (params) { const [inputUsername] = params.split(' ') // get player, by non-case-sensitive username const player = serv.players.find(player => player.username.toLowerCase() === inputUsername.toLowerCase()) if (player === undefined || player === null) { const arr = serv.selectorString(params) if (arr.length === 0) throw new UserError('Could not find player') arr.map(entity => { entity.op = true return `Opped ${entity}` }) } else { if (!player.op) { player.op = true player.chat(`§7§o[${player.username ?? 'Server'}: Opped ${player.username}]`) return `Opped ${player.username}` } else { return `${player.username} is opped already` } } } }) serv.commands.add({ base: 'deop', info: 'Deop a player', usage: '/deop <player>', op: true, parse (params) { if (!params.match(/([a-zA-Z0-9_]+)/)) return false return params }, action (params) { params = params.split(' ') const player = serv.getPlayer(params[0]) if (player === undefined || player === null) { const arr = serv.selectorString(params) if (arr.length === 0) throw new UserError('Could not find player') arr.map(entity => { entity.op = false return `Deopped ${entity}` }) } else { if (player.op) { player.op = false player.chat(`§7§o[Server: Deopped ${params[0]}]`) return `Deopped ${params[0]}` } else { return `${params[0]} isn't opped` } } } }) serv.commands.add({ base: 'kick', info: 'to kick a player', usage: '/kick <player> [reason]', op: true, parse (str) { if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } const parts = str.split(' ') return { username: parts.shift(), reason: parts.join(' ') } }, action ({ username, reason }, ctx) { const kickPlayer = serv.getPlayer(username) if (!kickPlayer) { if (ctx.player) ctx.player.chat(username + ' is not on this server!') else throw new UserError(username + ' is not on this server!') } else { kickPlayer.kick(reason) kickPlayer.emit('kicked', ctx.player ? ctx.player : { username: '[@]' }, reason) } } }) serv.commands.add({ base: 'ban', info: 'to ban a player', usage: '/ban <player> [reason]', op: true, parse (str) { if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } const parts = str.split(' ') return { username: parts.shift(), reason: parts.join(' ') } }, action ({ username, reason }, ctx) { const banPlayer = serv.getPlayer(username) if (!banPlayer) { if (settings['online-mode']) { serv.banUUID(username, reason) .then(result => { if (result) { serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) .catch(err => { if (err) { // This tricks eslint if (ctx.player) ctx.player.chat(username + ' is not a valid player!') else serv.err(username + ' is not a valid player!') } }) } else { serv.banUsername(username, reason) .then(result => { if (result) { serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) .catch(err => { if (err) { // This tricks eslint if (ctx.player) ctx.player.chat(username + ' is not a valid player!') else serv.err(username + ' is not a valid player!') } }) } } else { if (settings['online-mode']) { banPlayer.banUUID(reason) .then(result => { if (result) { serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) } else { banPlayer.banUsername(reason) .then(result => { if (result) { serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) } } } }) serv.commands.add({ base: 'ban-ip', info: 'bans a specific IP', usage: '/ban-ip <ip> [reason]', op: true, parse (str) { const argv = str.split(' ') if (argv[0] === '') return false if (!/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(argv[0])) throw new UserError('IP is not correct') return { IP: argv.shift(), reason: argv.shift() } }, action ({ IP, reason }, ctx) { serv.banIP(IP, reason) .then(result => { if (result) { if (ctx.player) ctx.player.chat(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) else serv.info(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) } else { if (ctx.player) ctx.player.chat(`IP ${IP} is banned!`) else serv.err(`IP ${IP} is banned!`) } }) } }) serv.commands.add({ base: 'banlist', info: 'Displays banlist.', usage: '/banlist', op: true, action (v, ctx) { const pllist = Object.keys(serv.bannedPlayers) const iplist = Object.keys(serv.bannedIPs) if (v !== 'ips') { if (ctx.player) { ctx.player.chat(`There are ${pllist.length} total banned players${pllist.length > 0 ? ':' : ''}`) pllist.forEach(e => { ctx.player.chat(e) }) } else { serv.info(`There are ${pllist.length} total banned players${pllist.length > 0 ? ':' : ''}`) pllist.forEach(e => { serv.info(e) }) } } else { if (ctx.player) { ctx.player.chat(`There are ${iplist.length} total banned IP addresses${iplist.length > 0 ? ':' : ''}`) iplist.forEach(e => { ctx.player.chat(e) }) } else { serv.info(`There are ${iplist.length} total banned IP addresses${iplist.length > 0 ? ':' : ''}`) iplist.forEach(e => { serv.info(e) }) } } } }) serv.commands.add({ base: 'pardon-ip', info: 'to pardon a player by ip', usage: '/pardon-ip <ip>', op: true, action (IP, ctx) { serv.pardonIP(IP) .then(result => { if (result) { if (ctx.player) ctx.player.chat(`IP ${IP} was pardoned`) else serv.info(`IP ${IP} was pardoned`) } else { if (ctx.player) ctx.player.chat(`IP ${IP} is not banned`) else serv.err(`IP ${IP} is not banned`) } }) } }) serv.commands.add({ base: 'pardon', info: 'to pardon a player', usage: '/pardon <player>', op: true, parse (str) { if (!str.match(/([a-zA-Z0-9_]+)/)) { return false } return str }, action (nick, ctx) { if (settings['online-mode']) { serv.pardonUUID(nick) .then((result) => { if (result) { if (ctx.player) ctx.player.chat(nick + ' is unbanned') else serv.info(nick + ' is unbanned') } else { if (ctx.player) ctx.player.chat(nick + ' is not banned') else serv.err(nick + ' is not banned') } }) } else { serv.pardonUsername(nick) .then((result) => { if (result) { if (ctx.player) ctx.player.chat(nick + ' is unbanned') else serv.info(nick + ' is unbanned') } else { if (ctx.player) ctx.player.chat(nick + ' is not banned') else serv.err(nick + ' is not banned') } }) } } }) } module.exports.player = function (player, serv) { player.kick = (reason = 'You were kicked!') => { serv.log(`Kicking ${player.username} for '${reason}'`) player._client.end(reason) } player.banUUID = reason => { reason = reason || 'You were banned!' player.kick(reason) const uuid = player.uuid return serv.ban(uuid, reason) } player.banUsername = reason => { reason = reason || 'You were banned!' player.kick(reason) const nick = player.username return serv.banUsername(nick, reason) } player.banIP = reason => { reason = reason || 'You were IP banned!' player.kick(reason) return serv.banIP(player._client.socket?.remoteAddress) } // I think it doesn't do anything but ok well... player.pardonUUID = () => serv.pardonUsername(player.uuid) player.pardonUsername = () => serv.pardonUsername(player.username) }