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,
"node": true
},
"overrides": [
// {
// "files": [
// "tests/*"
// ],
// "env": {
// "jest": true,
// "jest/globals": true
// }
// }
],
"overrides": [],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
@ -109,7 +99,13 @@
"warn",
4,
{
"SwitchCase": 1
"SwitchCase": 1,
"VariableDeclarator": "first",
"FunctionDeclaration": {"parameters": "first"},
"CallExpression": {"arguments": "first"},
"ArrayExpression": "first",
"ObjectExpression": "first",
"ImportDeclaration": "first"
}
],
"init-declarations": "warn",
@ -118,14 +114,15 @@
"single"
],
"jsx-quotes": [
"warn",
"error",
"prefer-single"
],
"key-spacing": [
"warn",
{
"beforeColon": false,
"afterColon": true
"afterColon": true,
"align": "value"
}
],
"keyword-spacing": [
@ -164,7 +161,6 @@
"new-parens": "warn",
"no-alert": "warn",
"no-array-constructor": "warn",
// "no-bitwise": "warn",
"no-buffer-constructor": "warn",
"no-caller": "warn",
"no-console": "warn",
@ -192,7 +188,7 @@
"no-loop-func": "warn",
"no-mixed-requires": "warn",
"no-multi-assign": "warn",
"no-multi-spaces": "warn",
"no-multi-spaces": ["warn", {"ignoreEOLComments": true, "exceptions": {"ImportDeclaration": true}}],
"no-multi-str": "warn",
"no-multiple-empty-lines": "warn",
"no-native-reassign": "warn",
@ -224,7 +220,7 @@
"no-setter-return": "warn",
"no-spaced-func": "warn",
"@typescript-eslint/no-shadow": "error",
"no-tabs": "warn",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-throw-literal": "warn",
"no-trailing-spaces": "warn",
@ -241,7 +237,6 @@
"no-useless-rename": "warn",
"no-useless-return": "warn",
"no-var": "warn",
// "no-void": "warn",
"no-whitespace-before-property": "error",
"nonblock-statement-body-position": [
"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 defaultStats: MusicStatsEntry = {
name: '',
name: '',
plays: 0,
skips: 0
};
@ -267,14 +267,14 @@ class MusicLibrary implements Initialisable
const title = segmets[segmets.length - 1].replace((/\..+$/u), '');
const entry = {
id: this.#currentId++,
id: this.#currentId++,
artist: common.artist ?? artist,
title: common.title ?? title,
album: common.album,
year: common.year,
genre: common.genre ?? [],
file: fp,
stats: {
title: common.title ?? title,
album: common.album,
year: common.year,
genre: common.genre ?? [],
file: fp,
stats: {
plays: 0,
skips: 0
}

View File

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

View File

@ -33,10 +33,10 @@ class SpotifyAPI
const response = await fetch(
'https://accounts.spotify.com/api/token',
{
method: 'POST',
method: 'POST',
headers: {
'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')}`
}
@ -55,7 +55,10 @@ class SpotifyAPI
this.#token = token;
this.#tokenType = type;
setTimeout(this.login.bind(this), expires * 1000);
setTimeout(() =>
{
this.#ready = false;
}, expires * 1000);
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 [ artist ] = artists;
return {
album: album.name,
album: album.name,
artist: artist.name,
genres: artist.genres,
title: name
title: name
};
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ class CommandHandler extends Observer
constructor (client: DiscordClient)
{
super(client, {
name: 'commandHandler',
name: 'commandHandler',
priority: 10,
});
@ -29,16 +29,16 @@ class CommandHandler extends Observer
];
this.#parser = new Parser({
commands: this.client.commands.values(),
prefix: client.prefix,
resolver: client.resolver,
commands: this.client.commands.values(),
prefix: client.prefix,
resolver: client.resolver,
allowIncompleteReturn: true,
globalFlags: [{
name: 'help',
flag: true,
globalFlags: [{
name: 'help',
flag: true,
valueOptional: true,
defaultValue: true,
type: OptionType.BOOLEAN
defaultValue: true,
type: OptionType.BOOLEAN
}],
debug: false
});
@ -56,7 +56,7 @@ class CommandHandler extends Observer
try
{
result = await this.#parser.parseMessage(message.content, {
guild: message.guild,
guild: message.guild,
commandFilter: (cmd) =>
{
const command = cmd as Command;
@ -81,9 +81,9 @@ class CommandHandler extends Observer
if (err instanceof ParserError)
return void message.reply({
embeds: [{
title: 'Command parse error',
title: 'Command parse error',
description: err.message,
color: 0xbf2d30
color: 0xbf2d30
}],
allowedMentions
});
@ -91,9 +91,9 @@ class CommandHandler extends Observer
this.logger.error(error);
return void message.reply({
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.',
color: 0xbf2d30
color: 0xbf2d30
}],
allowedMentions
});
@ -123,9 +123,9 @@ class CommandHandler extends Observer
const [ first ] = inhibitions;
return void message.reply({
embeds: [{
title: 'Command execution inhibited',
title: 'Command execution inhibited',
description: first.reason ?? '',
color: 0xd88c49
color: 0xd88c49
}],
allowedMentions
});
@ -138,9 +138,9 @@ class CommandHandler extends Observer
this.logger.info(`${author.username} (${author.id}) ran into ${restrictedArgs.length} restricted arguments`);
return void message.reply({
embeds: [{
title: 'Restricted arguments',
title: 'Restricted arguments',
description: `${Util.plural(restrictedArgs.length, 'Argument')} ${restrictedArgs.map(flag => flag?.name).join(', ')} are restricted`,
color: 0xd88c49
color: 0xd88c49
}],
allowedMentions
});
@ -197,9 +197,9 @@ class CommandHandler extends Observer
const error = err as Error;
await message.reply({
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.',
color: 0xbf2d30
color: 0xbf2d30
}],
allowedMentions: { repliedUser: false },
failIfNotExists: false

View File

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

View File

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

View File

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

View File

@ -57,12 +57,12 @@ class Shard extends EventEmitter
this.#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
SHARDS: this.#id,
SHARD_ID: this.#id,
SHARD_COUNT: options.totalShards,
DISCORD_TOKEN: options.token
SHARDS: this.#id,
SHARD_ID: this.#id,
SHARD_COUNT: options.totalShards,
DISCORD_TOKEN: options.token
};
if (!options.clientOptions?.libraryOptions)
throw new Error('Missing library options, must provide intents');
@ -111,7 +111,7 @@ class Shard extends EventEmitter
this.#process = childProcess
.fork(path.resolve(this.#file), this.#args, {
env: this.#env as NodeJS.ProcessEnv,
env: this.#env as NodeJS.ProcessEnv,
execArgv: this.#execArgv
})
.on('message', this.#handleMessage.bind(this))

View File

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