Altered linter rules and subsequent pass. Change how Spotify API credentials are refreshed.

This commit is contained in:
Erik 2024-05-01 16:31:52 +03:00
parent 76f25ac199
commit 1ef645c27d
25 changed files with 140 additions and 142 deletions

View File

@ -6,17 +6,7 @@
"es6": true, "es6": true,
"node": true "node": true
}, },
"overrides": [ "overrides": [],
// {
// "files": [
// "tests/*"
// ],
// "env": {
// "jest": true,
// "jest/globals": true
// }
// }
],
"extends": [ "extends": [
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/recommended" "plugin:@typescript-eslint/recommended"
@ -109,7 +99,13 @@
"warn", "warn",
4, 4,
{ {
"SwitchCase": 1 "SwitchCase": 1,
"VariableDeclarator": "first",
"FunctionDeclaration": {"parameters": "first"},
"CallExpression": {"arguments": "first"},
"ArrayExpression": "first",
"ObjectExpression": "first",
"ImportDeclaration": "first"
} }
], ],
"init-declarations": "warn", "init-declarations": "warn",
@ -118,14 +114,15 @@
"single" "single"
], ],
"jsx-quotes": [ "jsx-quotes": [
"warn", "error",
"prefer-single" "prefer-single"
], ],
"key-spacing": [ "key-spacing": [
"warn", "warn",
{ {
"beforeColon": false, "beforeColon": false,
"afterColon": true "afterColon": true,
"align": "value"
} }
], ],
"keyword-spacing": [ "keyword-spacing": [
@ -164,7 +161,6 @@
"new-parens": "warn", "new-parens": "warn",
"no-alert": "warn", "no-alert": "warn",
"no-array-constructor": "warn", "no-array-constructor": "warn",
// "no-bitwise": "warn",
"no-buffer-constructor": "warn", "no-buffer-constructor": "warn",
"no-caller": "warn", "no-caller": "warn",
"no-console": "warn", "no-console": "warn",
@ -192,7 +188,7 @@
"no-loop-func": "warn", "no-loop-func": "warn",
"no-mixed-requires": "warn", "no-mixed-requires": "warn",
"no-multi-assign": "warn", "no-multi-assign": "warn",
"no-multi-spaces": "warn", "no-multi-spaces": ["warn", {"ignoreEOLComments": true, "exceptions": {"ImportDeclaration": true}}],
"no-multi-str": "warn", "no-multi-str": "warn",
"no-multiple-empty-lines": "warn", "no-multiple-empty-lines": "warn",
"no-native-reassign": "warn", "no-native-reassign": "warn",
@ -224,7 +220,7 @@
"no-setter-return": "warn", "no-setter-return": "warn",
"no-spaced-func": "warn", "no-spaced-func": "warn",
"@typescript-eslint/no-shadow": "error", "@typescript-eslint/no-shadow": "error",
"no-tabs": "warn", "no-tabs": "error",
"no-template-curly-in-string": "error", "no-template-curly-in-string": "error",
"no-throw-literal": "warn", "no-throw-literal": "warn",
"no-trailing-spaces": "warn", "no-trailing-spaces": "warn",
@ -241,7 +237,6 @@
"no-useless-rename": "warn", "no-useless-rename": "warn",
"no-useless-return": "warn", "no-useless-return": "warn",
"no-var": "warn", "no-var": "warn",
// "no-void": "warn",
"no-whitespace-before-property": "error", "no-whitespace-before-property": "error",
"nonblock-statement-body-position": [ "nonblock-statement-body-position": [
"warn", "warn",

View File

@ -16,7 +16,7 @@ import { inspect } from 'node:util';
const linkReg = /(https?:\/\/(www\.)?)?(?<domain>([a-z0-9-]{1,63}\.)?([a-z0-9-]{1,63})(\.[a-z0-9-]{2,63})(\.[a-z0-9-]{2,63})?)(\/[^()\s]*)?/iu; const linkReg = /(https?:\/\/(www\.)?)?(?<domain>([a-z0-9-]{1,63}\.)?([a-z0-9-]{1,63})(\.[a-z0-9-]{2,63})(\.[a-z0-9-]{2,63})?)(\/[^()\s]*)?/iu;
const defaultStats: MusicStatsEntry = { const defaultStats: MusicStatsEntry = {
name: '', name: '',
plays: 0, plays: 0,
skips: 0 skips: 0
}; };
@ -267,14 +267,14 @@ class MusicLibrary implements Initialisable
const title = segmets[segmets.length - 1].replace((/\..+$/u), ''); const title = segmets[segmets.length - 1].replace((/\..+$/u), '');
const entry = { const entry = {
id: this.#currentId++, id: this.#currentId++,
artist: common.artist ?? artist, artist: common.artist ?? artist,
title: common.title ?? title, title: common.title ?? title,
album: common.album, album: common.album,
year: common.year, year: common.year,
genre: common.genre ?? [], genre: common.genre ?? [],
file: fp, file: fp,
stats: { stats: {
plays: 0, plays: 0,
skips: 0 skips: 0
} }

View File

@ -98,7 +98,7 @@ class MusicPlayer implements Initialisable
const config = { const config = {
volume: this.#volume, volume: this.#volume,
queue: this.#queue queue: this.#queue
}; };
fs.writeFileSync(cachePath, JSON.stringify(config)); fs.writeFileSync(cachePath, JSON.stringify(config));
} }
@ -149,7 +149,7 @@ class MusicPlayer implements Initialisable
this.#currentSong = info; this.#currentSong = info;
this.#currentResource = createAudioResource(info.file, { this.#currentResource = createAudioResource(info.file, {
inlineVolume: true, inlineVolume: true,
metadata: { metadata: {
title: info.title title: info.title
} }
}); });
@ -183,9 +183,9 @@ class MusicPlayer implements Initialisable
return; return;
const payload = { const payload = {
embeds: [{ embeds: [{
title: 'Now playing :notes:', title: 'Now playing :notes:',
description: `**${info.title}** by ${info.artist}`, description: `**${info.title}** by ${info.artist}`,
color: 0xffafff color: 0xffafff
}] }]
}; };
const messages = await channel.messages.fetch({ limit: 100 }); const messages = await channel.messages.fetch({ limit: 100 });
@ -236,8 +236,8 @@ class MusicPlayer implements Initialisable
} }
const connection = joinVoiceChannel({ const connection = joinVoiceChannel({
channelId: channel.id, channelId: channel.id,
guildId: guild.id, guildId: guild.id,
adapterCreator: guild.voiceAdapterCreator adapterCreator: guild.voiceAdapterCreator
}); });
connection.removeAllListeners(); connection.removeAllListeners();

