Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull Request: ESLint Configuration, Dependency Updates, and Type Safety Improvements #1178

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 58 additions & 4 deletions README.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it has been added with chatgpt, why should this be added exactly?

Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ The `master` branch acts as the developing / bleeding edge branch and is not gua

When running a production instance, I recommend that you use the [latest release](https://github.com/museofficial/muse/releases/).


### 🐳 Docker

There are a variety of image tags available:

- `:2`: versions >= 2.0.0
- `:2.1`: versions >= 2.1.0 and < 2.2.0
- `:2.1.1`: an exact version specifier
Expand All @@ -60,7 +60,7 @@ docker run -it -v "$(pwd)/data":/data -e DISCORD_TOKEN='' -e SPOTIFY_CLIENT_ID='

This starts Muse and creates a data directory in your current directory.

You can also store your tokens in an environment file and make it available to your container. By default, the container will look for a `/config` environment file. You can customize this path with the `ENV_FILE` environment variable to use with, for example, [docker secrets](https://docs.docker.com/engine/swarm/secrets/).
You can also store your tokens in an environment file and make it available to your container. By default, the container will look for a `/config` environment file. You can customize this path with the `ENV_FILE` environment variable to use with, for example, [docker secrets](https://docs.docker.com/engine/swarm/secrets/).

**Docker Compose**:

Expand All @@ -81,8 +81,9 @@ services:
### Node.js

**Prerequisites**:
* Node.js (18.17.0 or later is required and latest 18.x.x LTS is recommended)
* ffmpeg (4.1 or later)

- Node.js (18.17.0 or later is required and latest 18.x.x LTS is recommended)
- ffmpeg (4.1 or later)

1. `git clone https://github.com/museofficial/muse.git && cd muse`
2. Copy `.env.example` to `.env` and populate with values
Expand Down Expand Up @@ -125,11 +126,13 @@ In the default state, Muse has the status "Online" and the text "Listening to Mu
#### Examples

**Muse is watching a movie and is DND**:

- `BOT_STATUS=dnd`
- `BOT_ACTIVITY_TYPE=WATCHING`
- `BOT_ACTIVITY=a movie`

**Muse is streaming Monstercat**:

- `BOT_STATUS=online`
- `BOT_ACTIVITY_TYPE=STREAMING`
- `BOT_ACTIVITY_URL=https://www.twitch.tv/monstercat`
Expand All @@ -147,3 +150,54 @@ You can configure the bot to automatically turn down the volume when people are
- `/config set-reduce-vol-when-voice false` - Disable automatic volume reduction
- `/config set-reduce-vol-when-voice-target <volume>` - Set the target volume percentage when people speak (0-100, default is 70)

------

## Workflow section

## Database Workflow via Prisma using Node.js

muse uses [Prisma](https://www.prisma.io/) as an Object-Relational Mapping (ORM) tool to interact with a database. To properly set up and manage the database, you'll need to run a few commands.

### Generating Migrations

Whenever you make changes to some database schema defined in the Prisma schema file (see: [`schema.prisma`](schema.prisma)), you're gonna need to generate migration files. For this run:

```bash
npm run migrations:generate
```

This command will generate new migration files based on the changes you've made to the schema.

### Applying Migrations

After generating migration files, you need to apply them to your database to update its schema. Run the following command to apply pending migrations:

```bash
npm run migrations:run
```

This command will execute the migration files and bring your database schema up to date.

### Starting the Bot

To start the bot and ensure that the database is properly set up, use the following command:

```bash
npm start
```

This command will set the necessary environment variables, apply any pending migrations, and then start the bot.

### Generating Prisma Client

If you make changes to the Prisma schema, you'll need to regenerate the Prisma client to update the TypeScript types and client code. Run the following command to generate the Prisma client:

```bash
npm run prisma:generate
```

This command will generate the updated Prisma client based on your current schema.

### Environment Variables

The `prisma:with-env` script is a helper command that sets the `DATABASE_URL` environment variable and then runs the `prisma` command. Make sure you have the correct database URL set in your environment - see [`.env.example`] (example.env) - variables before running any Prisma-related commands.
12 changes: 12 additions & 0 deletions eslint.config.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not widly known with eslint configuration, I'm assuming this is added for linting during development. Instead of only during committing?

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pluginJs from "@eslint/js";
import globals from "globals";
import tseslint from "typescript-eslint";


/** @type {import('eslint').Linter.Config[]} */
export default [
{files: ["**/*.{js,mjs,cjs,ts}"]},
{languageOptions: { globals: globals.browser }},
pluginJs.configs.recommended,
...tseslint.configs.recommended,
];
19 changes: 10 additions & 9 deletions package.json
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has the bot been checked to still work with all these dependencies? I tried updating some a while back and they still broke the functionality of the bot.

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@release-it/keep-a-changelog": "^2.3.0",
"@types/bluebird": "^3.5.35",
"@types/debug": "^4.1.5",
"@types/fluent-ffmpeg": "^2.1.17",
"@types/fluent-ffmpeg": "^2.1.27",
"@types/fs-capacitor": "^2.0.0",
"@types/ms": "0.7.34",
"@types/node": "^17.0.0",
Expand All @@ -45,12 +45,12 @@
"@types/ws": "8.5.4",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"eslint": "^7.32.0",
"eslint": "^9.17.0",
"eslint-config-xo": "^0.39.0",
"eslint-config-xo-typescript": "^0.44.0",
"eslint-plugin-import": "2.29.1",
"husky": "^4.3.8",
"prisma": "5.21.1",
"prisma": "^6.1.0",
"release-it": "^14.11.8",
"type-fest": "^2.12.0",
"typescript": "^4.6.4"
Expand Down Expand Up @@ -86,26 +86,26 @@
},
"dependencies": {
"@discordjs/builders": "1.1.0",
"@discordjs/opus": "^0.8.0",
"@discordjs/opus": "^0.9.0",
"@discordjs/rest": "1.0.1",
"@discordjs/voice": "0.17.0",
"@distube/ytdl-core": "^4.14.4",
"@distube/ytsr": "^2.0.0",
"@prisma/client": "4.16.0",
"@prisma/client": "^6.1.0",
"@types/libsodium-wrappers": "^0.7.9",
"array-shuffle": "^3.0.0",
"debug": "^4.3.3",
"delay": "^5.0.0",
"discord-api-types": "0.32.1",
"discord-api-types": "^0.37.114",
"discord.js": "14.11.0",
"dotenv": "^16.4.5",
"execa": "^6.1.0",
"fluent-ffmpeg": "^2.1.2",
"fluent-ffmpeg": "^2.1.3",
"fs-capacitor": "^7.0.1",
"get-youtube-id": "^1.0.1",
"got": "^12.0.2",
"hasha": "^5.2.2",
"inversify": "^6.0.1",
"inversify": "^6.2.1",
"iso8601-duration": "^2.1.2",
"libsodium-wrappers": "^0.7.9",
"make-dir": "^3.1.0",
Expand All @@ -121,12 +121,13 @@
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"read-pkg": "7.1.0",
"reflect-metadata": "^0.1.13",
"reflect-metadata": "^0.2.2",
"sponsorblock-api": "^0.2.4",
"spotify-uri": "^3.0.2",
"spotify-web-api-node": "^5.0.2",
"sync-fetch": "^0.3.1",
"tsx": "3.8.2",
"typescript-eslint": "^8.18.2",
"xbytes": "^1.7.0",
"ytsr": "^3.8.4"
},
Expand Down
26 changes: 14 additions & 12 deletions src/bot.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it has only been ordered correctly. No functional changes what-so-ever.

Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {Client, Collection, User} from 'discord.js';
import {inject, injectable} from 'inversify';
import { REST } from '@discordjs/rest';
import { generateDependencyReport } from '@discordjs/voice';
import { Routes } from 'discord-api-types/v10';
import { Client, Collection, User } from 'discord.js';
import { inject, injectable } from 'inversify';
import ora from 'ora';
import {TYPES} from './types.js';
import container from './inversify.config.js';
import Command from './commands/index.js';
import debug from './utils/debug.js';
import handleGuildCreate from './events/guild-create.js';
import handleVoiceStateUpdate from './events/voice-state-update.js';
import errorMsg from './utils/error-msg.js';
import {isUserInVoice} from './utils/channels.js';
import container from './inversify.config.js';
import Config from './services/config.js';
import {generateDependencyReport} from '@discordjs/voice';
import {REST} from '@discordjs/rest';
import {Routes} from 'discord-api-types/v10';
import { TYPES } from './types.js';
import { isUserInVoice } from './utils/channels.js';
import debug from './utils/debug.js';
import errorMsg from './utils/error-msg.js';
import registerCommandsOnGuild from './utils/register-commands-on-guild.js';

@injectable()
Expand Down Expand Up @@ -54,7 +54,7 @@ export default class {
}

// Register event handlers
// eslint-disable-next-line complexity
this.client.on('interactionCreate', async interaction => {
try {
if (interaction.isCommand()) {
Expand Down Expand Up @@ -109,7 +109,9 @@ export default class {
} else if (interaction.isCommand() || interaction.isButton()) {
await interaction.reply({content: errorMsg(error as Error), ephemeral: true});
}
} catch {}
} catch {
// Do nothing
}
}
});

Expand Down
26 changes: 14 additions & 12 deletions src/commands/play.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import {AutocompleteInteraction, ChatInputCommandInteraction} from 'discord.js';
import {URL} from 'url';
import {SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder} from '@discordjs/builders';
import {inject, injectable, optional} from 'inversify';
import { SlashCommandBuilder, SlashCommandSubcommandsOnlyBuilder } from '@discordjs/builders';
import { AutocompleteInteraction, ChatInputCommandInteraction } from 'discord.js';
import { inject, injectable, optional } from 'inversify';
import Spotify from 'spotify-web-api-node';
import Command from './index.js';
import {TYPES} from '../types.js';
import { URL } from 'url';
import AddQueryToQueue from '../services/add-query-to-queue.js';
import KeyValueCacheProvider from '../services/key-value-cache.js';
import ThirdParty from '../services/third-party.js';
import { TYPES } from '../types.js';
import { ONE_HOUR_IN_SECONDS } from '../utils/constants.js';
import getYouTubeAndSpotifySuggestionsFor from '../utils/get-youtube-and-spotify-suggestions-for.js';
import KeyValueCacheProvider from '../services/key-value-cache.js';
import {ONE_HOUR_IN_SECONDS} from '../utils/constants.js';
import AddQueryToQueue from '../services/add-query-to-queue.js';
import Command from './index.js';

@injectable()
export default class implements Command {
Expand Down Expand Up @@ -75,14 +75,16 @@ export default class implements Command {

try {
// Don't return suggestions for URLs
// eslint-disable-next-line no-new
new URL(query);
await interaction.respond([]);
return;
} catch {}
} catch {
// Ignore
}

const suggestions = await this.cache.wrap(
getYouTubeAndSpotifySuggestionsFor,
async (...args: unknown[]) => getYouTubeAndSpotifySuggestionsFor(args[0] as string, args[1] as Spotify, args[2] as number),
query,
this.spotify,
10,
Expand Down
11 changes: 6 additions & 5 deletions src/commands/skip.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it has only been ordered correctly. No functional changes what-so-ever.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {ChatInputCommandInteraction} from 'discord.js';
import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify';
import { SlashCommandBuilder } from '@discordjs/builders';
import { ChatInputCommandInteraction } from 'discord.js';
import { inject, injectable } from 'inversify';
import PlayerManager from '../managers/player.js';
import { TYPES } from '../types.js';
import { buildPlayingMessageEmbed } from '../utils/build-embed.js';
import Command from './index.js';
import {SlashCommandBuilder} from '@discordjs/builders';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js';

@injectable()
export default class implements Command {
Expand Down Expand Up @@ -39,6 +39,7 @@ export default class implements Command {
content: 'keep \'er movin\'',
embeds: player.getCurrent() ? [buildPlayingMessageEmbed(player)] : [],
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_: unknown) {
throw new Error('no song to skip to');
}
Expand Down
11 changes: 6 additions & 5 deletions src/commands/unskip.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {ChatInputCommandInteraction} from 'discord.js';
import {TYPES} from '../types.js';
import {inject, injectable} from 'inversify';
import { SlashCommandBuilder } from '@discordjs/builders';
import { ChatInputCommandInteraction } from 'discord.js';
import { inject, injectable } from 'inversify';
import PlayerManager from '../managers/player.js';
import { TYPES } from '../types.js';
import { buildPlayingMessageEmbed } from '../utils/build-embed.js';
import Command from './index.js';
import {SlashCommandBuilder} from '@discordjs/builders';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js';

@injectable()
export default class implements Command {
Expand All @@ -29,6 +29,7 @@ export default class implements Command {
content: 'back \'er up\'',
embeds: player.getCurrent() ? [buildPlayingMessageEmbed(player)] : [],
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_: unknown) {
throw new Error('no song to go back to');
}
Expand Down
9 changes: 5 additions & 4 deletions src/events/voice-state-update.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {VoiceChannel, VoiceState} from 'discord.js';
import { VoiceChannel, VoiceState } from 'discord.js';
import container from '../inversify.config.js';
import {TYPES} from '../types.js';
import PlayerManager from '../managers/player.js';
import {getSizeWithoutBots} from '../utils/channels.js';
import {getGuildSettings} from '../utils/get-guild-settings.js';
import { TYPES } from '../types.js';
import { getSizeWithoutBots } from '../utils/channels.js';
import { getGuildSettings } from '../utils/get-guild-settings.js';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default async (oldState: VoiceState, _: VoiceState): Promise<void> => {
const playerManager = container.get<PlayerManager>(TYPES.Managers.Player);

Expand Down
23 changes: 12 additions & 11 deletions src/services/add-query-to-queue.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'm assuming here that several variables have been changed and or replaced. What about the code it was attached to?

Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/* eslint-disable complexity */
import {ChatInputCommandInteraction, GuildMember} from 'discord.js';
import {inject, injectable} from 'inversify';

import shuffle from 'array-shuffle';
import {TYPES} from '../types.js';
import GetSongs from '../services/get-songs.js';
import {MediaSource, SongMetadata, STATUS} from './player.js';
import { ChatInputCommandInteraction, GuildMember } from 'discord.js';
import { inject, injectable } from 'inversify';
import { SponsorBlock } from 'sponsorblock-api';
import PlayerManager from '../managers/player.js';
import {buildPlayingMessageEmbed} from '../utils/build-embed.js';
import {getMemberVoiceChannel, getMostPopularVoiceChannel} from '../utils/channels.js';
import {getGuildSettings} from '../utils/get-guild-settings.js';
import {SponsorBlock} from 'sponsorblock-api';
import GetSongs from '../services/get-songs.js';
import { TYPES } from '../types.js';
import { buildPlayingMessageEmbed } from '../utils/build-embed.js';
import { getMemberVoiceChannel, getMostPopularVoiceChannel } from '../utils/channels.js';
import { ONE_HOUR_IN_SECONDS } from '../utils/constants.js';
import { getGuildSettings } from '../utils/get-guild-settings.js';
import Config from './config.js';
import KeyValueCacheProvider from './key-value-cache.js';
import {ONE_HOUR_IN_SECONDS} from '../utils/constants.js';
import { MediaSource, SongMetadata, STATUS } from './player.js';

@injectable()
export default class AddQueryToQueue {
Expand Down Expand Up @@ -106,6 +106,7 @@ export default class AddQueryToQueue {
if (skipCurrentTrack) {
try {
await player.forward(1);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (_: unknown) {
throw new Error('no song to skip to');
}
Expand Down
Loading
Loading