chipmunkbot-archive/plugins/commands.js
2022-11-13 01:32:35 +00:00

133 lines
4.3 KiB
JavaScript

const fs = require('fs')
const path = require('path')
const { inspect } = require('util')
const { parseText } = require('../util/text_parser.js')
const { getHash } = require('../util/cval.js')
const sectionRegex = /\xa7.?/g
function inject (bot, options) {
bot.commands = {
commands: {},
add,
execute,
info,
isCommand,
loadFromDir,
isValid
}
const listener = ({ message }, { sender }) => {
message = parseText(message).raw // fard
const player = bot.players[sender]
if (!message.startsWith(bot.prefix)) return
const args = message.slice(bot.prefix.length).trim().split(' ')
const command = args.shift().toLowerCase()
if (!isCommand(command)) {
bot.tellraw({ text: `Unknown command: ${bot.prefix}${command}`, color: bot.colors.error })
return
}
if (args[args.length - 1]?.endsWith('\\')) {
bot.tellraw({ text: 'This will be added... idk when.' })
return
}
const { permLevel } = bot.commands.info(command)
if (permLevel) {
if (args.length === 0) {
bot.tellraw({ text: 'Expected a hash', color: bot.colors.error })
return
}
// TODO: Don't use a bad argument parser
const commandHashLength = message.charCodeAt(message.length - 2) * 2
if (commandHashLength >= message.length) {
bot.tellraw({ text: `Length of the hash (${commandHashLength}) is longer than the message's length (${message.length})`, color: bot.colors.error })
return
}
const originalCommand = message.substring(0, message.length - commandHashLength - 4)
let commandHash = ''
for (let i = message.length - commandHashLength - 2; i < message.length - 3; i += 2) {console.log(i, message[i])
if (message[i - 1] !== '\xa7') {
bot.tellraw(`Expected an escape character at ${i - 1}`)
return
}
commandHash += message[i]
}
const hash = getHash(originalCommand, player.UUID, options.trustedKey)
console.log({ message, commandHash, commandHashLength, hash, originalCommand })
if (commandHash !== hash) {
bot.tellraw({ text: 'Invalid hash', color: bot.colors.error })
return
}
args.splice(-1, hash.split(' ').length) // TODO: Make this less bad
}
bot.commands.execute(bot, command, player, args)
}
bot.on('emote', listener)
bot.on('whisper', listener)
bot.on('announcement', listener)
function add (command) {
if (!isValid(command)) throw new Error('Invalid command', 'invalid_command')
command.aliases.forEach(alias => (bot.commands.commands[alias.toLowerCase()] = command))
}
function loadFromDir (dirpath) {
fs.readdirSync(dirpath).forEach(filename => {
const filepath = path.resolve(dirpath, filename)
if (!filepath.endsWith('js') || !fs.statSync(filepath).isFile()) return // TODO: Use require.extensions
try {
bot.commands.add(require(filepath))
} catch (err) {
bot.console.error('Error loading command ' + filepath + ': ' + inspect(err))
}
})
}
function info (command) {
const info = bot.commands.commands[command] ?? command
if (isValid(info)) return info
}
function isCommand (command) { return bot.commands.info(command) != null }
async function execute (bot, command, player, args, ...custom) {
const info = bot.commands.info(command)
if (info == null) {
bot.tellraw({ text: 'Unknown command: ' + bot.prefix + command, color: bot.colors.error })
return
}
if (!info.enabled) {
bot.tellraw({ text: bot.prefix + command + ' is disabled', color: bot.colors.error })
return
}
try {
return await info.execute(bot, command, player, args, ...custom)
} catch (err) {
bot.console.error('Error executing command ' + command + ': ' + inspect(err))
bot.tellraw({ text: err?.name + ': ' + err?.message, color: bot.colors.error })
}
}
}
function isValid (command) {
return command != null &&
typeof command.execute === 'function' &&
typeof command.name === 'string' &&
typeof command.description === 'string' &&
Array.isArray(command.usages) &&
Array.isArray(command.aliases) &&
typeof command.enabled === 'boolean' &&
command.aliases.length > 0 &&
typeof command.permLevel === 'number'
}
module.exports.bot = inject