View File

@ -33,10 +33,10 @@ class SpotifyAPI
const response = await fetch( const response = await fetch(
'https://accounts.spotify.com/api/token', 'https://accounts.spotify.com/api/token',
{ {
method: 'POST', method: 'POST',
headers: { headers: {
'Authorization': `Basic ${Buffer.from(`${this.#id}:${this.#secret}`).toString('base64')}`, 'Authorization': `Basic ${Buffer.from(`${this.#id}:${this.#secret}`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
}, },
body: `${encodeURI('grant_type')}=${encodeURI('client_credentials')}` body: `${encodeURI('grant_type')}=${encodeURI('client_credentials')}`
} }
@ -55,7 +55,10 @@ class SpotifyAPI
this.#token = token; this.#token = token;
this.#tokenType = type; this.#tokenType = type;
setTimeout(this.login.bind(this), expires * 1000); setTimeout(() =>
{
this.#ready = false;
}, expires * 1000);
this.#ready = true; this.#ready = true;
} }
@ -70,10 +73,10 @@ class SpotifyAPI
const { album, artists, name } = data as { album: { name: string }, artists: { name: string, genres: string[] }[], name: string }; const { album, artists, name } = data as { album: { name: string }, artists: { name: string, genres: string[] }[], name: string };
const [ artist ] = artists; const [ artist ] = artists;
return { return {
album: album.name, album: album.name,
artist: artist.name, artist: artist.name,
genres: artist.genres, genres: artist.genres,
title: name title: name
}; };
} }

