pissbot-9000/commands/message/core/help.js
2023-06-30 23:00:37 +02:00

185 lines
No EOL
6.3 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { codeblock, highlight, icon, link, pill, smallPill } = require('../../../labscore/utils/markdown')
const { createEmbed, formatPaginationEmbeds } = require('../../../labscore/utils/embed')
const { DISCORD_INVITES, DEFAULT_BOT_PREFIX } = require('../../../labscore/constants')
const { paginator } = require('../../../labscore/client');
const { editOrReply } = require('../../../labscore/utils/message');
const { Permissions } = require("detritus-client/lib/constants");
function createHelpPage(context, title, contents, descriptions){
return {
"embeds": [
createEmbed("default", context, {
description: `${title}\n\n` +
renderCommandList(contents, descriptions) +
`\n\n${icon("question")} Use ${pill(`${DEFAULT_BOT_PREFIX}help <command>`)} to view more information about a command.`
})
]
}
}
function renderCommandList(commands, descriptions, limit){
let len = Math.max(...(commands.map(el => el.length))) + 3;
let render = []
let i = 0;
for(const c of commands){
let pad = len - c.length;
let desc = descriptions[i]
if(desc.includes('\n')) desc = desc.split('\n')[0]
if(desc.length >= 41) desc = desc.substr(0, 40) + '...'
render.push(` **\` ${c}${' '.repeat(pad)}\`** ${desc}`)
i++
}
if(limit && render.length > limit) render.splice(limit, 999)
return render.join('\n')
}
function createCommandPage(context, prefix, command){
alias = ' '
if(command.aliases.length >= 1){
for(const al of command.aliases) alias += smallPill(al)
alias += "\n"
}
let explicit = '';
if(command.metadata.explicit) explicit = `\n${icon('nsfw')} This command contains explicit content and can only be used in Age-Restricted channels. ${link("https://support.discord.com/hc/en-us/articles/115000084051-Age-Restricted-Channels-and-Content", "Learn More")}\n`
// Render argument pills if present
let args = [];
if(command.argParser.args){
for(const a of command.argParser.args){
let argument = `-${a._name} <${a._type.replace('bool','true/false')}>`
argument = pill(argument)
if(a.help) argument += ` ${a.help}`
argument += `\n ${smallPill(`default: ${a.default}`)} `
if(!a.required) argument += smallPill('optional')
args.push(argument)
}
}
let page = createEmbed("default", context, {
description: `${icon("command")} ${pill(command.name)}\n${alias}${explicit}\n${command.metadata.description}\n\n${args.join('\n\n')}`,
fields: []
})
// TODO: maybe try building a little parser that highlights things via ansi
if(command.metadata.usage) page.fields.push({
name: `${icon("util")} Usage`,
value: codeblock("py", [prefix + command.metadata.usage]),
inline: true
})
if(command.metadata.examples){
let ex = []
for(const e of command.metadata.examples) ex.push(prefix + e)
page.fields.push({
name: `${icon("info")} Examples`,
value: '```' + ex.join('``````') + '```',
inline: false
})
}
return {
embeds: [page]
};
}
// These categories will be displayed to users, add them in the correct order
const categories = {
"core": `${icon("house")} Core Commands`,
"info": `${icon("info")} Information Commands`,
"search": `${icon("search")} Search Commands`,
"utils": `${icon("utils")} Utility Commands`,
"image": `${icon("image")} Image Commands`,
"mod": `${icon("moderation")} Moderation Commands`
}
module.exports = {
name: 'help',
label: 'command',
metadata: {
description: 'List all commands, get more information about individual commands.',
description_short: 'Show full command list',
examples: ['help ping'],
category: 'core',
usage: 'help [<command>]'
},
permissionsClient: [Permissions.EMBED_LINKS, Permissions.SEND_MESSAGES, Permissions.USE_EXTERNAL_EMOJIS],
run: async (context, args) => {
if(args.command){
// Detailed command view
let results = []
for(const c of context.commandClient.commands){
if(c.name.includes(args.command.toLowerCase()) || c.aliases.filter((f)=>{return f.includes(args.command.toLowerCase())}).length >= 1){
if(c.metadata.explicit && !context.channel.nsfw) continue;
results.push(c)
}
}
let pages = []
let prefix = DEFAULT_BOT_PREFIX
try{
if(results.length == 0) return editOrReply(context, {embeds: [createEmbed("warning", context, "No commands found for the provided query.")]})
if(results.length > 1) {
// Command overview
let cmds = results.map((m)=>{return m.name})
let dscs = results.map((m)=>{return m.metadata.description_short})
pages.push({embeds:[
createEmbed("default", context, {
description: `Check pages for detailed command descriptions.\n\n` + renderCommandList(cmds, dscs, 15) + `\n\n${icon("question")} Need help with something else? Contact us via our ${link(DISCORD_INVITES.support, "Support Server")}.`
})
]})
// Generate command detail pages
for(const c of results){
pages.push(createCommandPage(context, prefix, c))
}
pages = formatPaginationEmbeds(pages)
const paging = await paginator.createPaginator({
context,
pages
});
return;
} else {
return editOrReply(context, createCommandPage(context, prefix, results[0]))
}
}catch(e){
console.log(e)
}
} else {
// Full command list
let commands = {}
let descriptions = {}
for(const c of context.commandClient.commands){
if(!categories[c.metadata.category]) continue;
if(c.metadata.explicit && !context.channel.nsfw) continue;
if(!commands[c.metadata.category]) commands[c.metadata.category] = []
if(!descriptions[c.metadata.category]) descriptions[c.metadata.category] = []
commands[c.metadata.category].push(`${c.name}`);
descriptions[c.metadata.category].push(`${c.metadata.description_short}`);
}
let pages = []
for(const cat of Object.keys(categories)){
pages.push(createHelpPage(context, categories[cat], commands[cat], descriptions[cat]))
}
pages = formatPaginationEmbeds(pages)
const paging = await paginator.createPaginator({
context,
pages
});
}
},
};