a lot of thingssss

This commit is contained in:
derpystuff 2022-05-23 23:14:57 +02:00
parent eb0ba140f3
commit 726861294b
14 changed files with 420 additions and 24 deletions

View file

@ -1,7 +1,10 @@
const { codeblock, highlight, icon } = require('../../../labscore/utils/markdown')
const { codeblock, highlight, icon, link } = require('../../../labscore/utils/markdown')
const { createEmbed, formatPaginationEmbeds } = require('../../../labscore/utils/embed')
const { DISCORD_INVITE } = require('../../../labscore/constants')
const { paginator } = require('../../../labscore/client');
const { editOrReply } = require('../../../labscore/utils/message');
function createHelpPage(context, title, contents){
return {
@ -15,13 +18,44 @@ function createHelpPage(context, title, contents){
}
}
function createCommandPage(context, prefix, command){
let page = createEmbed("default", context, {
description: `**${prefix}${command.name}**\n${command.metadata.description}`,
fields: []
})
if(command.aliases.length >= 1) page.fields.push({
name: `${icon("activity")} Aliases`,
value: command.aliases.join(', '),
inline: true
})
if(command.metadata.usage) page.fields.push({
name: `${icon("util")} Usage`,
value: codeblock("ansi", [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: codeblock("ansi", ex),
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`,
"search": `${icon("search")} Search Commands`,
"dev": `${icon("analytics")} Development`
"info": `${icon("info")} Information Commands`,
"mod": `${icon("moderation")} Moderation Commands`,
"search": `${icon("search")} Search Commands`
}
module.exports = {
name: 'help',
label: 'command',
@ -33,12 +67,50 @@ module.exports = {
},
run: async (context, args) => {
context.triggerTyping();
if(args.label){
if(args.command){
// Detailed command view
let results = []
for(const c of context.commandClient.commands){
if(c.name.includes(args.command) || c.aliases.filter((f)=>{return f.includes(args.command)}).length >= 1) results.push(c)
}
let pages = []
let prefix = context.commandClient.prefixes.custom.first()
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
pages.push({embeds:[
createEmbed("default", context, {
description: `Check pages for detailed command descriptions.\n` + codeblock("ansi", [(prefix + results.map((m)=>{return m.name}).splice(0, 10).join('\n' + prefix))]) + `\n${icon("question")} Need help with something else? Contact us via our ${link(DISCORD_INVITE, "Support Server")}.`
})
]})
// Generate command detail pages
for(const c of results){
pages.push(createCommandPage(context, prefix, c))
}
pages = formatPaginationEmbeds(pages)
const message = context.message
const paging = await paginator.createPaginator({
message,
pages
});
return;
} else {
return editOrReply(context, createCommandPage(context, prefix, results[0]))
}
}catch(e){
console.log(e)
}
} else {
// Full command list
let commands = {
}
let commands = {}
let prefix = context.commandClient.prefixes.custom.first()
for(const c of context.commandClient.commands){
if(!categories[c.metadata.category]) continue;

View file

@ -0,0 +1,53 @@
const { format } = require('../../../labscore/utils/ansi')
const { codeblock, icon, highlight } = require('../../../labscore/utils/markdown')
const { createEmbed } = require('../../../labscore/utils/embed')
const { editOrReply } = require('../../../labscore/utils/message')
module.exports = {
name: 'undo',
default: 1,
label: 'amount',
metadata: {
description: 'undo your last bot command(s)',
examples: ['undo 5'],
category: 'core',
usage: 'undo [<amount (1-5)>]'
},
run: async (context, args) => {
try{
context.triggerTyping();
if(typeof(args.amount) == "string") args.amount = parseInt(args.amount)
if(!args.amount) args.amount = 1
if(args.amount >= 6 || args.amount <= 0) return await editOrReply(context, {embeds:[createEmbed("warning", context, "Invalid Argument (amount)")]})
let cmds = [];
let found = 0;
for(const c of context.commandClient.replies.toArray().reverse()){
if(found > args.amount) break;
if (c.context.channelId !== context.channelId || c.context.userId !== context.userId) continue;
if (c.context.message.canDelete) cmds.push(c.context.message.id)
if (c.reply.canDelete && !c.reply.deleted) {
cmds.push(c.reply.id);
found++;
}
}
if (cmds.length == 1 || !context.canManage) {
for (let id of cmds) {
await context.channel.deleteMessage(id);
}
} else {
await context.channel.bulkDelete(cmds);
}
if(context.canManage) await context.message.delete()
let resp = await editOrReply(context, {
"content": `${icon("success_simple")} Deleted ${highlight(found)} command replies.`
})
console.log(resp)
setTimeout(async () => {
await context.channel.deleteMessage(resp.id)
}, 5000)
}catch(e){
console.log(e)
}
},
};

View file

@ -0,0 +1,28 @@
const { getRecentImage } = require("../../../../labscore/utils/attachment");
const { createEmbed } = require("../../../../labscore/utils/embed");
const { editOrReply } = require("../../../../labscore/utils/message");
module.exports = {
name: 'attachment',
metadata: {
description: 'test',
examples: ['attachment'],
category: 'dev',
usage: 'attachment'
},
run: async (context) => {
try{
let image = await getRecentImage(context, 50)
console.log(image)
if(!image) return editOrReply(context, { embeds: [createEmbed("warning", context, "No images found.")] })
return editOrReply(context, { embeds: [createEmbed("default", context, {
image: {
url: image
}
})] })
}catch(e){
console.log(e)
}
},
};

View file

@ -1,14 +1,26 @@
const { createEmbed } = require("../../../../labscore/utils/embed");
const { editOrReply } = require("../../../../labscore/utils/message");
const { getUser } = require("../../../../labscore/utils/users");
module.exports = {
name: 'test',
label: 'input',
metadata: {
description: 'test',
examples: ['test'],
category: 'dev',
usage: 'test'
},
run: async (context) => {
return context.editOrReply('test successful.')
run: async (context, args) => {
try{
let u = await getUser(context, args.input)
if(!u) return editOrReply(context, { embeds: [createEmbed("warning", context, "No users found.")] })
return editOrReply(context, { embeds: [createEmbed("default", context, {
description: u.mention
})] })
}catch(e){
console.log(e)
}
},
};

View file

@ -0,0 +1,36 @@
const { createEmbed } = require('../../../labscore/utils/embed')
const { format } = require('../../../labscore/utils/ansi')
const { editOrReply } = require('../../../labscore/utils/message')
const { STATICS } = require('../../../labscore/utils/statics')
const { inferkit } = require('../../../labscore/api')
const { codeblock } = require('../../../labscore/utils/markdown')
module.exports = {
name: 'inferkit',
aliases: ['complete'],
label: 'text',
metadata: {
description: 'make ai continue your text',
examples: ['complete The Fitness Gram Pacer'],
category: 'fun',
usage: 'inferkit <prompt>'
},
run: async (context, args) => {
context.triggerTyping();
if(!args.text) return editOrReply(context, {embeds:[createEmbed("warning", context, `Missing Parameter (text).`)]})
try{
let res = await inferkit(context, args.text)
return editOrReply(context, {embeds:[createEmbed("default", context, {
description: codeblock("ansi", [format(res.response.body.input, "cyan") + res.response.body.output]),
footer: {
iconUrl: STATICS.inferkit,
text: `InferKit • ${context.application.name} • Took ${res.timings}s`
}
})]})
}catch(e){
console.log(e)
return editOrReply(context, {embeds:[createEmbed("error", context, `Unable to generate text.`)]})
}
}
};

View file

@ -0,0 +1,25 @@
const { createEmbed } = require("../../../labscore/utils/embed");
const { editOrReply } = require("../../../labscore/utils/message");
const { getUser } = require("../../../labscore/utils/users");
module.exports = {
name: 'avatar',
label: 'user',
aliases: ['a'],
metadata: {
description: 'avatar',
examples: ['avatar labsCore'],
category: 'info',
usage: 'avatar [<id|user>]'
},
run: async (context, args) => {
let u;
if(!args.user) { u = context.user } else { u = await getUser(context, args.user) }
if(!u) return editOrReply(context, { embeds: [createEmbed("warning", context, "No users found.")] })
return editOrReply(context, { embeds: [createEmbed("default", context, {
image: {
url: u.avatarUrl + '?size=4096'
}
})] })
},
};

View file

@ -0,0 +1,76 @@
const { Constants } = require("detritus-client");
const { icon } = require("../../../labscore/utils/markdown");
const Permissions = Constants.Permissions;
// TODO: copy pasted from v1, rework this eventually
module.exports = {
label: "filter",
name: "purge",
metadata: {
description: 'Removes recent messages in chat. Allows you to optionally filter by message content to remove spam.\n\n`-amount` allows you to specify how many messages should be searched (default: 20)\n`-case` specifies if the provided query should be case sensitive or not (default: true)',
examples: ['purge Spam -amount 25'],
category: 'mod',
usage: 'purge [<content>] [-amount <1-50>] [-case <true|false>]'
},
args: [
{default: 20, name: 'amount', type: 'integer'},
{default: true, name: 'case', type: 'bool'},
],
permissionsClient: [Permissions.MANAGE_MESSAGES],
permissions: [Permissions.MANAGE_MESSAGES],
onPermissionsFailClient: (context) => context.editOrReply(`${icon("failiure_simple")} ${context.message.author.mention}, the bot needs the \`Manage Messages\` permission to run this command.`),
onPermissionsFail: (context) => context.editOrReply(`${icon("failiure_simple")} ${context.message.author.mention}, you are lacking the permission \`Manage Messages\`.`),
ratelimit: {
type: 'guild',
limit: 1,
duration: 5000
},
permissionsClient: [Permissions.MANAGE_MESSAGES],
run: async (context, args) => {
await context.triggerTyping();
if(args.amount >= 51 || args.amount <= 0){
return context.editOrReply(`${icon("failiure_simple")} ${context.message.author.mention}, Invalid amount (1-50).`);
}
const messages = await context.message.channel.fetchMessages({limit: args.amount});
let deleteIds = []
messages.forEach(message => {
if(args.filter.length >= 1){
if(message.canDelete){
if(args.case == false){
if(message.content.toLowerCase().includes(args.filter.toLowerCase())){
deleteIds.push(message.id)
}
} else {
if(message.content.includes(args.filter)){
deleteIds.push(message.id)
}
}
}
} else {
if(message.canDelete){
deleteIds.push(message.id)
}
}
})
if(deleteIds.length == 0){
return context.editOrReply(`${icon("failiure_simple")} No messages found.`);
}
if(deleteIds.length == 1){
try{
await context.client.rest.deleteMessage(context.channel.id, deleteIds[0])
return context.editOrReply(`${icon("success_simple")} Removed \`1\` message.`);
}catch(e){
await context.editOrReply(`${icon("failiure_simple")} Something went wrong while attempting to remove \`1\` message.`);
}
} else {
try{
await context.client.rest.bulkDeleteMessages(context.channel.id, deleteIds)
return context.editOrReply(`${icon("success_simple")} Removed \`${deleteIds.length}\` messages.`);
}catch(e){
await context.editOrReply(`${icon("failiure_simple")} Something went wrong while attempting to remove \`${deleteIds.length}\` messages.`);
}
}
}
};

View file

@ -16,7 +16,9 @@ const Api = Object.freeze({
SEARCH_BING_IMAGES: '/search/bing-images',
SEARCH_WOLFRAM_ALPHA: '/search/wolfram-alpha',
PHOTOFUNIA_YACHT: '/photofunia/yacht'
PHOTOFUNIA_YACHT: '/photofunia/yacht',
INFERKIT: '/inferkit',
})
const Static = Object.freeze({

View file

@ -82,6 +82,12 @@ module.exports.yacht = async function(context, text){
})
}
module.exports.inferkit = async function(context, input){
return await request(Api.INFERKIT, "GET", {}, {
input: input
})
}
module.exports.emojiTwitter = async function(codepoint){
return Static.HOST + Static.TWITTER(codepoint)
}

View file

@ -41,11 +41,11 @@ const paginator = new Paginator(cluster, {
await commandClient.addMultipleIn('../commands/message/');
await commandClient.run()
commandClient.on('commandDelete', async ({reply}) => {
if (reply){
reply.delete();
}
});
//commandClient.on('commandDelete', async ({reply}) => {
// if (reply){
// reply.delete();
// }
//});
})();

View file

@ -1,4 +1,4 @@
const COLORS = Object.freeze({
module.exports.COLORS = Object.freeze({
"error": 15548997,
"success": 6411359,
"warning": 16426522,
@ -6,7 +6,7 @@ const COLORS = Object.freeze({
"brand": 6085465
})
const ICONS = Object.freeze({
module.exports.ICONS = Object.freeze({
"error": "<:ico_error:925832574239121429>",
"warning": "<:ico_warning:925832574931189830>",
"success": "<:ico_check:925813919929491516>",
@ -52,7 +52,7 @@ const ICONS = Object.freeze({
"question": "<:ico_question:949420315677691934>"
})
const WEB_ASSETS = Object.freeze({
module.exports.WEB_ASSETS = Object.freeze({
"brands": {
"genius": "357a0d4aaf1cedfa41dfb38bf3acb961",
"labscore": "042e4a437e14580ee2fda8be217991d6"
@ -60,8 +60,4 @@ const WEB_ASSETS = Object.freeze({
"weather": "aab92e69374e4c7b8c6741fe02e574b9"
})
module.exports = {
COLORS,
ICONS,
WEB_ASSETS
}
module.exports.DISCORD_INVITE = `https://discord.gg/8c4p6xcjru`

View file

@ -0,0 +1,57 @@
const attachmentTypes = Object.freeze({
image: ["image/png", "image/jpeg", "image/gif"]
})
async function getRecentMedia(context, limit){
if (!context.message.channel) {
return undefined;
} else if (context.message.attachments.length > 0) {
return context.message.attachments.first();
}
const messages = await context.message.channel.fetchMessages({
limit
});
if (!messages) {
return undefined;
}
let attachments = [];
for(const m of messages){
let message = m[1]
if ( // First the attachment on the message
message.attachments.first()
) { attachments.push(message.attachments.first())
} else if ( // Then the embed image
message.embeds.length > 0 &&
message.embeds.toArray()[0].image
) { attachments.push(message.embeds.toArray()[0].image)
} else if (
message.embeds.length > 0 &&
message.embeds.toArray()[0].thumbnail
) { attachments.push(message.embeds.toArray()[0].thumbnail) }
}
return attachments;
}
// simple helpers
async function getRecentImage(context, limit){
let attachments = await getRecentMedia(context, limit)
let at;
let validImages = attachmentTypes.image
for(const a of attachments){
if(a.contentType && validImages.includes(a.contentType) && at === undefined){ // discord attachment
at = a.url
} else if (!a.content_type && at === undefined){ // other form of media
at = a.url
}
}
return at;
}
module.exports = {
getRecentImage
}

View file

@ -21,6 +21,10 @@ const Statics = Object.freeze({
wolframalpha: {
file: "brands/wolframalpha.png",
revision: 0
},
inferkit: {
file: "brands/inferkit.png",
revision: 0
}
}
})
@ -34,5 +38,6 @@ module.exports.STATICS = Object.freeze({
genius: staticAsset(Statics.brands.genius),
bing: staticAsset(Statics.brands.bing),
google: staticAsset(Statics.brands.google),
wolframalpha: staticAsset(Statics.brands.wolframalpha)
wolframalpha: staticAsset(Statics.brands.wolframalpha),
inferkit: staticAsset(Statics.brands.inferkit)
})

28
labscore/utils/users.js Normal file
View file

@ -0,0 +1,28 @@
async function getUser(context, query){
let user;
if(/[0-9]{18}/.test(query)){ // User ID supplied, use that
let uid = query.match(/[0-9]{18}/)
try{
user = await context.client.rest.fetchUser(uid)
} catch(e){
user = undefined
}
} else {
user = await getMember(context, query)
if(user) user = user.user
}
return user;
}
async function getMember(context, query){
if(!context.guild) return;
let members = await context.guild.fetchMembersSearch({ query })
console.log(members)
if(members) return members.first()
return;
}
module.exports = {
getUser,
getMember
}