View File

@ -8,17 +8,17 @@ class ListCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'list', name: 'list',
description: 'Display a list of things on the bot.', description: 'Display a list of things on the bot.',
options: [{ options: [{
name: 'commands', name: 'commands',
type: OptionType.SUB_COMMAND, type: OptionType.SUB_COMMAND,
options: [{ options: [{
name: 'all', name: 'all',
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
valueOptional: true, valueOptional: true,
defaultValue: true, defaultValue: true,
flag: true flag: true
}] }]
}] }]
}); });

View File

@ -6,7 +6,7 @@ class PingCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'ping', name: 'ping',
description: 'pong' description: 'pong'
}); });
} }

View File

@ -8,10 +8,10 @@ class QueueCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'queue', name: 'queue',
aliases: [ 'q' ], aliases: [ 'q' ],
description: 'Queue a song (must be already downloaded, use search to look up songs), or display the current queue.', description: 'Queue a song (must be already downloaded, use search to look up songs), or display the current queue.',
options: [{ options: [{
name: 'artist', name: 'artist',
flag: true flag: true
}, { }, {
@ -45,9 +45,9 @@ class QueueCommand extends Command
const [ artist ]= map.get('artist') ?? []; const [ artist ]= map.get('artist') ?? [];
const [ id ]= map.get('id') ?? []; const [ id ]= map.get('id') ?? [];
const query = { const query = {
title: song?.value as string | undefined, title: song?.value as string | undefined,
artist: artist?.value as string | undefined, artist: artist?.value as string | undefined,
id: id?.value as number | undefined id: id?.value as number | undefined
}; };
const result = this.client.musicPlayer.queueSong(query); const result = this.client.musicPlayer.queueSong(query);

View File

@ -10,14 +10,14 @@ class RequestCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'request', name: 'request',
aliases: [ 'r', 'req' ], aliases: [ 'r', 'req' ],
description: 'Request a song to be downloaded and queued.', description: 'Request a song to be downloaded and queued.',
guildOnly: true, guildOnly: true,
sameVc: true, sameVc: true,
showUsage: true, showUsage: true,
options: [{ options: [{
name: 'link', name: 'link',
required: true required: true
}] }]
}); });

View File

@ -8,15 +8,15 @@ class PingCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'rescan', name: 'rescan',
restricted: true, restricted: true,
description: 'Rescan the library and add to index.', description: 'Rescan the library and add to index.',
options: [{ options: [{
name: 'rebuild', name: 'rebuild',
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
flag: true, flag: true,
valueOptional: true, valueOptional: true,
defaultValue: true defaultValue: true
}] }]
}); });
} }

View File

@ -6,10 +6,10 @@ class ReshuffleCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'reshuffle', name: 'reshuffle',
description: 'Reshuffles the playlist (does not apply to queue).', description: 'Reshuffles the playlist (does not apply to queue).',
sameVc: true, sameVc: true,
guildOnly: true, guildOnly: true,
}); });
} }

View File

@ -8,11 +8,11 @@ class SearchCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'search', name: 'search',
aliases: [ 's', 'query' ], aliases: [ 's', 'query' ],
description: 'Search the index for an already downloaded song.', description: 'Search the index for an already downloaded song.',
showUsage: true, showUsage: true,
options: [{ options: [{
name: 'keyword', name: 'keyword',
}, { }, {
name: 'artist', name: 'artist',
@ -30,8 +30,8 @@ class SearchCommand extends Command
const [ artist ] = map.get('artist') ?? []; const [ artist ] = map.get('artist') ?? [];
const [ keyword ] = map.get('keyword') ?? []; const [ keyword ] = map.get('keyword') ?? [];
const query = { const query = {
title: song?.value as string | undefined, title: song?.value as string | undefined,
artist: artist?.value as string | undefined, artist: artist?.value as string | undefined,
keyword: keyword?.value as string | undefined keyword: keyword?.value as string | undefined
}; };
const results = this.client.musicPlayer.library.search(query); const results = this.client.musicPlayer.library.search(query);

View File

@ -8,13 +8,13 @@ class SetAvatarCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'set', name: 'set',
description: 'Sets various things on the bot.', description: 'Sets various things on the bot.',
options: [{ options: [{
name: 'avatar', name: 'avatar',
type: OptionType.SUB_COMMAND, type: OptionType.SUB_COMMAND,
options: [{ options: [{
name: 'asset', name: 'asset',
required: true required: true
}] }]
}], }],

View File

@ -7,12 +7,12 @@ class SkipCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'skip', name: 'skip',
description: 'Skips the current song.', description: 'Skips the current song.',
guildOnly: true, guildOnly: true,
// restricted: true, // restricted: true,
sameVc: true, sameVc: true,
limited: [ '1076274430520594514' ] limited: [ '1076274430520594514' ]
}); });
} }

