poru 1.0.9 → 1.1.2
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/README.md +1 -1
- package/package.json +1 -1
- package/src/Node.js +45 -28
- package/src/Player.js +26 -35
- package/src/Poru.js +72 -65
- package/src/guild/Queue.js +3 -16
- package/src/guild/Track.js +16 -11
- package/typings/index.d.ts +179 -0
- package/.gitpod.yml +0 -8
package/README.md
CHANGED
|
@@ -85,7 +85,7 @@ client.once("ready", () => {
|
|
|
85
85
|
console.log(`Logged in as ${client.user.tag}`);
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
//
|
|
88
|
+
// this event used to make connections upto date with lavalink
|
|
89
89
|
client.on("raw",async d => await client.poru.packetUpdate(d));
|
|
90
90
|
|
|
91
91
|
// Finally login at the END of your code
|
package/package.json
CHANGED
package/src/Node.js
CHANGED
|
@@ -2,7 +2,7 @@ const WebSocket = require("ws");
|
|
|
2
2
|
const config = require("./config.json")
|
|
3
3
|
|
|
4
4
|
class Node {
|
|
5
|
-
constructor(manager,
|
|
5
|
+
constructor(manager,options,node) {
|
|
6
6
|
|
|
7
7
|
this.manager = manager
|
|
8
8
|
this.name= options.name || null;
|
|
@@ -12,13 +12,13 @@ class Node {
|
|
|
12
12
|
this.password = options.password ||"youshallnotpass"
|
|
13
13
|
this.secure = options.secure || false;
|
|
14
14
|
this.ws = null;
|
|
15
|
-
this.reconnectTime =
|
|
16
|
-
this.resumeKey =
|
|
17
|
-
this.
|
|
15
|
+
this.reconnectTime = node.reconnectTime || 5000;
|
|
16
|
+
this.resumeKey = node.resumeKey || null;
|
|
17
|
+
this.resumeTimeout = node.resumeTimeout || 60;
|
|
18
18
|
this.reconnectAttempt;
|
|
19
19
|
this.reconnects = 0;
|
|
20
|
-
this.queue = [];
|
|
21
20
|
this.isConnected = false;
|
|
21
|
+
this.destroyed = null;
|
|
22
22
|
this.stats = {
|
|
23
23
|
players: 0,
|
|
24
24
|
playingPlayers: 0,
|
|
@@ -49,29 +49,36 @@ class Node {
|
|
|
49
49
|
};
|
|
50
50
|
if (this.resumeKey) headers["Resume-Key"] = this.resumeKey;
|
|
51
51
|
this.ws = new WebSocket(`ws${this.secure ? "s" : ""}:${this.host}:${this.port}/`, { headers });
|
|
52
|
-
this.ws.on("open",
|
|
53
|
-
this.ws.on("error", this
|
|
54
|
-
this.ws.on("message", this
|
|
55
|
-
this.ws.on("close", this
|
|
56
|
-
|
|
52
|
+
this.ws.on("open",this.#open.bind(this));
|
|
53
|
+
this.ws.on("error", this.#error.bind(this));
|
|
54
|
+
this.ws.on("message", this.#message.bind(this));
|
|
55
|
+
this.ws.on("close", this.#close.bind(this));
|
|
56
|
+
}
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
open(){
|
|
59
|
+
#open(){
|
|
60
60
|
if (this.reconnectAttempt) {
|
|
61
61
|
clearTimeout(this.reconnectAttempt);
|
|
62
62
|
delete this.reconnectAttempt;
|
|
63
|
-
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (this.resumeKey){
|
|
66
|
+
this.send({
|
|
67
|
+
op: "configureResuming",
|
|
68
|
+
key: (this.resumeKey).toString(),
|
|
69
|
+
timeout: this.resumeTimeout
|
|
70
|
+
});
|
|
71
|
+
this.manager.emit("debug",this.name,`[Web Socket] Resuming configured on Lavalink`)
|
|
72
|
+
}
|
|
64
73
|
|
|
65
|
-
this.
|
|
66
|
-
if (this.resumeKey) this.send({ op: "configureResuming", key: (this.resumeKey).toString(), timeout: this._resumeTimeout });
|
|
67
|
-
this.manager.emit("nodeConnect", this);
|
|
74
|
+
this.manager.emit("nodeConnect", this);
|
|
68
75
|
this.isConnected = true;
|
|
76
|
+
this.manager.emit('debug', this.name, `[Web Socket] Connection ready ${this.url}`);
|
|
77
|
+
|
|
69
78
|
}
|
|
70
79
|
|
|
71
|
-
message(payload) {
|
|
72
|
-
// eslint-disable-next-line no-param-reassign
|
|
80
|
+
#message(payload) {
|
|
73
81
|
if (Array.isArray(payload)) payload = Buffer.concat(payload);
|
|
74
|
-
// eslint-disable-next-line no-param-reassign
|
|
75
82
|
else if (payload instanceof ArrayBuffer) payload = Buffer.from(payload);
|
|
76
83
|
|
|
77
84
|
const packet = JSON.parse(payload);
|
|
@@ -83,14 +90,13 @@ message(payload) {
|
|
|
83
90
|
if (packet.guildId && player) player.emit(packet.op, packet);
|
|
84
91
|
|
|
85
92
|
packet.node = this;
|
|
86
|
-
|
|
87
|
-
* Fire up when raw packets / or sending raw data
|
|
88
|
-
*/
|
|
93
|
+
this.manager.emit("debug",this.name,`[Web Socket] Lavalink Node Update : ${packet.op} `)
|
|
89
94
|
this.manager.emit("raw", packet);
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
close(event) {
|
|
93
|
-
this.manager.emit("
|
|
97
|
+
#close(event) {
|
|
98
|
+
this.manager.emit("nodeDisconnect", event, this);
|
|
99
|
+
this.manager.emit("debug",this.name,`[Web Socket] Connection with Lavalink closed with Error code : ${event||"Unkwon code"}`)
|
|
94
100
|
if (event !== 1000){
|
|
95
101
|
|
|
96
102
|
return this.reconnect();
|
|
@@ -98,13 +104,10 @@ message(payload) {
|
|
|
98
104
|
}
|
|
99
105
|
|
|
100
106
|
|
|
101
|
-
error(event) {
|
|
107
|
+
#error(event) {
|
|
102
108
|
if (!event) return "Unknown event";
|
|
103
109
|
|
|
104
|
-
|
|
105
|
-
* Fire up when node return an error
|
|
106
|
-
* @event nodeError
|
|
107
|
-
*/
|
|
110
|
+
this.manager.emit("debug",this.name,`[Web Socket] Connection for Lavalink node has error code: ${event.code}`)
|
|
108
111
|
this.manager.emit("nodeError", this, event);
|
|
109
112
|
return this.reconnect();
|
|
110
113
|
}
|
|
@@ -118,6 +121,7 @@ destroy(){
|
|
|
118
121
|
this.ws.removeAllListeners();
|
|
119
122
|
this.ws = null;
|
|
120
123
|
this.reconnect = 1;
|
|
124
|
+
this.destroyed = true;
|
|
121
125
|
this.manager.nodes.delete(this.host)
|
|
122
126
|
this.manager.emit("nodeDestroy", this);
|
|
123
127
|
|
|
@@ -143,6 +147,19 @@ send(payload) {
|
|
|
143
147
|
|
|
144
148
|
|
|
145
149
|
|
|
150
|
+
get penalties(){
|
|
151
|
+
let penalties = 0;
|
|
152
|
+
if (!this.isConnected) return penalties;
|
|
153
|
+
penalties += this.stats.players;
|
|
154
|
+
penalties += Math.round(Math.pow(1.05, 100 * this.stats.cpu.systemLoad) * 10 - 10);
|
|
155
|
+
if (this.stats.frameStats) {
|
|
156
|
+
penalties += this.stats.frameStats.deficit;
|
|
157
|
+
penalties += this.stats.frameStats.nulled * 2;
|
|
158
|
+
}
|
|
159
|
+
return penalties;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
146
163
|
}
|
|
147
164
|
|
|
148
165
|
|
package/src/Player.js
CHANGED
|
@@ -2,7 +2,7 @@ const { EventEmitter } = require("events");
|
|
|
2
2
|
const Queue = require("./guild/Queue");
|
|
3
3
|
const Filters = require("./guild/Filter")
|
|
4
4
|
class Player extends EventEmitter {
|
|
5
|
-
constructor(node, options
|
|
5
|
+
constructor(manager,node, options) {
|
|
6
6
|
super();
|
|
7
7
|
|
|
8
8
|
this.manager = manager;
|
|
@@ -13,53 +13,40 @@ class Player extends EventEmitter {
|
|
|
13
13
|
|
|
14
14
|
this.filters = new Filters(this, this.node)
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
this.guild = options.guild.id || options.guild;
|
|
18
17
|
|
|
19
18
|
this.voiceChannel = options.voiceChannel.id || options.voiceChannel;
|
|
20
19
|
|
|
21
20
|
this.textChannel = options.textChannel || null;
|
|
22
21
|
|
|
23
|
-
this.state = { volume: 100, equalizer: [] };
|
|
24
|
-
|
|
25
22
|
this.isConnectd = false;
|
|
26
23
|
|
|
24
|
+
this.isPlaying = false;
|
|
25
|
+
|
|
26
|
+
this.isPause = false;
|
|
27
|
+
|
|
27
28
|
this.trackRepeat = false;
|
|
28
29
|
|
|
29
30
|
this.queueRepeat = false;
|
|
30
31
|
|
|
31
32
|
this.loop = 0;
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
this.playing = false;
|
|
35
|
-
|
|
36
|
-
this.timestamp = Date.now();
|
|
37
|
-
|
|
38
|
-
this.paused = false;
|
|
39
34
|
this.position = 0;
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
this.volume = 100;
|
|
42
37
|
|
|
43
38
|
this.currentTrack = {};
|
|
44
39
|
|
|
45
40
|
this.previousTrack = {};
|
|
46
41
|
|
|
47
|
-
|
|
48
42
|
this.voiceUpdateState = null;
|
|
49
43
|
|
|
50
44
|
|
|
51
45
|
|
|
52
46
|
this.on("event", (data) => (this.lavalinkEvent(data).bind(this))());
|
|
53
|
-
this.on("event", (data) => this.manager.emit("debug", data))
|
|
54
47
|
this.on("playerUpdate", (packet) => {
|
|
55
48
|
this.isConnectd = packet.state.connected,
|
|
56
49
|
this.position = packet.state.position
|
|
57
|
-
this.state = {
|
|
58
|
-
volume: this.state.volume,
|
|
59
|
-
equalizer: this.state.equalizer,
|
|
60
|
-
...packet.state,
|
|
61
|
-
|
|
62
|
-
};
|
|
63
50
|
this.manager.emit("playerUpdate", this, packet);
|
|
64
51
|
});
|
|
65
52
|
}
|
|
@@ -82,11 +69,11 @@ class Player extends EventEmitter {
|
|
|
82
69
|
}
|
|
83
70
|
|
|
84
71
|
|
|
85
|
-
|
|
72
|
+
stop() {
|
|
86
73
|
|
|
87
74
|
this.position = 0;
|
|
88
75
|
this.isConnectd = false
|
|
89
|
-
this.
|
|
76
|
+
this.isPlaying = false;
|
|
90
77
|
this.node.send({
|
|
91
78
|
op: "stop",
|
|
92
79
|
guildId: this.guild
|
|
@@ -102,8 +89,8 @@ class Player extends EventEmitter {
|
|
|
102
89
|
guildId: this.guild,
|
|
103
90
|
pause,
|
|
104
91
|
});
|
|
105
|
-
this.
|
|
106
|
-
this.
|
|
92
|
+
this.isPlaying = !pause;
|
|
93
|
+
this.isPause = pause;
|
|
107
94
|
|
|
108
95
|
return this;
|
|
109
96
|
}
|
|
@@ -121,7 +108,7 @@ class Player extends EventEmitter {
|
|
|
121
108
|
|
|
122
109
|
async setVolume(volume) {
|
|
123
110
|
if (Number.isNaN(volume)) throw new RangeError("Volume level must be a number.");
|
|
124
|
-
|
|
111
|
+
this.volume = volume;
|
|
125
112
|
this.node.send({
|
|
126
113
|
op: "volume",
|
|
127
114
|
guildId: this.guild,
|
|
@@ -167,12 +154,14 @@ class Player extends EventEmitter {
|
|
|
167
154
|
}
|
|
168
155
|
|
|
169
156
|
async connect(data) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
157
|
+
if (data) {
|
|
158
|
+
this.voiceUpdateState = data;
|
|
159
|
+
this.node.send({
|
|
160
|
+
op: "voiceUpdate",
|
|
161
|
+
guildId: this.guild,
|
|
162
|
+
...data,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
176
165
|
return this;
|
|
177
166
|
}
|
|
178
167
|
|
|
@@ -197,7 +186,7 @@ class Player extends EventEmitter {
|
|
|
197
186
|
if (this.voiceChannel === null) return null;
|
|
198
187
|
this.pause(true);
|
|
199
188
|
this.isConnectd = false;
|
|
200
|
-
this.manager.
|
|
189
|
+
this.manager.sendData({
|
|
201
190
|
op: 4,
|
|
202
191
|
d: {
|
|
203
192
|
guild_id: this.guild,
|
|
@@ -250,7 +239,7 @@ class Player extends EventEmitter {
|
|
|
250
239
|
lavalinkEvent(data) {
|
|
251
240
|
const events = {
|
|
252
241
|
TrackStartEvent() {
|
|
253
|
-
this.
|
|
242
|
+
this.isPlaying = true;
|
|
254
243
|
this.paused = false;
|
|
255
244
|
this.manager.emit("trackStart", this, this.currentTrack, data);
|
|
256
245
|
},
|
|
@@ -262,18 +251,20 @@ class Player extends EventEmitter {
|
|
|
262
251
|
if (this.currentTrack && this.loop === 1) {
|
|
263
252
|
|
|
264
253
|
this.queue.unshift(this.previousTrack)
|
|
254
|
+
this.manager.emit("trackEnd", this, this.currentTrack, data)
|
|
265
255
|
return this.play();
|
|
266
256
|
} else if (this.currentTrack && this.loop === 2) {
|
|
267
257
|
|
|
268
258
|
this.queue.push(this.previousTrack)
|
|
259
|
+
this.manager.emit("trackEnd", this, this.currentTrack, data)
|
|
260
|
+
|
|
269
261
|
return this.play();
|
|
270
262
|
}
|
|
271
263
|
|
|
272
264
|
if (this.queue.length === 0) {
|
|
273
265
|
return this.manager.emit("queueEnd", this, this.track, data);
|
|
274
|
-
// this.destroy();
|
|
275
266
|
} else if (this.queue.length > 0) {
|
|
276
|
-
|
|
267
|
+
this.manager.emit("trackEnd", this, this.currentTrack, data)
|
|
277
268
|
return this.play();
|
|
278
269
|
}
|
|
279
270
|
this.manager.emit("queueEnd", this, this.track, data);
|
|
@@ -293,7 +284,7 @@ class Player extends EventEmitter {
|
|
|
293
284
|
},
|
|
294
285
|
WebSocketClosedEvent() {
|
|
295
286
|
if ([4015, 4009].includes(data.code)) {
|
|
296
|
-
this.manager.
|
|
287
|
+
this.manager.sendData({
|
|
297
288
|
op: 4,
|
|
298
289
|
d: {
|
|
299
290
|
guild_id: data.guildId,
|
package/src/Poru.js
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
1
|
const { EventEmitter } = require("events");
|
|
2
2
|
const fetch = (...args) => import('node-fetch').then(({
|
|
3
3
|
default: fetch
|
|
4
|
-
}) => fetch(...args));
|
|
4
|
+
}) => fetch(...args));
|
|
5
|
+
const Player = require("./Player");
|
|
5
6
|
const Node = require("./Node");
|
|
6
7
|
const Response = require("./guild/Response");
|
|
8
|
+
const config = require("./config.json")
|
|
7
9
|
|
|
8
10
|
class Poru extends EventEmitter {
|
|
9
11
|
constructor(client, nodes, options = {}) {
|
|
10
12
|
super();
|
|
11
13
|
if (!client) throw new Error("[Poru Error] you did't provide a valid client");
|
|
12
14
|
if (!nodes) throw new Error("[Poru Error] you did't provide a lavalink nodes");
|
|
13
|
-
|
|
15
|
+
if(!options) throw new Error("[Poru Error] options must be provided!")
|
|
14
16
|
this.client = client;
|
|
15
|
-
this.player = options.player || Player;
|
|
16
17
|
this._nodes = nodes;
|
|
17
18
|
this.nodes = new Map();
|
|
18
19
|
this.players = new Map();
|
|
19
20
|
this.voiceStates = new Map();
|
|
20
21
|
this.voiceServers = new Map();
|
|
21
22
|
this.user = null;
|
|
23
|
+
this.options = options
|
|
22
24
|
this.shards = options.shards || 1;
|
|
23
|
-
this.
|
|
25
|
+
this.sendData = null;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
//create a node and connect it with lavalink
|
|
29
|
-
|
|
30
|
-
const node = new Node(this, options);
|
|
31
|
+
addNode(options) {
|
|
32
|
+
const node = new Node(this, options,this.options);
|
|
31
33
|
if (options.name) {
|
|
32
34
|
this.nodes.set(options.name || options.host, node);
|
|
33
35
|
node.connect();
|
|
@@ -38,83 +40,100 @@ class Poru extends EventEmitter {
|
|
|
38
40
|
return node;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
//remove node and destroy web socket connection
|
|
44
|
+
removeNode(identifier){
|
|
42
45
|
const node = this.nodes.get(identifier);
|
|
43
46
|
if (!node) return;
|
|
44
47
|
node.destroy();
|
|
45
48
|
this.nodes.delete(identifier)
|
|
46
49
|
}
|
|
47
50
|
//create connection with discord voice channel
|
|
48
|
-
createConnection(data = {}
|
|
51
|
+
createConnection(data = {}) {
|
|
49
52
|
const player = this.players.get(data.guild.id || data.guild);
|
|
50
53
|
if (player){
|
|
51
54
|
return player;
|
|
52
55
|
}
|
|
53
|
-
this.
|
|
56
|
+
this.sendData({
|
|
54
57
|
op: 4,
|
|
55
58
|
d: {
|
|
56
59
|
guild_id: data.guild.id || data.guild,
|
|
57
60
|
channel_id: data.voiceChannel.id || data.voiceChannel,
|
|
58
|
-
self_mute:
|
|
59
|
-
self_deaf:
|
|
61
|
+
self_mute: data.selfMute || false,
|
|
62
|
+
self_deaf: data.selfDeaf || true,
|
|
60
63
|
},
|
|
61
64
|
});
|
|
62
|
-
return this
|
|
65
|
+
return this.#Player(data);
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
|
|
66
69
|
|
|
67
70
|
init(client) {
|
|
68
71
|
|
|
69
|
-
this.user =client.user.id;
|
|
70
|
-
this.
|
|
72
|
+
this.user = client.user.id;
|
|
73
|
+
this.sendData = (data) => {
|
|
71
74
|
const guild = client.guilds.cache.get(data.d.guild_id);
|
|
72
75
|
if (guild) guild.shard.send(data);
|
|
73
76
|
}
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
client.on("raw",async packet =>{
|
|
78
|
+
await this.#packetUpdate(packet);
|
|
79
|
+
})
|
|
80
|
+
this._nodes.forEach((node) => this.addNode(node));
|
|
76
81
|
console.log(`Thanks for using Poru`)
|
|
77
82
|
}
|
|
78
83
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
setServersUpdate(data) {
|
|
85
|
+
let guild = data.guild_id
|
|
86
|
+
this.voiceServers.set(guild, data);
|
|
87
|
+
const server = this.voiceServers.get(guild);
|
|
88
|
+
const state = this.voiceStates.get(guild);
|
|
89
|
+
if (!server) return false;
|
|
90
|
+
const player = this.players.get(guild);
|
|
91
|
+
if (!player) return false;
|
|
92
|
+
|
|
93
|
+
player.connect({
|
|
94
|
+
sessionId: state ? state.session_id : player.voiceUpdateState.sessionId,
|
|
95
|
+
event: server,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
83
100
|
|
|
84
|
-
|
|
101
|
+
setStateUpdate(data) {
|
|
85
102
|
if (data.user_id !== this.user) return;
|
|
86
103
|
if (data.channel_id) {
|
|
104
|
+
const guild = data.guild_id;
|
|
105
|
+
|
|
87
106
|
this.voiceStates.set(data.guild_id, data);
|
|
88
|
-
|
|
89
|
-
|
|
107
|
+
const server = this.voiceServers.get(guild);
|
|
108
|
+
const state = this.voiceStates.get(guild);
|
|
109
|
+
if (!server) return false;
|
|
110
|
+
const player = this.players.get(guild);
|
|
111
|
+
if (!player) return false;
|
|
112
|
+
|
|
113
|
+
player.connect({
|
|
114
|
+
sessionId: state ? state.session_id : player.voiceUpdateState.sessionId,
|
|
115
|
+
event: server,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return true;
|
|
90
119
|
}
|
|
91
120
|
this.voiceServers.delete(data.guild_id);
|
|
92
121
|
this.voiceStates.delete(data.guild_id);
|
|
93
122
|
}
|
|
94
123
|
|
|
95
|
-
packetUpdate(packet) {
|
|
124
|
+
#packetUpdate(packet) {
|
|
125
|
+
if (!['VOICE_STATE_UPDATE', 'VOICE_SERVER_UPDATE'].includes(packet.t)) return;
|
|
126
|
+
const player = this.players.get(packet.d.guild_id);
|
|
127
|
+
if (!player) return;
|
|
128
|
+
|
|
96
129
|
if (packet.t === "VOICE_SERVER_UPDATE"){
|
|
97
|
-
|
|
130
|
+
this.setServersUpdate(packet.d);
|
|
98
131
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
this.voiceStateUpdate(packet.d);
|
|
132
|
+
if (packet.t === "VOICE_STATE_UPDATE"){
|
|
133
|
+
this.setStateUpdate(packet.d);
|
|
102
134
|
}
|
|
103
135
|
}
|
|
104
136
|
|
|
105
|
-
connectionProcess(guildId) {
|
|
106
|
-
const server = this.voiceServers.get(guildId);
|
|
107
|
-
const state = this.voiceStates.get(guildId);
|
|
108
|
-
if (!server) return false;
|
|
109
|
-
const player = this.players.get(guildId);
|
|
110
|
-
if (!player) return false;
|
|
111
|
-
|
|
112
|
-
player.connect({
|
|
113
|
-
sessionId: state ? state.session_id : player.voiceUpdateState.sessionId,
|
|
114
|
-
event: server,
|
|
115
|
-
});
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
137
|
|
|
119
138
|
|
|
120
139
|
get leastUsedNodes() {
|
|
@@ -127,7 +146,7 @@ class Poru extends EventEmitter {
|
|
|
127
146
|
});
|
|
128
147
|
}
|
|
129
148
|
|
|
130
|
-
Player(data) {
|
|
149
|
+
#Player(data) {
|
|
131
150
|
const guild = data.guild.id || data.guild;
|
|
132
151
|
const Nodes = this.nodes.get(guild);
|
|
133
152
|
if (Nodes) return Nodes;
|
|
@@ -137,25 +156,13 @@ class Poru extends EventEmitter {
|
|
|
137
156
|
if (!node) throw new Error("[Poru Error] No nodes are avalible");
|
|
138
157
|
|
|
139
158
|
// eslint-disable-next-line new-cap
|
|
140
|
-
const player = new this
|
|
159
|
+
const player = new Player(this,node, data);
|
|
141
160
|
this.players.set(guild, player);
|
|
142
|
-
|
|
161
|
+
player.connect()
|
|
143
162
|
return player;
|
|
144
163
|
}
|
|
145
164
|
|
|
146
|
-
|
|
147
|
-
const node = this.leastUsedNodes[0];
|
|
148
|
-
if (!node) throw new Error("No nodes are available.");
|
|
149
|
-
const regex = /^https?:\/\//;
|
|
150
|
-
if (!regex.test(track)) {
|
|
151
|
-
// eslint-disable-next-line no-param-reassign
|
|
152
|
-
track = `${source || "yt"}search:${track}`;
|
|
153
|
-
}
|
|
154
|
-
const result = await this.request(node, "loadtracks", `identifier=${encodeURIComponent(track)}`);
|
|
155
|
-
// this.emit("error", result);
|
|
156
|
-
if (!result) throw new Error("No tracks found.");
|
|
157
|
-
return new Response(result);
|
|
158
|
-
}
|
|
165
|
+
|
|
159
166
|
|
|
160
167
|
|
|
161
168
|
async resolve(track, source) {
|
|
@@ -166,9 +173,9 @@ class Poru extends EventEmitter {
|
|
|
166
173
|
// eslint-disable-next-line no-param-reassign
|
|
167
174
|
track = `${source || "yt"}search:${track}`;
|
|
168
175
|
}
|
|
169
|
-
const result = await this
|
|
170
|
-
|
|
171
|
-
if (!result) throw new Error("No tracks found.");
|
|
176
|
+
const result = await this.#fetch(node, "loadtracks", `identifier=${encodeURIComponent(track)}`);
|
|
177
|
+
|
|
178
|
+
if (!result) throw new Error("[Poru Error] No tracks found.");
|
|
172
179
|
return new Response(result);
|
|
173
180
|
}
|
|
174
181
|
|
|
@@ -176,21 +183,21 @@ class Poru extends EventEmitter {
|
|
|
176
183
|
async decodeTrack(track) {
|
|
177
184
|
const node = this.leastUsedNodes[0];
|
|
178
185
|
if (!node) throw new Error("No nodes are available.");
|
|
179
|
-
const result = await this
|
|
180
|
-
this.emit("error", result);
|
|
186
|
+
const result = await this.#fetch(node, "decodetrack", `track=${track}`);
|
|
181
187
|
if (result.status === 500) return null;
|
|
182
188
|
return result;
|
|
183
189
|
}
|
|
184
190
|
|
|
185
|
-
|
|
191
|
+
#fetch(node, endpoint, param) {
|
|
186
192
|
return fetch(`http${node.secure ? "s" : ""}://${node.host}:${node.port}/${endpoint}?${param}`, {
|
|
187
193
|
headers: {
|
|
188
194
|
Authorization: node.password,
|
|
195
|
+
|
|
189
196
|
},
|
|
190
197
|
})
|
|
191
198
|
.then((r) => r.json())
|
|
192
199
|
.catch((e) => {
|
|
193
|
-
throw new Error(`[Poru Error] Failed to
|
|
200
|
+
throw new Error(`[Poru Error] Failed to fetch from the lavalink.\n error: ${e}`);
|
|
194
201
|
});
|
|
195
202
|
}
|
|
196
203
|
|
|
@@ -199,4 +206,4 @@ class Poru extends EventEmitter {
|
|
|
199
206
|
}
|
|
200
207
|
}
|
|
201
208
|
|
|
202
|
-
module.exports = Poru
|
|
209
|
+
module.exports = Poru
|
package/src/guild/Queue.js
CHANGED
|
@@ -2,21 +2,11 @@ class Queue extends Array{
|
|
|
2
2
|
constructor() {
|
|
3
3
|
super(...arguments);
|
|
4
4
|
}
|
|
5
|
-
|
|
6
|
-
return this.reduce((acc, val) => acc + val.info.length, 0);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
get totalSize() {
|
|
10
|
-
return this.length + (this.current ? 1 : 0);
|
|
11
|
-
}
|
|
12
|
-
|
|
5
|
+
|
|
13
6
|
get size() {
|
|
14
7
|
return this.length
|
|
15
8
|
}
|
|
16
9
|
|
|
17
|
-
get empty() {
|
|
18
|
-
return this.length / 2 < 1;
|
|
19
|
-
}
|
|
20
10
|
|
|
21
11
|
first() {
|
|
22
12
|
return this ? this[0] : 0;
|
|
@@ -27,10 +17,7 @@ class Queue extends Array{
|
|
|
27
17
|
return this;
|
|
28
18
|
}
|
|
29
19
|
|
|
30
|
-
|
|
31
|
-
return this.shift();
|
|
32
|
-
}
|
|
33
|
-
|
|
20
|
+
|
|
34
21
|
remove(index) {
|
|
35
22
|
return this.splice(index, 1)[0];
|
|
36
23
|
}
|
|
@@ -47,4 +34,4 @@ class Queue extends Array{
|
|
|
47
34
|
}
|
|
48
35
|
}
|
|
49
36
|
|
|
50
|
-
module.exports = Queue;
|
|
37
|
+
module.exports = Queue;
|
package/src/guild/Track.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
class Track {
|
|
2
2
|
constructor(data) {
|
|
3
|
-
this.
|
|
4
|
-
this.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
this.track = data.track
|
|
4
|
+
this.info = {
|
|
5
|
+
identifier : data.info.identifier,
|
|
6
|
+
isSeekable : data.info.isSeekable,
|
|
7
|
+
author : data.info.author,
|
|
8
|
+
length : data.info.length,
|
|
9
|
+
isStream : data.info.isStream,
|
|
10
|
+
position : data.info.position,
|
|
11
|
+
sourceName:data.info.sourceName,
|
|
12
|
+
title : data.info.title,
|
|
13
|
+
uri : data.info.uri,
|
|
14
|
+
image : `https://i.ytimg.com/vi/${data.info.identifier}/maxresdefault.jpg` || null
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
module.exports = Track;
|
|
20
|
+
module.exports = Track;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
declare module'Poru' {
|
|
2
|
+
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
|
|
5
|
+
export class Poru extends EventEmitter {
|
|
6
|
+
constructor(client: typeof EventEmitter| any,nodes:[],options:{})
|
|
7
|
+
|
|
8
|
+
public client :typeof EventEmitter | any
|
|
9
|
+
public nodes :typeof Map
|
|
10
|
+
public players :typeof Map
|
|
11
|
+
public voiceStates :typeof Map
|
|
12
|
+
public voiceServers :typeof Map
|
|
13
|
+
public user : String
|
|
14
|
+
public options: Object | any
|
|
15
|
+
public shards :Number
|
|
16
|
+
public sendData : Function
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
public on(event: 'nodeConnect' | 'nodeReconnect', listener: (node: Object) => void): this
|
|
22
|
+
public on(event: 'nodeDisconnect', listener: (event: any, node: Object) => void): this
|
|
23
|
+
public on(event: 'nodeError', listener: (node: Object, event: any) => void): this
|
|
24
|
+
public on(event: 'queueEnd', listener: (player:typeof EventEmitter |any,track:Object,data:Object|any ) => void): this
|
|
25
|
+
public on(event: 'trackStart' | 'trackEnd', listener: (player:typeof EventEmitter |any,track:Object,data:Object|any) => void): this
|
|
26
|
+
public on(event: 'trackEnd' | 'trackEnd', listener: (player:typeof EventEmitter |any,track:Object,data:Object|any) => void): this
|
|
27
|
+
public on(event: 'trackStuck' | 'trackError', listener: (player:typeof EventEmitter |any,track:Object,data:Object|any) => void): this
|
|
28
|
+
public on(event: 'socketClosed', listener: (player:typeof EventEmitter |any,data:Object|any) => void): this
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
addNode(options:Object)
|
|
33
|
+
|
|
34
|
+
removeNode(identifier:String)
|
|
35
|
+
|
|
36
|
+
createConnection(data:Object)
|
|
37
|
+
|
|
38
|
+
init(client:typeof EventEmitter|any)
|
|
39
|
+
|
|
40
|
+
leastUsedNodes()
|
|
41
|
+
|
|
42
|
+
resolve(track:String, source:String)
|
|
43
|
+
|
|
44
|
+
decodeTrack(tarck:String)
|
|
45
|
+
|
|
46
|
+
get(guildID:String)
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
export class Node {
|
|
54
|
+
constructor(manager:typeof EventEmitter|any,options:object,node:object)
|
|
55
|
+
|
|
56
|
+
public manager: EventEmitter
|
|
57
|
+
public name: String
|
|
58
|
+
public host: String
|
|
59
|
+
public port : Number
|
|
60
|
+
public url : String
|
|
61
|
+
public password: String
|
|
62
|
+
public secure: Boolean
|
|
63
|
+
public ws = any
|
|
64
|
+
public reconnectTime : Number
|
|
65
|
+
public resumeKey:String|Number;
|
|
66
|
+
public resumeTimeout =Number
|
|
67
|
+
public reconnectAttempt:Number;
|
|
68
|
+
public reconnects:Number;
|
|
69
|
+
public isConnected:Boolean;
|
|
70
|
+
public destroyed:Boolean;
|
|
71
|
+
public stats:Object
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
connect():void
|
|
75
|
+
|
|
76
|
+
destroy()
|
|
77
|
+
|
|
78
|
+
reconnect()
|
|
79
|
+
|
|
80
|
+
send(playload:any)
|
|
81
|
+
|
|
82
|
+
get penalties():Number
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
export class Player extends EventEmitter {
|
|
90
|
+
constructor(manager:EventEmitter,node:Map|Object, options:Object)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
public manager:EventEmitter
|
|
95
|
+
|
|
96
|
+
public queue:Array |any
|
|
97
|
+
|
|
98
|
+
public node: Map|Object|Any;
|
|
99
|
+
|
|
100
|
+
public filters: any
|
|
101
|
+
|
|
102
|
+
public guild:String
|
|
103
|
+
|
|
104
|
+
public voiceChannel:any
|
|
105
|
+
|
|
106
|
+
public textChannel:any;
|
|
107
|
+
|
|
108
|
+
public isConnectd = Boolean;
|
|
109
|
+
|
|
110
|
+
public isPlaying:Boolean;
|
|
111
|
+
|
|
112
|
+
public isPause:Boolean;
|
|
113
|
+
|
|
114
|
+
public trackRepeat:Boolean;
|
|
115
|
+
|
|
116
|
+
public queueRepeat:Boolean;
|
|
117
|
+
|
|
118
|
+
public loop:Number;
|
|
119
|
+
|
|
120
|
+
public position :Number;
|
|
121
|
+
|
|
122
|
+
public volume :Number;
|
|
123
|
+
|
|
124
|
+
public currentTrack:Object
|
|
125
|
+
|
|
126
|
+
public previousTrack:Object;
|
|
127
|
+
|
|
128
|
+
public voiceUpdateState = any;
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
play()
|
|
134
|
+
|
|
135
|
+
stop()
|
|
136
|
+
|
|
137
|
+
pause(pause:Boolean)
|
|
138
|
+
|
|
139
|
+
seekTo(position:Number)
|
|
140
|
+
|
|
141
|
+
setVolume(volume:Number)
|
|
142
|
+
|
|
143
|
+
TrackRepeat();
|
|
144
|
+
|
|
145
|
+
QueueRepeat();
|
|
146
|
+
|
|
147
|
+
DisableRepeat();
|
|
148
|
+
|
|
149
|
+
setTextChannel(channel:any)
|
|
150
|
+
|
|
151
|
+
setVoiceChannel(channel:any)
|
|
152
|
+
|
|
153
|
+
connect(data:any)
|
|
154
|
+
|
|
155
|
+
reconnect()
|
|
156
|
+
|
|
157
|
+
disconnect()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
destroy()
|
|
161
|
+
|
|
162
|
+
autoplay(toggle:Boolean)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
}
|
package/.gitpod.yml
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
# This configuration file was automatically generated by Gitpod.
|
|
2
|
-
# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
|
|
3
|
-
# and commit this file to your remote git repository to share the goodness with others.
|
|
4
|
-
|
|
5
|
-
tasks:
|
|
6
|
-
- init: npm install
|
|
7
|
-
|
|
8
|
-
|