ext-manager
Version:
A package to manage an extensions for event listeners or discord bot commands with ease
201 lines (168 loc) • 5.98 kB
JavaScript
/* eslint-disable no-ex-assign */
/* eslint-disable no-eval */
/* eslint-disable node/handle-callback-err */
/* eslint-disable no-unused-vars */
const Discord = require('discord.js')
const BasePaginator = require('discord-paginator.js')
const yargs = require('yargs-parser')
const util = require('util')
const { isOwner } = require('../bot/commandManager/parser')
function arraySplitter (array, pages = 10) {
const arr = []
const len = array.length
for (let i = 0; i < len / pages; i++) {
arr.push(array.splice(0, pages))
}
if (arr.length < len / pages) {
arr.push(array.splice(0, array.length))
}
return arr
}
function merge (array, arr) {
const len = Math.max(array.length, arr.length)
const merged = []
let o = -1
for (let i = 0; i < len; i++) {
const mergeArr = []
mergeArr.push(array[i] || array[o])
mergeArr.push(arr[i] || arr[o])
merged.push(mergeArr)
if (array[i] && arr[i]) o++
continue
}
return merged
}
function clean (text, token) {
return text
.replace(/`/g, '`' + String.fromCharCode(8203))
.replace(/@/g, '@' + String.fromCharCode(8203))
.replace(new RegExp(token, 'g'), '[Token]')
}
/**
* an eval command for a discord bot developer.
*/
class EvalCommand {
/**
* @param {Object} [options] Options for the eval command
*/
constructor (options) {
this.name = 'eval'
this.ownerOnly = 'This command is can only used by bot developers!'
Object.assign(this, options)
this.type = 'command'
}
/**
* @param {Discord.Message} message A discord message
* @param {Array<String>} args An Array of strings
* @param {String} prefix The bot prefix
* @param {Object} CMD The command
*/
async main (message, args, prefix, CMD) {
if (!args.length) {
message.channel.send('Please enter a code to evaluate with!').catch(console.error)
return
}
const { client } = message
const { options } = client
const { evalCommand } = options
const embed = evalCommand ? evalCommand.embed : undefined
const opts = {
alias: {
async: ['a'],
embed: ['e'],
silent: ['s'],
console: ['c', 'log'],
depth: ['d']
},
boolean: ['async', 'embed', 'silent', 'console'],
number: ['depth'],
default: {
async: false,
embed: embed instanceof Object,
silent: false,
console: false,
depth: 0
}
}
const argv = yargs(args.join(' '), opts)
let code = argv._.join(' ').trim()
let reaction
let content = {}
const timeout = setTimeout(async () => {
reaction = await message.react('▶️').catch(err => {})
}, 5000)
try {
let evaled
if (!argv.async) evaled = eval(`(() => {${code}})()`)
else if (argv.async) evaled = await eval(`(async () => {${code}})()`)
code = clean(code, client.token)
const type = typeof evaled
if (type !== 'string') {
evaled = util.inspect(evaled, {
depth: argv.depth >= 0 ? argv.depth : 0
})
}
if (!argv.silent) {
evaled = clean(evaled, client.token)
if (argv.console) {
console.log('\x1b[32m%s\x1b[0m', evaled)
} else if (!argv.embed || !(embed instanceof Object)) {
const contents = arraySplitter(evaled.split(''), 1975)
content = contents.map(ctx => `\`\`\`js\n${ctx.join('')}\`\`\``)
} else if (argv.embed && embed instanceof Object) {
let contents = arraySplitter(evaled.split(''), 1010)
code = arraySplitter(code.split(''), 1010)
contents = merge(contents, code)
content = contents.map(ctx => new Discord.MessageEmbed(embed)
.addFields(
{ name: 'Input', value: `\`\`\`js\n${ctx[1].join('')}\`\`\`` },
{ name: 'Output', value: `\`\`\`js\n${ctx[0].join('')}\`\`\`` },
{ name: 'Type', value: `\`\`\`js\n${type}\`\`\`` }
)
)
}
}
} catch (err) {
err = util.inspect(err, {
depth: argv.depth >= 0 ? argv.depth : 0
})
err = clean(err, client.token)
code = clean(code, client.token)
if (argv.console) {
console.error('\x1b[31m%s\x1b[0m', err)
} else if (!argv.embed || !(embed instanceof Object)) {
const contents = arraySplitter(err.split(''), 1975)
content = contents.map(ctx => `Error:\`\`\`js\n${ctx.join('')}\`\`\``)
} else if (argv.embed && embed instanceof Object) {
let contents = arraySplitter(err.split(''), 1010)
code = arraySplitter(code.split(''), 1010)
contents = merge(contents, code)
content = contents.map(ctx => new Discord.MessageEmbed(embed)
.addFields(
{ name: 'Input', value: `\`\`\`js\n${ctx[1].join('')}\`\`\`` },
{ name: 'Error', value: `\`\`\`js\n${ctx[0].join('')}\`\`\`` },
{ name: 'Type', value: '```js\nError```' }
)
)
}
content.error = true
}
if (Array.isArray(content) && content.length) {
const Paginator = new BasePaginator({
pages: content,
timeout: 90000,
filter: (reaction, user) => isOwner(client.owner, user.id, [...options.owner, message.author.id])
})
Paginator.spawn(message.channel).catch(console.error)
}
if (reaction) await reaction.remove().catch(err => {}) || await reaction.users.remove(client.user.id).catch(err => {})
if (content.error) {
reaction = await message.react('‼️').catch(err => {})
} else if (!content.error) {
reaction = await message.react('✅').catch(err => {})
}
clearTimeout(timeout)
}
}
module.exports = EvalCommand