View File

@ -9,15 +9,15 @@ class StatsCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'stats', name: 'stats',
description: 'Display statistics about the songs played', description: 'Display statistics about the songs played',
options: [{ options: [{
name: 'reset', name: 'reset',
type: OptionType.BOOLEAN, type: OptionType.BOOLEAN,
defaultValue: true, defaultValue: true,
valueOptional: true, valueOptional: true,
flag: true, flag: true,
restricted: true restricted: true
}], }],
guildOnly: true guildOnly: true
}); });

View File

@ -8,13 +8,13 @@ class VolumeCommand extends Command
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'volume', name: 'volume',
aliases: [ 'v', 'vol' ], aliases: [ 'v', 'vol' ],
description: 'Display or set the volume.', description: 'Display or set the volume.',
options: [ options: [
{ {
name: 'volume', name: 'volume',
type: OptionType.INTEGER, type: OptionType.INTEGER,
// required: true, // required: true,
minimum: 0, minimum: 0,
maximum: 100 maximum: 100
@ -22,8 +22,8 @@ class VolumeCommand extends Command
], ],
guildOnly: true, guildOnly: true,
// restricted: true, // restricted: true,
sameVc: true, sameVc: true,
limited: [ '1076274430520594514' ], limited: [ '1076274430520594514' ],
}); });
} }

View File

@ -121,9 +121,9 @@ class SpotifyDownloader extends Downloader
const ext = elems[elems.length - 1]; const ext = elems[elems.length - 1];
return Promise.resolve({ return Promise.resolve({
existing: true, existing: true,
artist: existingData.artist, artist: existingData.artist,
song: existingData.title, song: existingData.title,
album: data.album, album: data.album,
ext ext
}); });
} }

View File

@ -9,7 +9,7 @@ class DMOnlyInhibitor extends Inhibitor
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'DMOnly', name: 'DMOnly',
priority: 4 priority: 4
}); });
} }

View File

@ -9,7 +9,7 @@ class GuildOnlyInhibitor extends Inhibitor
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'GuildOnly', name: 'GuildOnly',
priority: 4 priority: 4
}); });
} }

View File

@ -10,7 +10,7 @@ class LimitedInhibitor extends Inhibitor
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'Limited', name: 'Limited',
priority: 5 priority: 5
}); });
} }

View File

