diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bot.ts | 2 | ||||
-rw-r--r-- | src/commands/info/help.ts | 13 | ||||
-rw-r--r-- | src/commands/info/links.ts | 11 | ||||
-rw-r--r-- | src/commands/utilities/wolframAlpha.ts | 13 | ||||
-rw-r--r-- | src/lib/common/Sentry.ts | 6 | ||||
-rw-r--r-- | src/lib/utils/BushClientUtils.ts | 46 | ||||
-rw-r--r-- | src/lib/utils/BushLogger.ts | 3 | ||||
-rw-r--r-- | src/lib/utils/BushUtils.ts | 6 | ||||
-rw-r--r-- | src/listeners/message/directMessage.ts | 12 |
9 files changed, 75 insertions, 37 deletions
@@ -10,7 +10,7 @@ const { Sentry } = await import('./lib/common/Sentry.js'); const { BushClient } = await import('./lib/index.js'); const isDry = process.argv.includes('dry'); -if (!isDry) new Sentry(dirname(fileURLToPath(import.meta.url)) || process.cwd()); +if (!isDry && config.credentials.sentryDsn !== null) new Sentry(dirname(fileURLToPath(import.meta.url)) || process.cwd(), config); BushClient.extendStructures(); const client = new BushClient(config); if (!isDry) await client.dbPreInit(); diff --git a/src/commands/info/help.ts b/src/commands/info/help.ts index ec079e7..d8d91d5 100644 --- a/src/commands/info/help.ts +++ b/src/commands/info/help.ts @@ -211,14 +211,17 @@ export default class HelpCommand extends BushCommand { private addLinks(message: CommandMessage | SlashMessage) { const row = new ActionRowBuilder<ButtonBuilder>(); + const config = this.client.config; - if (!this.client.config.isDevelopment && !this.client.guilds.cache.some((guild) => guild.ownerId === message.author.id)) { + if (!config.isDevelopment && !this.client.guilds.cache.some((guild) => guild.ownerId === message.author.id)) { row.addComponents(new ButtonBuilder({ style: ButtonStyle.Link, label: 'Invite Me', url: invite(this.client) })); } - if (!this.client.guilds.cache.get(this.client.config.supportGuild.id)?.members.cache.has(message.author.id)) { - row.addComponents( - new ButtonBuilder({ style: ButtonStyle.Link, label: 'Support Server', url: this.client.config.supportGuild.invite }) - ); + if ( + config.supportGuild.id && + config.supportGuild.invite && + !this.client.guilds.cache.get(config.supportGuild.id)?.members.cache.has(message.author.id) + ) { + row.addComponents(new ButtonBuilder({ style: ButtonStyle.Link, label: 'Support Server', url: config.supportGuild.invite })); } if (packageDotJSON?.repository) row.addComponents(new ButtonBuilder({ style: ButtonStyle.Link, label: 'GitHub', url: packageDotJSON.repository })); diff --git a/src/commands/info/links.ts b/src/commands/info/links.ts index 3671c6c..3c7add2 100644 --- a/src/commands/info/links.ts +++ b/src/commands/info/links.ts @@ -24,10 +24,13 @@ export default class LinksCommand extends BushCommand { if (!this.client.config.isDevelopment || message.author.isOwner()) { buttonRow.addComponents(new ButtonBuilder({ style: ButtonStyle.Link, label: 'Invite Me', url: invite(this.client) })); } - buttonRow.addComponents( - new ButtonBuilder({ style: ButtonStyle.Link, label: 'Support Server', url: this.client.config.supportGuild.invite }), - new ButtonBuilder({ style: ButtonStyle.Link, label: 'GitHub', url: packageDotJSON.repository }) - ); + const supportInvite = this.client.config.supportGuild.invite; + + if (supportInvite) { + buttonRow.addComponents(new ButtonBuilder({ style: ButtonStyle.Link, label: 'Support Server', url: supportInvite })); + } + + buttonRow.addComponents(new ButtonBuilder({ style: ButtonStyle.Link, label: 'GitHub', url: packageDotJSON.repository })); return await message.util.reply({ content: 'Here are some useful links:', components: [buttonRow] }); } } diff --git a/src/commands/utilities/wolframAlpha.ts b/src/commands/utilities/wolframAlpha.ts index 3cd0653..bac9f58 100644 --- a/src/commands/utilities/wolframAlpha.ts +++ b/src/commands/utilities/wolframAlpha.ts @@ -54,8 +54,17 @@ export default class WolframAlphaCommand extends BushCommand { ) { if (message.util.isSlashMessage(message)) await message.interaction.deferReply(); - args.image && void message.util.reply({ content: `${emojis.loading} Loading...`, embeds: [] }); - const waApi = WolframAlphaAPI(this.client.config.credentials.wolframAlphaAppId); + const appId = this.client.config.credentials.wolframAlphaAppId; + + if (appId === null || appId === '' || appId === '[APP_ID]') + return message.util.reply( + message.author.isSuperUser() + ? `${emojis.error} The 'wolframAlphaAppId' credential isn't set so this command cannot be used.` + : `${emojis.error} Sorry, this command is unavailable.` + ); + + if (args.image) void message.util.reply({ content: `${emojis.loading} Loading...`, embeds: [] }); + const waApi = WolframAlphaAPI(appId); const decodedEmbed = new EmbedBuilder().addFields({ name: '📥 Input', diff --git a/src/lib/common/Sentry.ts b/src/lib/common/Sentry.ts index 34bc06f..2792203 100644 --- a/src/lib/common/Sentry.ts +++ b/src/lib/common/Sentry.ts @@ -1,10 +1,12 @@ import { RewriteFrames } from '@sentry/integrations'; import * as SentryNode from '@sentry/node'; import { Integrations } from '@sentry/node'; -import config from '../../../config/options.js'; +import type { Config } from '../../../config/Config.js'; export class Sentry { - public constructor(rootdir: string) { + public constructor(rootdir: string, config: Config) { + if (config.credentials.sentryDsn === null) throw TypeError('sentryDsn cannot be null'); + SentryNode.init({ dsn: config.credentials.sentryDsn, environment: config.environment, diff --git a/src/lib/utils/BushClientUtils.ts b/src/lib/utils/BushClientUtils.ts index 44a08ef..af49803 100644 --- a/src/lib/utils/BushClientUtils.ts +++ b/src/lib/utils/BushClientUtils.ts @@ -1,11 +1,13 @@ import assert from 'assert'; import { cleanCodeBlockContent, + DMChannel, escapeCodeBlock, GuildMember, Message, + PartialDMChannel, Routes, - TextChannel, + TextBasedChannel, ThreadMember, User, type APIMessage, @@ -15,6 +17,7 @@ import { } from 'discord.js'; import got from 'got'; import _ from 'lodash'; +import { ConfigChannelKey } from '../../../config/Config.js'; import CommandErrorListener from '../../listeners/commands/commandError.js'; import { BushInspectOptions } from '../common/typings/BushInspectOptions.js'; import { CodeBlockLang } from '../common/typings/CodeBlockLang.js'; @@ -146,15 +149,16 @@ export class BushClientUtils { * @returns The readable version of the key or the original key if there isn't a mapping. */ #mapCredential(key: string): string { - const mapping = { - token: 'Main Token', - devToken: 'Dev Token', - betaToken: 'Beta Token', - hypixelApiKey: 'Hypixel Api Key', - wolframAlphaAppId: 'Wolfram|Alpha App ID', - dbPassword: 'Database Password' - }; - return mapping[key as keyof typeof mapping] || key; + return ( + { + token: 'Main Token', + devToken: 'Dev Token', + betaToken: 'Beta Token', + hypixelApiKey: 'Hypixel Api Key', + wolframAlphaAppId: 'Wolfram|Alpha App ID', + dbPassword: 'Database Password' + }[key] ?? key + ); } /** @@ -167,6 +171,7 @@ export class BushClientUtils { const credential = { ...this.client.config.credentials, dbPassword: this.client.config.db.password }[ credentialName as keyof typeof this.client.config.credentials ]; + if (credential === null || credential === '') continue; const replacement = this.#mapCredential(credentialName); const escapeRegex = /[.*+?^${}()|[\]\\]/g; text = text.replace(new RegExp(credential.toString().replace(escapeRegex, '\\$&'), 'g'), `[${replacement} Omitted]`); @@ -456,11 +461,24 @@ export class BushClientUtils { } /** - * Gets a a configured channel as a TextChannel. - * @channel The channel to retrieve. + * Resolves a channel from the config and ensures it is a non-dm-based-text-channel. + * @param channel The channel to retrieve. */ - public async getConfigChannel(channel: keyof Client['config']['channels']): Promise<TextChannel> { - return (await this.client.channels.fetch(this.client.config.channels[channel])) as unknown as TextChannel; + public async getConfigChannel( + channel: ConfigChannelKey + ): Promise<Exclude<TextBasedChannel, DMChannel | PartialDMChannel> | null> { + const channels = this.client.config.channels; + if (!(channel in channels)) + throw new TypeError(`Invalid channel provided (${channel}), must be one of ${Object.keys(channels).join(' ')}`); + + const channelId = channels[channel]; + if (channelId === '') return null; + + const res = await this.client.channels.fetch(channelId); + + if (!res?.isTextBased() || res.isDMBased()) return null; + + return res; } } diff --git a/src/lib/utils/BushLogger.ts b/src/lib/utils/BushLogger.ts index 3cfd860..5c98760 100644 --- a/src/lib/utils/BushLogger.ts +++ b/src/lib/utils/BushLogger.ts @@ -155,6 +155,7 @@ export class BushLogger { */ public async channelLog(message: SendMessageType): Promise<Message | null> { const channel = await this.client.utils.getConfigChannel('log'); + if (channel === null) return null; return await channel.send(message).catch(() => null); } @@ -322,5 +323,3 @@ export class BushLogger { await this.channelLog({ embeds: [embed] }).catch(() => {}); } } - -/** @typedef {PartialTextBasedChannelFields} vscodeDontDeleteMyImportTy */ diff --git a/src/lib/utils/BushUtils.ts b/src/lib/utils/BushUtils.ts index 059d001..e3539a1 100644 --- a/src/lib/utils/BushUtils.ts +++ b/src/lib/utils/BushUtils.ts @@ -11,7 +11,7 @@ import { } from '#lib'; import { humanizeDuration as humanizeDurationMod } from '@notenoughupdates/humanize-duration'; import assert from 'assert'; -import { exec } from 'child_process'; +import cp from 'child_process'; import deepLock from 'deep-lock'; import { Util as AkairoUtil } from 'discord-akairo'; import { @@ -43,13 +43,15 @@ export function capitalize(text: string): string { return text.charAt(0).toUpperCase() + text.slice(1); } +export const exec = promisify(cp.exec); + /** * Runs a shell command and gives the output * @param command The shell command to run * @returns The stdout and stderr of the shell command */ export async function shell(command: string): Promise<{ stdout: string; stderr: string }> { - return await promisify(exec)(command); + return await exec(command); } /** diff --git a/src/listeners/message/directMessage.ts b/src/listeners/message/directMessage.ts index 91733a5..7278e63 100644 --- a/src/listeners/message/directMessage.ts +++ b/src/listeners/message/directMessage.ts @@ -14,7 +14,11 @@ export default class DirectMessageListener extends BushListener { if (message.channel.type === ChannelType.DM) { if (!(message.author.id == this.client.user!.id) && message.author.bot) return; if (this.client.cache.global.blacklistedUsers.includes(message.author.id)) return; - const dmLogEmbed = new EmbedBuilder().setTimestamp().setFooter({ text: `User ID • ${message.channel.recipientId}` }); + + const dmLogEmbed = new EmbedBuilder() + .setTimestamp() + .setFooter({ text: `User ID • ${message.channel.recipientId}` }) + .setDescription(`**DM:**\n${message.content}`); if (message.author.id != this.client.user!.id) { dmLogEmbed @@ -22,7 +26,6 @@ export default class DirectMessageListener extends BushListener { name: `From: ${message.author.username}`, iconURL: `${message.author.displayAvatarURL()}` }) - .setDescription(`**DM:**\n${message}`) .setColor(colors.blue); } else { dmLogEmbed @@ -30,9 +33,7 @@ export default class DirectMessageListener extends BushListener { name: `To: ${message.channel.recipient?.username}`, iconURL: `${message.channel.recipient?.displayAvatarURL()}` }) - .setDescription(`**DM:**\n${message}`) - .setColor(colors.red) - .setTimestamp(); + .setColor(colors.red); } if (message.attachments.filter((a) => typeof a.size == 'number').size == 1) { dmLogEmbed.setImage(message.attachments.filter((a) => typeof a.size == 'number').first()!.proxyURL); @@ -40,6 +41,7 @@ export default class DirectMessageListener extends BushListener { dmLogEmbed.addFields({ name: 'Attachments', value: message.attachments.map((a) => a.proxyURL).join('\n') }); } const dmChannel = await this.client.utils.getConfigChannel('dm'); + if (dmChannel === null) return; await dmChannel.send({ embeds: [dmLogEmbed] }); } } |