aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bot.ts3
-rw-r--r--src/config/example-options.ts3
-rw-r--r--src/lib/common/Sentry.ts12
-rw-r--r--src/lib/extensions/discord-akairo/BushClient.ts12
-rw-r--r--src/lib/extensions/global.d.ts1
-rw-r--r--src/lib/utils/BushConstants.ts142
-rw-r--r--src/lib/utils/Config.ts1
-rw-r--r--src/listeners/commands/commandError.ts20
-rw-r--r--src/listeners/commands/commandStarted.ts26
-rw-r--r--src/listeners/other/promiseRejection.ts5
-rw-r--r--src/listeners/other/uncaughtException.ts5
-rw-r--r--src/listeners/other/warning.ts5
12 files changed, 162 insertions, 73 deletions
diff --git a/src/bot.ts b/src/bot.ts
index daa6382..6be90e7 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -2,6 +2,9 @@ import 'module-alias/register';
import 'source-map-support/register';
import config from './config/options';
import { BushClient } from './lib';
+import { Sentry } from './lib/common/Sentry';
+global.__rootdir__ = __dirname || process.cwd();
+new Sentry();
BushClient.init();
void new BushClient(config).start();
diff --git a/src/config/example-options.ts b/src/config/example-options.ts
index f6b9dc1..aafda05 100644
--- a/src/config/example-options.ts
+++ b/src/config/example-options.ts
@@ -8,7 +8,8 @@ export default new Config({
hypixelApiKey: '[API_KEY]',
wolframAlphaAppId: '[APP_ID]',
imgurClientId: '[CLIENT_ID]',
- imgurClientSecret: '[CLIENT_SECRET]'
+ imgurClientSecret: '[CLIENT_SECRET]',
+ sentryDsn: 'SENTRY_DSN'
},
environment: 'development',
owners: [
diff --git a/src/lib/common/Sentry.ts b/src/lib/common/Sentry.ts
new file mode 100644
index 0000000..2040536
--- /dev/null
+++ b/src/lib/common/Sentry.ts
@@ -0,0 +1,12 @@
+import * as SentryNode from '@sentry/node';
+import config from './../../config/options';
+
+export class Sentry {
+ public constructor() {
+ SentryNode.init({
+ dsn: config.credentials.sentryDsn,
+ environment: config.environment,
+ tracesSampleRate: 1.0
+ });
+ }
+}
diff --git a/src/lib/extensions/discord-akairo/BushClient.ts b/src/lib/extensions/discord-akairo/BushClient.ts
index 32f43be..4954d8e 100644
--- a/src/lib/extensions/discord-akairo/BushClient.ts
+++ b/src/lib/extensions/discord-akairo/BushClient.ts
@@ -1,4 +1,5 @@
-import { AkairoClient, ContextMenuCommandHandler } from 'discord-akairo';
+import * as Sentry from '@sentry/node';
+import { AkairoClient, ContextMenuCommandHandler, version as akairoVersion } from 'discord-akairo';
import {
Awaitable,
Collection,
@@ -13,6 +14,7 @@ import {
ReplyMessageOptions,
Snowflake,
Structures,
+ version as discordJsVersion,
WebhookEditMessageOptions
} from 'discord.js';
//@ts-ignore: no typings
@@ -152,6 +154,7 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
public logger = BushLogger;
public constants = BushConstants;
public cache = BushCache;
+ public sentry!: typeof Sentry;
public override on<K extends keyof BushClientEvents>(
event: K,
@@ -322,6 +325,13 @@ export class BushClient<Ready extends boolean = boolean> extends AkairoClient<Re
durationSeconds: durationSecondsTypeCaster,
globalUser: globalUserTypeCaster
});
+
+ this.sentry = Sentry;
+ this.sentry.setTag('process', process.pid.toString());
+ this.sentry.setTag('discord.js', discordJsVersion);
+ this.sentry.setTag('discord-akairo', akairoVersion);
+ void this.logger.success('startup', `Successfully connected to <<Sentry>>.`, false);
+
// loads all the handlers
const loaders = {
commands: this.commandHandler,
diff --git a/src/lib/extensions/global.d.ts b/src/lib/extensions/global.d.ts
index e10db0a..5274fd2 100644
--- a/src/lib/extensions/global.d.ts
+++ b/src/lib/extensions/global.d.ts
@@ -4,4 +4,5 @@ import { BushClientUtil } from './discord-akairo/BushClientUtil';
declare global {
var client: BushClient;
var util: BushClientUtil;
+ var __rootdir__: string;
}
diff --git a/src/lib/utils/BushConstants.ts b/src/lib/utils/BushConstants.ts
index 64208a1..a4b3108 100644
--- a/src/lib/utils/BushConstants.ts
+++ b/src/lib/utils/BushConstants.ts
@@ -1,76 +1,5 @@
import { Constants, ConstantsColors } from 'discord.js';
-interface bushColors {
- default: '#1FD8F1';
- error: '#EF4947';
- warn: '#FEBA12';
- success: '#3BB681';
- info: '#3B78FF';
- red: '#ff0000';
- blue: '#0055ff';
- aqua: '#00bbff';
- purple: '#8400ff';
- blurple: '#5440cd';
- newBlurple: '#5865f2';
- pink: '#ff00e6';
- green: '#00ff1e';
- darkGreen: '#008f11';
- gold: '#b59400';
- yellow: '#ffff00';
- white: '#ffffff';
- gray: '#a6a6a6';
- lightGray: '#cfcfcf';
- darkGray: '#7a7a7a';
- black: '#000000';
- orange: '#E86100';
- discord: ConstantsColors;
-}
-
-export type PronounCode =
- | 'unspecified'
- | 'hh'
- | 'hi'
- | 'hs'
- | 'ht'
- | 'ih'
- | 'ii'
- | 'is'
- | 'it'
- | 'shh'
- | 'sh'
- | 'si'
- | 'st'
- | 'th'
- | 'ti'
- | 'ts'
- | 'tt'
- | 'any'
- | 'other'
- | 'ask'
- | 'avoid';
-export type Pronoun =
- | 'Unspecified'
- | 'He/Him'
- | 'He/It'
- | 'He/She'
- | 'He/They'
- | 'It/Him'
- | 'It/Its'
- | 'It/She'
- | 'It/They'
- | 'She/He'
- | 'She/Her'
- | 'She/It'
- | 'She/They'
- | 'They/He'
- | 'They/It'
- | 'They/She'
- | 'They/Them'
- | 'Any pronouns'
- | 'Other pronouns'
- | 'Ask me my pronouns'
- | 'Avoid pronouns, use my name';
-
const rawCapeUrl = 'https://raw.githubusercontent.com/NotEnoughUpdates/capes/master/';
export class BushConstants {
public static emojis = {
@@ -564,3 +493,74 @@ export class BushConstants {
{ name: 'No Support', id: '790247359824396319' }
];
}
+
+interface bushColors {
+ default: '#1FD8F1';
+ error: '#EF4947';
+ warn: '#FEBA12';
+ success: '#3BB681';
+ info: '#3B78FF';
+ red: '#ff0000';
+ blue: '#0055ff';
+ aqua: '#00bbff';
+ purple: '#8400ff';
+ blurple: '#5440cd';
+ newBlurple: '#5865f2';
+ pink: '#ff00e6';
+ green: '#00ff1e';
+ darkGreen: '#008f11';
+ gold: '#b59400';
+ yellow: '#ffff00';
+ white: '#ffffff';
+ gray: '#a6a6a6';
+ lightGray: '#cfcfcf';
+ darkGray: '#7a7a7a';
+ black: '#000000';
+ orange: '#E86100';
+ discord: ConstantsColors;
+}
+
+export type PronounCode =
+ | 'unspecified'
+ | 'hh'
+ | 'hi'
+ | 'hs'
+ | 'ht'
+ | 'ih'
+ | 'ii'
+ | 'is'
+ | 'it'
+ | 'shh'
+ | 'sh'
+ | 'si'
+ | 'st'
+ | 'th'
+ | 'ti'
+ | 'ts'
+ | 'tt'
+ | 'any'
+ | 'other'
+ | 'ask'
+ | 'avoid';
+export type Pronoun =
+ | 'Unspecified'
+ | 'He/Him'
+ | 'He/It'
+ | 'He/She'
+ | 'He/They'
+ | 'It/Him'
+ | 'It/Its'
+ | 'It/She'
+ | 'It/They'
+ | 'She/He'
+ | 'She/Her'
+ | 'She/It'
+ | 'She/They'
+ | 'They/He'
+ | 'They/It'
+ | 'They/She'
+ | 'They/Them'
+ | 'Any pronouns'
+ | 'Other pronouns'
+ | 'Ask me my pronouns'
+ | 'Avoid pronouns, use my name';
diff --git a/src/lib/utils/Config.ts b/src/lib/utils/Config.ts
index 393dd44..81e3a85 100644
--- a/src/lib/utils/Config.ts
+++ b/src/lib/utils/Config.ts
@@ -61,6 +61,7 @@ interface Credentials {
wolframAlphaAppId: string;
imgurClientId: string;
imgurClientSecret: string;
+ sentryDsn: string;
}
type Environment = 'production' | 'beta' | 'development';
diff --git a/src/listeners/commands/commandError.ts b/src/listeners/commands/commandError.ts
index 0ef4ebd..61fe206 100644
--- a/src/listeners/commands/commandError.ts
+++ b/src/listeners/commands/commandError.ts
@@ -1,4 +1,5 @@
import { BushCommandHandlerEvents } from '@lib';
+import { Severity } from '@sentry/types';
import { AkairoMessage, Command, GuildTextBasedChannels } from 'discord-akairo';
import { DMChannel, Formatters, Message, MessageEmbed } from 'discord.js';
import { BushListener } from '../../lib/extensions/discord-akairo/BushListener';
@@ -26,6 +27,25 @@ export default class CommandErrorListener extends BushListener {
: (message.channel as GuildTextBasedChannels)!.name;
const command = _command ?? message.util?.parsed?.command;
+ client.sentry.captureException(error, {
+ level: Severity.Error,
+ user: { id: message.author.id, username: message.author.tag },
+ extra: {
+ 'command.name': command?.id,
+ 'message.id': message.id,
+ 'message.type': message.util.isSlash ? 'slash' : 'normal',
+ 'message.parsed.content': message.util.parsed!.content,
+ 'channel.id':
+ message.channel!.type === 'DM'
+ ? (message.channel as DMChannel)!.recipient.id
+ : (message.channel as GuildTextBasedChannels)!.id,
+ 'channel.name': channel,
+ 'guild.id': message.guild?.id,
+ 'guild.name': message.guild?.name,
+ 'environment': client.config.environment
+ }
+ });
+
void client.console.error(
`${isSlash ? 'slashC' : 'c'}ommandError`,
`an error occurred with the <<${command}>> ${isSlash ? 'slash ' : ''}command in <<${channel}>> triggered by <<${
diff --git a/src/listeners/commands/commandStarted.ts b/src/listeners/commands/commandStarted.ts
index a9284ed..5d77d66 100644
--- a/src/listeners/commands/commandStarted.ts
+++ b/src/listeners/commands/commandStarted.ts
@@ -1,4 +1,7 @@
import { BushCommandHandlerEvents, BushListener } from '@lib';
+import { Severity } from '@sentry/types';
+import { GuildTextBasedChannels } from 'discord-akairo';
+import { DMChannel } from 'discord.js';
export default class CommandStartedListener extends BushListener {
public constructor() {
@@ -9,6 +12,29 @@ export default class CommandStartedListener extends BushListener {
});
}
public override exec(...[message, command]: BushCommandHandlerEvents['commandStarted']): void {
+ client.sentry.addBreadcrumb({
+ message: `[commandStarted] The ${command.id} was started by ${message.author.tag}.`,
+ level: Severity.Info,
+ timestamp: Date.now(),
+ data: {
+ 'command.name': command?.id,
+ 'message.id': message.id,
+ 'message.type': message.util.isSlash ? 'slash' : 'normal',
+ 'message.parsed.content': message.util.parsed!.content,
+ 'channel.id':
+ message.channel!.type === 'DM'
+ ? (message.channel as DMChannel)!.recipient.id
+ : (message.channel as GuildTextBasedChannels)!.id,
+ 'channel.name':
+ message.channel!.type === 'DM'
+ ? (message.channel as DMChannel)!.recipient.tag
+ : (message.channel as GuildTextBasedChannels)!.name,
+ 'guild.id': message.guild?.id,
+ 'guild.name': message.guild?.name,
+ 'environment': client.config.environment
+ }
+ });
+
void client.logger.info(
'commandStarted',
`The <<${command.id}>> command was used by <<${message.author.tag}>> in ${
diff --git a/src/listeners/other/promiseRejection.ts b/src/listeners/other/promiseRejection.ts
index 45e647e..ad16773 100644
--- a/src/listeners/other/promiseRejection.ts
+++ b/src/listeners/other/promiseRejection.ts
@@ -1,4 +1,5 @@
import { BushListener } from '@lib';
+import { Severity } from '@sentry/node';
import CommandErrorListener from '../commands/commandError';
export default class PromiseRejectionListener extends BushListener {
@@ -10,6 +11,10 @@ export default class PromiseRejectionListener extends BushListener {
}
public override async exec(error: Error) {
+ client.sentry.captureException(error, {
+ level: Severity.Error
+ });
+
void client.console.error(
'promiseRejection',
`An unhanded promise rejection occurred:\n${typeof error == 'object' ? error.stack : error}`,
diff --git a/src/listeners/other/uncaughtException.ts b/src/listeners/other/uncaughtException.ts
index 8eb4294..0f8c17c 100644
--- a/src/listeners/other/uncaughtException.ts
+++ b/src/listeners/other/uncaughtException.ts
@@ -1,4 +1,5 @@
import { BushListener } from '@lib';
+import { Severity } from '@sentry/node';
import CommandErrorListener from '../commands/commandError';
export default class UncaughtExceptionListener extends BushListener {
@@ -10,6 +11,10 @@ export default class UncaughtExceptionListener extends BushListener {
}
public override async exec(error: Error) {
+ client.sentry.captureException(error, {
+ level: Severity.Error
+ });
+
void client.console.error(
'uncaughtException',
`An uncaught exception occurred:\n${typeof error == 'object' ? error.stack : error}`,
diff --git a/src/listeners/other/warning.ts b/src/listeners/other/warning.ts
index 51f67ba..bf1488f 100644
--- a/src/listeners/other/warning.ts
+++ b/src/listeners/other/warning.ts
@@ -1,4 +1,5 @@
import { BushListener } from '@lib';
+import { Severity } from '@sentry/node';
import CommandErrorListener from '../commands/commandError';
export default class WarningListener extends BushListener {
@@ -10,6 +11,10 @@ export default class WarningListener extends BushListener {
}
public override async exec(error: Error) {
+ client.sentry.captureException(error, {
+ level: Severity.Warning
+ });
+
void client.console.warn('warning', `A warning occurred:\n${typeof error == 'object' ? error.stack : error}`, false);
void client.console.channelError({
embeds: [