@ -20,7 +20,7 @@ class CommandHandler extends Observer
constructor (client: DiscordClient) constructor (client: DiscordClient)
{ {
super(client, { super(client, {
name: 'commandHandler', name: 'commandHandler',
priority: 10, priority: 10,
}); });
@ -29,16 +29,16 @@ class CommandHandler extends Observer
]; ];
this.#parser = new Parser({ this.#parser = new Parser({
commands: this.client.commands.values(), commands: this.client.commands.values(),
prefix: client.prefix, prefix: client.prefix,
resolver: client.resolver, resolver: client.resolver,
allowIncompleteReturn: true, allowIncompleteReturn: true,
globalFlags: [{ globalFlags: [{
name: 'help', name: 'help',
flag: true, flag: true,
valueOptional: true, valueOptional: true,
defaultValue: true, defaultValue: true,
type: OptionType.BOOLEAN type: OptionType.BOOLEAN
}], }],
debug: false debug: false
}); });
@ -56,7 +56,7 @@ class CommandHandler extends Observer
try try
{ {
result = await this.#parser.parseMessage(message.content, { result = await this.#parser.parseMessage(message.content, {
guild: message.guild, guild: message.guild,
commandFilter: (cmd) => commandFilter: (cmd) =>
{ {
const command = cmd as Command; const command = cmd as Command;
@ -81,9 +81,9 @@ class CommandHandler extends Observer
if (err instanceof ParserError) if (err instanceof ParserError)
return void message.reply({ return void message.reply({
embeds: [{ embeds: [{
title: 'Command parse error', title: 'Command parse error',
description: err.message, description: err.message,
color: 0xbf2d30 color: 0xbf2d30
}], }],
allowedMentions allowedMentions
}); });
@ -91,9 +91,9 @@ class CommandHandler extends Observer
this.logger.error(error); this.logger.error(error);
return void message.reply({ return void message.reply({
embeds: [{ embeds: [{
title: 'Command parse error', title: 'Command parse error',
description: this.client.isDeveloper(author) ? `\`\`\`js\n${error.stack ?? error.message}\n\`\`\`` : 'An internal error occurred...\n\nThis has been logged, please try again at a later point.', description: this.client.isDeveloper(author) ? `\`\`\`js\n${error.stack ?? error.message}\n\`\`\`` : 'An internal error occurred...\n\nThis has been logged, please try again at a later point.',
color: 0xbf2d30 color: 0xbf2d30
}], }],
allowedMentions allowedMentions
}); });
@ -123,9 +123,9 @@ class CommandHandler extends Observer
const [ first ] = inhibitions; const [ first ] = inhibitions;
return void message.reply({ return void message.reply({
embeds: [{ embeds: [{
title: 'Command execution inhibited', title: 'Command execution inhibited',
description: first.reason ?? '', description: first.reason ?? '',
color: 0xd88c49 color: 0xd88c49
}], }],
allowedMentions allowedMentions
}); });
@ -138,9 +138,9 @@ class CommandHandler extends Observer
this.logger.info(`${author.username} (${author.id}) ran into ${restrictedArgs.length} restricted arguments`); this.logger.info(`${author.username} (${author.id}) ran into ${restrictedArgs.length} restricted arguments`);
return void message.reply({ return void message.reply({
embeds: [{ embeds: [{
title: 'Restricted arguments', title: 'Restricted arguments',
description: `${Util.plural(restrictedArgs.length, 'Argument')} ${restrictedArgs.map(flag => flag?.name).join(', ')} are restricted`, description: `${Util.plural(restrictedArgs.length, 'Argument')} ${restrictedArgs.map(flag => flag?.name).join(', ')} are restricted`,
color: 0xd88c49 color: 0xd88c49
}], }],
allowedMentions allowedMentions
}); });
@ -197,9 +197,9 @@ class CommandHandler extends Observer
const error = err as Error; const error = err as Error;
await message.reply({ await message.reply({
embeds: [{ embeds: [{
title: 'Command execution error', title: 'Command execution error',
description: this.client.isDeveloper(message.author) ? `\`\`\`js\n${error.stack ?? error.message}\n\`\`\`` : 'An internal error occurred, this has been logged.\nTry again later.\n\nIf your issue is truly urgent contact staff directly.', description: this.client.isDeveloper(message.author) ? `\`\`\`js\n${error.stack ?? error.message}\n\`\`\`` : 'An internal error occurred, this has been logged.\nTry again later.\n\nIf your issue is truly urgent contact staff directly.',
color: 0xbf2d30 color: 0xbf2d30
}], }],
allowedMentions: { repliedUser: false }, allowedMentions: { repliedUser: false },
failIfNotExists: false failIfNotExists: false

View File

@ -58,9 +58,9 @@ class CommandError extends Error
get embed () get embed ()
{ {
return { return {
title: 'Command Error', title: 'Command Error',
description: this.reason, description: this.reason,
color: 15120384 color: 15120384
}; };
} }

View File

@ -89,7 +89,7 @@ abstract class Component
this.client.emit('componentUpdate', { this.client.emit('componentUpdate', {
component: this, component: this,
type: 'UNLOAD' type: 'UNLOAD'
}); });
return { error: false }; return { error: false };

View File

@ -37,13 +37,13 @@ class Controller
options.discord.logger = options.logger; options.discord.logger = options.logger;
options.discord.version = version; options.discord.version = version;
this.#shardingOptions = { this.#shardingOptions = {
path: clientPath, path: clientPath,
totalShards, totalShards,
shardList, shardList,
respawn, respawn,
shardArgs: [], shardArgs: [],
execArgv, execArgv,
token: process.env.DISCORD_TOKEN, token: process.env.DISCORD_TOKEN,
clientOptions: options.discord, clientOptions: options.discord,
debug debug
}; };

View File

@ -57,12 +57,12 @@ class Shard extends EventEmitter
this.#env = { this.#env = {
...process.env, ...process.env,
SHARDING_MANAGER: true, // IMPORTANT, SHARD IPC WILL BREAK IF MISSING SHARDING_MANAGER: true, // IMPORTANT, SHARD IPC WILL BREAK IF MISSING
SHARDING_MANAGER_MODE: 'process', // IMPORTANT, SHARD IPC WILL BREAK IF MISSING SHARDING_MANAGER_MODE: 'process', // IMPORTANT, SHARD IPC WILL BREAK IF MISSING
SHARDS: this.#id, SHARDS: this.#id,
SHARD_ID: this.#id, SHARD_ID: this.#id,
SHARD_COUNT: options.totalShards, SHARD_COUNT: options.totalShards,
DISCORD_TOKEN: options.token DISCORD_TOKEN: options.token
}; };
if (!options.clientOptions?.libraryOptions) if (!options.clientOptions?.libraryOptions)
throw new Error('Missing library options, must provide intents'); throw new Error('Missing library options, must provide intents');
@ -111,7 +111,7 @@ class Shard extends EventEmitter
this.#process = childProcess this.#process = childProcess
.fork(path.resolve(this.#file), this.#args, { .fork(path.resolve(this.#file), this.#args, {
env: this.#env as NodeJS.ProcessEnv, env: this.#env as NodeJS.ProcessEnv,
execArgv: this.#execArgv execArgv: this.#execArgv
}) })
.on('message', this.#handleMessage.bind(this)) .on('message', this.#handleMessage.bind(this))

View File

@ -22,10 +22,10 @@ const Constants: {
QuotePairs: StringIndexable<string> QuotePairs: StringIndexable<string>
} = { } = {
QuotePairs: { QuotePairs: {
'"': '"', // regular double '"': '"', // regular double
'\'': '\'', // regular single '\'': '\'', // regular single
'': '', // smart single '': '', // smart single
'“': '”' // smart double '“': '”' // smart double
} }
}; };
@ -357,7 +357,7 @@ class Util
word = ''; word = '';
const words: [string, boolean][] = [], const words: [string, boolean][] = [],
chars = string.split(''); chars = string.split('');
chars.forEach((char: string) => chars.forEach((char: string) =>
{ {
@ -506,9 +506,9 @@ class Util
static makePlainError (err: Error): PlainError static makePlainError (err: Error): PlainError
{ {
return { return {
name: err.name, name: err.name,
message: err.message, message: err.message,
stack: err.stack stack: err.stack
}; };
} }
@ -544,7 +544,7 @@ class Util
if (!token) if (!token)
throw new Error('[util] Token missing.'); throw new Error('[util] Token missing.');
return fetch('https://discord.com/api/v7/gateway/bot', { return fetch('https://discord.com/api/v7/gateway/bot', {
method: 'GET', method: 'GET',
headers: { Authorization: `Bot ${token.replace(/^Bot\s*/iu, '')}` } headers: { Authorization: `Bot ${token.replace(/^Bot\s*/iu, '')}` }
}).then((res) => }).then((res) =>
{ {