aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bot.ts2
-rw-r--r--src/commands/info/help.ts13
-rw-r--r--src/commands/info/links.ts11
-rw-r--r--src/commands/utilities/wolframAlpha.ts13
-rw-r--r--src/lib/common/Sentry.ts6
-rw-r--r--src/lib/utils/BushClientUtils.ts46
-rw-r--r--src/lib/utils/BushLogger.ts3
-rw-r--r--src/lib/utils/BushUtils.ts6
-rw-r--r--src/listeners/message/directMessage.ts12
9 files changed, 75 insertions, 37 deletions
diff --git a/src/bot.ts b/src/bot.ts
index 7d8327e..d7b5ad9 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -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] });
}
}