poru 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitpod.yml +0 -2
- package/README.md +34 -30
- package/SECURITY.md +21 -0
- package/index.js +11 -15
- package/package.json +5 -4
- package/src/Node.js +175 -171
- package/src/Player.js +297 -298
- package/src/Poru.js +276 -280
- package/src/config.js +18 -19
- package/src/guild/Filter.js +182 -179
- package/src/guild/PoruTrack.js +27 -21
- package/src/guild/Queue.js +31 -33
- package/src/guild/Response.js +7 -7
- package/src/guild/Track.js +29 -21
- package/src/platform/AppleMusic.js +79 -101
- package/src/platform/Deezer.js +68 -82
- package/src/platform/Spotify.js +104 -68
- package/typings/index.d.ts +0 -159
package/README.md
CHANGED
|
@@ -50,73 +50,77 @@ To use you need a configured [Lavalink](https://github.com/Frederikam/Lavalink)
|
|
|
50
50
|
## Example usage basic bot
|
|
51
51
|
|
|
52
52
|
```javascript
|
|
53
|
-
const { Client, GatewayIntentBits } = require(
|
|
54
|
-
const { Poru } = require(
|
|
53
|
+
const { Client, GatewayIntentBits } = require("discord.js");
|
|
54
|
+
const { Poru } = require("poru");
|
|
55
55
|
const nodes = [
|
|
56
56
|
{
|
|
57
57
|
id: "main_node",
|
|
58
58
|
hostname: "localhost",
|
|
59
59
|
port: 8080,
|
|
60
|
-
password: "iloveyou3000"
|
|
61
|
-
}
|
|
62
|
-
]
|
|
60
|
+
password: "iloveyou3000",
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
63
|
const PoruOptions = {
|
|
64
64
|
reconnectTime: 0,
|
|
65
|
-
resumeKey:
|
|
65
|
+
resumeKey: "MyPlayers",
|
|
66
66
|
resumeTimeout: 60,
|
|
67
|
-
defaultPlatform: "ytsearch"
|
|
68
|
-
}
|
|
67
|
+
defaultPlatform: "ytsearch",
|
|
68
|
+
};
|
|
69
69
|
const client = new Client({
|
|
70
70
|
intents: [
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
]
|
|
71
|
+
GatewayIntentBits.Guilds,
|
|
72
|
+
GatewayIntentBits.GuildMessages,
|
|
73
|
+
GatewayIntentBits.GuildVoiceStates,
|
|
74
|
+
GatewayIntentBits.MessageContent,
|
|
75
|
+
],
|
|
76
76
|
});
|
|
77
|
-
client.poru = new Poru(client, nodes, PoruOptions)
|
|
77
|
+
client.poru = new Poru(client, nodes, PoruOptions);
|
|
78
78
|
|
|
79
|
-
client.poru.on(
|
|
79
|
+
client.poru.on("trackStart", (player, track) => {
|
|
80
80
|
const channel = client.channels.cache.get(player.textChannel);
|
|
81
81
|
return channel.send(`Now playing \`${track.title}\``);
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
client.on(
|
|
85
|
-
console.log(
|
|
84
|
+
client.on("ready", () => {
|
|
85
|
+
console.log("Ready!");
|
|
86
86
|
client.poru.init(client);
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
client.on('interactionCreate', async (interaction) => {
|
|
89
|
+
client.on("interactionCreate", async (interaction) => {
|
|
91
90
|
if (!interaction.isChatInputCommand()) return;
|
|
92
|
-
if (!interaction.member.voice.channel)
|
|
91
|
+
if (!interaction.member.voice.channel)
|
|
92
|
+
return interaction.reply({
|
|
93
|
+
content: `Please connect with voice channel `,
|
|
94
|
+
ephemeral: true,
|
|
95
|
+
});
|
|
93
96
|
|
|
94
|
-
const track = interaction.options.getString(
|
|
97
|
+
const track = interaction.options.getString("track");
|
|
95
98
|
|
|
96
99
|
const res = await client.poru.resolve(track);
|
|
97
100
|
|
|
98
101
|
if (res.loadType === "LOAD_FAILED") {
|
|
99
|
-
return interaction.reply(
|
|
102
|
+
return interaction.reply("Failed to load track.");
|
|
100
103
|
} else if (res.loadType === "NO_MATCHES") {
|
|
101
|
-
return interaction.reply(
|
|
104
|
+
return interaction.reply("No source found!");
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
//create connection with discord voice channnel
|
|
107
|
+
//create connection with discord voice channnel
|
|
105
108
|
const player = client.poru.createConnection({
|
|
106
109
|
guildId: interaction.guild.id,
|
|
107
110
|
voiceChannel: interaction.member.voice.channelId,
|
|
108
111
|
textChannel: interaction.channel.id,
|
|
109
|
-
selfDeaf: true
|
|
112
|
+
selfDeaf: true,
|
|
110
113
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (res.loadType === 'PLAYLIST_LOADED') {
|
|
114
|
+
|
|
115
|
+
if (res.loadType === "PLAYLIST_LOADED") {
|
|
114
116
|
for (const track of res.tracks) {
|
|
115
117
|
track.info.requester = interaction.user;
|
|
116
118
|
player.queue.add(track);
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
interaction.reply(
|
|
121
|
+
interaction.reply(
|
|
122
|
+
`${res.playlistInfo.name} has been loaded with ${res.tracks.length}`
|
|
123
|
+
);
|
|
120
124
|
} else {
|
|
121
125
|
const track = res.tracks[0];
|
|
122
126
|
track.info.requester = interaction.user;
|
|
@@ -127,7 +131,7 @@ client.on('interactionCreate', async (interaction) => {
|
|
|
127
131
|
if (!player.isPlaying && player.isConnected) player.play();
|
|
128
132
|
});
|
|
129
133
|
|
|
130
|
-
client.login(
|
|
134
|
+
client.login("TOKEN");
|
|
131
135
|
```
|
|
132
136
|
|
|
133
137
|
## Need Help?
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
Use this section to tell people about which versions of your project are
|
|
6
|
+
currently being supported with security updates.
|
|
7
|
+
|
|
8
|
+
| Version | Supported |
|
|
9
|
+
| ------- | ------------------ |
|
|
10
|
+
| 5.1.x | :white_check_mark: |
|
|
11
|
+
| 5.0.x | :x: |
|
|
12
|
+
| 4.0.x | :white_check_mark: |
|
|
13
|
+
| < 4.0 | :x: |
|
|
14
|
+
|
|
15
|
+
## Reporting a Vulnerability
|
|
16
|
+
|
|
17
|
+
Use this section to tell people how to report a vulnerability.
|
|
18
|
+
|
|
19
|
+
Tell them where to go, how often they can expect to get an update on a
|
|
20
|
+
reported vulnerability, what to expect if the vulnerability is accepted or
|
|
21
|
+
declined, etc.
|
package/index.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
|
|
2
1
|
module.exports = {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
2
|
+
Node: require("./src/Node"),
|
|
3
|
+
Player: require("./src/Player"),
|
|
4
|
+
Poru: require("./src/Poru"),
|
|
5
|
+
Spotify: require("./src/platform/Spotify"),
|
|
6
|
+
Deezer: require("./src/platform/Deezer"),
|
|
7
|
+
AppleMusic: require("./src/platform/AppleMusic"),
|
|
8
|
+
Queue: require("./src/guild/Queue"),
|
|
9
|
+
Filter: require("./src/guild/Filter"),
|
|
10
|
+
Track: require("./src/guild/Track"),
|
|
11
|
+
PoruTrack: require("./src/guild/PoruTrack"),
|
|
12
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poru",
|
|
3
|
-
"version": "3.0
|
|
4
|
-
"description": "A stable and
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "A stable and powerfull lavalink client around node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"ws": "^8.8.0"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
"node": ">=16.9.0"
|
|
25
|
+
},
|
|
26
26
|
"keywords": [
|
|
27
27
|
"music",
|
|
28
28
|
"lavalink",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"spotify",
|
|
32
32
|
"apple-music",
|
|
33
33
|
"soundcloud",
|
|
34
|
+
"deezer",
|
|
34
35
|
"discordjs",
|
|
35
36
|
"eris"
|
|
36
37
|
]
|
package/src/Node.js
CHANGED
|
@@ -1,188 +1,192 @@
|
|
|
1
1
|
const WebSocket = require("ws");
|
|
2
|
-
const config = require("./config")
|
|
2
|
+
const config = require("./config");
|
|
3
3
|
|
|
4
4
|
class Node {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
5
|
+
constructor(manager, options, node) {
|
|
6
|
+
this.manager = manager;
|
|
7
|
+
this.name = options.name || null;
|
|
8
|
+
this.host = options.host || "localhost";
|
|
9
|
+
this.port = options.port || 2333;
|
|
10
|
+
this.password = options.password || "youshallnotpass";
|
|
11
|
+
this.secure = options.secure || false;
|
|
12
|
+
this.url = `${this.secure ? "wss" : "ws"}://${this.host}:${this.port}/`;
|
|
13
|
+
this.ws = null;
|
|
14
|
+
this.reconnectTime = node.reconnectTime || 5000;
|
|
15
|
+
this.resumeKey = node.resumeKey || null;
|
|
16
|
+
this.resumeTimeout = node.resumeTimeout || 60;
|
|
17
|
+
this.reconnectAttempt;
|
|
18
|
+
this.reconnects = 0;
|
|
19
|
+
this.isConnected = false;
|
|
20
|
+
this.destroyed = null;
|
|
21
|
+
this.stats = {
|
|
22
|
+
players: 0,
|
|
23
|
+
playingPlayers: 0,
|
|
24
|
+
uptime: 0,
|
|
25
|
+
memory: {
|
|
26
|
+
free: 0,
|
|
27
|
+
used: 0,
|
|
28
|
+
allocated: 0,
|
|
29
|
+
reservable: 0,
|
|
30
|
+
},
|
|
31
|
+
cpu: {
|
|
32
|
+
cores: 0,
|
|
33
|
+
systemLoad: 0,
|
|
34
|
+
lavalinkLoad: 0,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
connect() {
|
|
40
|
+
if (this.ws) this.ws.close();
|
|
41
|
+
const headers = {
|
|
42
|
+
Authorization: this.password,
|
|
43
|
+
"Num-Shards": this.manager.shards || 1,
|
|
44
|
+
"User-Id": this.manager.user,
|
|
45
|
+
"Client-Name": config.clientName,
|
|
46
|
+
};
|
|
47
|
+
if (this.resumeKey) headers["Resume-Key"] = this.resumeKey;
|
|
48
|
+
this.ws = new WebSocket(this.url, { headers });
|
|
49
|
+
this.ws.on("open", this.#open.bind(this));
|
|
50
|
+
this.ws.on("error", this.#error.bind(this));
|
|
51
|
+
this.ws.on("message", this.#message.bind(this));
|
|
52
|
+
this.ws.on("close", this.#close.bind(this));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
disconnect() {
|
|
56
|
+
if (!this.isConnected) return;
|
|
57
|
+
|
|
58
|
+
this.ws?.removeAllListeners();
|
|
59
|
+
this.ws?.close();
|
|
60
|
+
this.ws = null;
|
|
61
|
+
this.isConnected = false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#open() {
|
|
65
|
+
if (this.reconnectAttempt) {
|
|
66
|
+
clearTimeout(this.reconnectAttempt);
|
|
67
|
+
delete this.reconnectAttempt;
|
|
56
68
|
}
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
if (this.resumeKey) {
|
|
71
|
+
this.send({
|
|
72
|
+
op: "configureResuming",
|
|
73
|
+
key: this.resumeKey.toString(),
|
|
74
|
+
timeout: this.resumeTimeout,
|
|
75
|
+
});
|
|
76
|
+
this.manager.emit(
|
|
77
|
+
"debug",
|
|
78
|
+
this.name,
|
|
79
|
+
`[Web Socket] Resuming configured on Lavalink`
|
|
80
|
+
);
|
|
67
81
|
}
|
|
68
82
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
});
|
|
82
|
-
this.manager.emit("debug",this.name,`[Web Socket] Resuming configured on Lavalink`)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
this.manager.emit("nodeConnect", this);
|
|
86
|
-
this.isConnected = true;
|
|
87
|
-
this.manager.emit('debug', this.name, `[Web Socket] Connection ready ${this.url}`);
|
|
88
|
-
|
|
89
|
-
if(config.autoResume){
|
|
90
|
-
|
|
91
|
-
for (const player of this.manager.players.values()) {
|
|
92
|
-
if (player.node === this) {
|
|
93
|
-
player.restart();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
83
|
+
this.manager.emit("nodeConnect", this);
|
|
84
|
+
this.isConnected = true;
|
|
85
|
+
this.manager.emit(
|
|
86
|
+
"debug",
|
|
87
|
+
this.name,
|
|
88
|
+
`[Web Socket] Connection ready ${this.url}`
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
if (config.autoResume) {
|
|
92
|
+
for (const player of this.manager.players.values()) {
|
|
93
|
+
if (player.node === this) {
|
|
94
|
+
player.restart();
|
|
102
95
|
}
|
|
103
|
-
|
|
96
|
+
}
|
|
104
97
|
}
|
|
98
|
+
}
|
|
105
99
|
|
|
106
|
-
|
|
100
|
+
#message(payload) {
|
|
101
|
+
const packet = JSON.parse(payload);
|
|
102
|
+
if (!packet.op) return;
|
|
107
103
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (packet.op && packet.op === "stats") {
|
|
112
|
-
this.stats = { ...packet };
|
|
113
|
-
}
|
|
114
|
-
const player = this.manager.players.get(packet.guildId);
|
|
115
|
-
if (packet.guildId && player) player.emit(packet.op, packet);
|
|
116
|
-
packet.node = this;
|
|
117
|
-
this.manager.emit("debug",this.name,`[Web Socket] Lavalink Node Update : ${packet.op} `)
|
|
118
|
-
this.manager.emit("raw", packet);
|
|
104
|
+
if (packet.op && packet.op === "stats") {
|
|
105
|
+
this.stats = { ...packet };
|
|
119
106
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
107
|
+
const player = this.manager.players.get(packet.guildId);
|
|
108
|
+
if (packet.guildId && player) player.emit(packet.op, packet);
|
|
109
|
+
packet.node = this;
|
|
110
|
+
this.manager.emit(
|
|
111
|
+
"debug",
|
|
112
|
+
this.name,
|
|
113
|
+
`[Web Socket] Lavalink Node Update : ${packet.op} `
|
|
114
|
+
);
|
|
115
|
+
this.manager.emit("raw", packet);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#close(event) {
|
|
119
|
+
this.disconnect();
|
|
120
|
+
this.manager.emit("nodeDisconnect", this, event);
|
|
121
|
+
this.manager.emit(
|
|
122
|
+
"debug",
|
|
123
|
+
this.name,
|
|
124
|
+
`[Web Socket] Connection with Lavalink closed with Error code : ${
|
|
125
|
+
event || "Unknown code"
|
|
126
|
+
}`
|
|
127
|
+
);
|
|
128
|
+
if (event !== 1000) {
|
|
137
129
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#error(event) {
|
|
133
|
+
if (!event) return "Unknown event";
|
|
134
|
+
|
|
135
|
+
this.manager.emit(
|
|
136
|
+
"debug",
|
|
137
|
+
this.name,
|
|
138
|
+
`[Web Socket] Connection for Lavalink node has error code: ${event.code}`
|
|
139
|
+
);
|
|
140
|
+
this.manager.emit("nodeError", this, event);
|
|
141
|
+
return this.reconnect();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
destroy() {
|
|
145
|
+
if (!this.isConnected) return;
|
|
146
|
+
|
|
147
|
+
const players = this.manager.players.filter((p) => p.node == this);
|
|
148
|
+
if (players.size) players.forEach((p) => p.destroy());
|
|
149
|
+
this.ws.close(1000, "destroy");
|
|
150
|
+
this.ws.removeAllListeners();
|
|
151
|
+
this.ws = null;
|
|
152
|
+
this.reconnect = 1;
|
|
153
|
+
this.destroyed = true;
|
|
154
|
+
this.manager.nodes.delete(this.host);
|
|
155
|
+
this.manager.emit("nodeDestroy", this);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
reconnect() {
|
|
159
|
+
this.reconnectAttempt = setTimeout(() => {
|
|
160
|
+
this.isConnected = false;
|
|
161
|
+
this.ws.removeAllListeners();
|
|
162
|
+
this.ws = null;
|
|
163
|
+
this.manager.emit("nodeReconnect", this);
|
|
164
|
+
this.connect();
|
|
165
|
+
}, this.reconnectTime);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
send(payload) {
|
|
169
|
+
const data = JSON.stringify(payload);
|
|
170
|
+
this.ws.send(data, (error) => {
|
|
171
|
+
if (error) return error;
|
|
172
|
+
return null;
|
|
173
|
+
});
|
|
174
|
+
this.manager.emit("raw", data, this.name);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
get penalties() {
|
|
178
|
+
let penalties = 0;
|
|
179
|
+
if (!this.isConnected) return penalties;
|
|
180
|
+
penalties += this.stats.players;
|
|
181
|
+
penalties += Math.round(
|
|
182
|
+
Math.pow(1.05, 100 * this.stats.cpu.systemLoad) * 10 - 10
|
|
183
|
+
);
|
|
184
|
+
if (this.stats.frameStats) {
|
|
185
|
+
penalties += this.stats.frameStats.deficit;
|
|
186
|
+
penalties += this.stats.frameStats.nulled * 2;
|
|
184
187
|
}
|
|
188
|
+
return penalties;
|
|
189
|
+
}
|
|
185
190
|
}
|
|
186
191
|
|
|
187
192
|
module.exports = Node;
|
|
188
|
-
|