Merge pull request #8 from keanuplayz/music

This commit is contained in:
Keanu Timmermans 2020-10-24 10:27:20 +02:00 committed by GitHub
commit 67d0e6ce4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 1684 additions and 1532 deletions

130
docs/MusicStructure.md Normal file
View File

@ -0,0 +1,130 @@
# The commands
```lang-none
- "mhelp" - Display a help embed.
- "play" - Adds a song to the queue and plays it.
- "skip" - Skips the currently playing track.
- "queue" - Shows the current queue.
- "stop" - Stops currently playing media and leaves the voice channel.
- "np" - Displays the currently playing track.
- "pause" - Pauses the currently playing track.
- "resume" - Resumes the currently paused track.
- "volume" - Changes the global volume of the bot.
- "loop" - Loops the current queue.
- "seek" - Seeks through the queue.
```
---
Now that the actual info about the functionality of this thing is out of the way, its storytime!
## The music structure
Originally, I, keanucode, aimed to port the music structure of TravBot-v2 to this version.
This would have been much too difficult of a task for three main reasons:
1. The original code is written badly.
2. The original code is written by *another person*.
3. The original code is written in JS.
These three reasons make porting the structure *considerably* harder.
So, of course, I resorted to different matters. I present: [discord.js-lavalink-musicbot](https://github.com/BluSpring/discord.js-lavalink-musicbot). ([npmjs.org](https://www.npmjs.com/package/discord.js-lavalink-musicbot))
This *pre-built* module utilises [Lavalink](https://github.com/Frederikam/Lavalink), which is an audio sending node based on [Lavaplayer](https://github.com/sedmelluq/lavaplayer) and [JDA-Audio](https://github.com/DV8FromTheWorld/JDA-Audio).
I've previously considered using Lavalink, but it turned out to be more difficult for me to implement than I thought.
So, I tried again with `discord.js-lavalink-musicbot`.
*ahem*...
**The library was written in such a way that it didn't work!**
---
## Fixing the broken library
First off; in the library's interface `LavaLinkNodeOptions`, option `id` was a *required* option:
```ts
interface LavalinkNodeOptions {
host: string;
id: string;
/* ... */
}
```
Here's the catch. `id` was referenced *nowhere* in the library code.
It was *literally* useless.
So, I lazily removed that by adding a `?` to the parameter. (`id?:`)
Next up:
```ts
declare function LavalinkMusic(client: Client, options: MusicbotOptions) {}
```
First up, the TS compiler reports that: `An implementation cannot be declared in ambient contexts. ts(1183)`
Secondly, this function, which makes up the entirety of the library, explicitly returns an `any` type. As you can see, the *declared* function returns... no specific type.
So, that had to be changed to:
```diff
- declare function LavalinkMusic(client: Client, options: MusicbotOptions) {}
+ declare function LavalinkMusic(client: Client, options: MusicbotOptions): any
```
...next up:
```ts
try {
const res = await axios.get(
/* ... */
`https://${music.lavalink.restnode.host}:`
/* ... */
)
```
The library tries to fetch the URL of the Lavalink node. With *HTTPS*.
I think you can see where this is going. An SSL error.
Changed the `https` to `http`, and all is well.
I republished the library under the name "[discord.js-lavalink-lib](https://npmjs.org/package/discord.js-lavalink-lib)" so I can easily install the non-broken version.
---
## Implementing the functionality
There's nothing much to do there, honestly. Only one edit to the original snippet has to be made.
The original example snippet has the following:
```ts
const Discord = require('discord.js');
const client = new Discord.Client();
client.music = new (require('discord.js-lavalink-musicbot'))(client, {
/* ...config... */
});
```
As you can see, this is... kind of disgusting. And on top of that, incompatible with TS.
So, we have to change a few things. First off, since TS is strict, it'll tell you that `music` doesn't exist on `client`. Which is true. The `Client` class has no `music` property.
So, we make `client.` an `any` type using keyword `as`:
```ts
const Discord = require('discord.js');
const client = new Discord.Client();
(client as any).music = LavalinkMusic(client, {
/* ...config... */
});
```
And that's about it. Launch up Lavalink, and start the bot.

2982
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +1,41 @@
{
"name": "d.js-v12-bot",
"version": "0.0.1",
"description": "A Discord bot built on Discord.JS v12",
"main": "dist/index.js",
"private": true,
"dependencies": {
"chalk": "^4.1.0",
"discord.js": "^12.4.0",
"discord.js-lavalink-lib": "^0.1.7",
"inquirer": "^7.3.3",
"moment": "^2.29.1",
"ms": "^2.1.2",
"os": "^0.1.1"
},
"devDependencies": {
"@types/inquirer": "^6.5.0",
"@types/mocha": "^8.0.3",
"@types/ms": "^0.7.31",
"@types/node": "^14.14.2",
"@types/ws": "^7.2.7",
"mocha": "^8.2.0",
"prettier": "2.1.2",
"ts-node": "^9.0.0",
"tsc-watch": "^4.2.9",
"typescript": "^3.9.7"
},
"scripts": {
"build": "tsc && npm prune --production",
"start": "node dist/index.js",
"once": "tsc && npm start",
"dev": "tsc-watch --onSuccess \"node dist/index.js dev\"",
"test": "mocha --require ts-node/register --extension ts --recursive"
},
"keywords": [
"discord.js",
"bot"
],
"author": "Keanu Timmermans",
"license": "MIT"
}
{
"name": "d.js-v12-bot",
"version": "0.0.1",
"description": "A Discord bot built on Discord.JS v12",
"main": "dist/index.js",
"private": true,
"dependencies": {
"chalk": "^4.1.0",
"discord.js": "^12.4.0",
"discord.js-lavalink-lib": "^0.1.7",
"inquirer": "^7.3.3",
"moment": "^2.29.1",
"ms": "^2.1.2",
"os": "^0.1.1"
},
"devDependencies": {
"@types/inquirer": "^6.5.0",
"@types/mocha": "^8.0.3",
"@types/ms": "^0.7.31",
"@types/node": "^14.14.2",
"@types/ws": "^7.2.7",
"mocha": "^8.2.0",
"prettier": "2.1.2",
"ts-node": "^9.0.0",
"tsc-watch": "^4.2.9",
"typescript": "^3.9.7"
},
"scripts": {
"build": "tsc && npm prune --production",
"start": "node dist/index.js",
"once": "tsc && npm start",
"dev": "tsc-watch --onSuccess \"node dist/index.js dev\"",
"test": "mocha --require ts-node/register --extension ts --recursive"
},
"keywords": [
"discord.js",
"bot"
],
"author": "Keanu Timmermans",
"license": "MIT"
}

View File

@ -3,11 +3,33 @@ import setup from './setup';
import { Config } from './core/structures';
import { loadCommands } from './core/command';
import { loadEvents } from './core/event';
import 'discord.js-lavalink-lib';
import LavalinkMusic from 'discord.js-lavalink-lib';
// This is here in order to make it much less of a headache to access the client from other files.
// This of course won't actually do anything until the setup process is complete and it logs in.
export const client = new Client();
(client as any).music = LavalinkMusic(client, {
lavalink: {
restnode: {
host: 'localhost',
port: 2333,
password: 'youshallnotpass',
},
nodes: [
{
host: 'localhost',
port: 2333,
password: 'youshallnotpass',
},
],
},
prefix: '!!',
helpCmd: 'mhelp',
admins: ['717352467280691331'],
});
// Begin the command loading here rather than when it's needed like in the message event.
setup.init().then(() => {
loadCommands();