poru 1.2.3 → 2.0.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/.gitpod.yml ADDED
@@ -0,0 +1,8 @@
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
+
package/README.md CHANGED
@@ -3,16 +3,15 @@
3
3
  </p>
4
4
  <p align="center">
5
5
 
6
- [![Discord](https://img.shields.io/discord/567705326774779944?style=flat-square)](https://discord.gg/Zmmc47Nrh8)
6
+ [![Discord](https://img.shields.io/discord/567705326774779944?style=flat-square)](https://discord.gg/Zmmc47Nrh8)
7
7
  [![npm](https://img.shields.io/npm/v/poru?style=flat-square)](https://www.npmjs.com/package/poru)
8
8
  ![Github Stars](https://img.shields.io/github/stars/parasop/poru?style=flat-square)
9
9
  ![GitHub issues](https://img.shields.io/github/issues-raw/parasop/poru?style=flat-square)
10
- ![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/poru?style=flat-square)
10
+ ![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/poru?style=flat-square)
11
11
  ![NPM](https://img.shields.io/npm/l/poru?style=flat-square)
12
12
 
13
13
  </p>
14
14
 
15
-
16
15
  <p align="center">
17
16
  <a href="https://nodei.co/npm/poru/"><img src="https://nodei.co/npm/poru.png?downloads=true&downloadRank=true&stars=true"></a>
18
17
  </p>
@@ -25,6 +24,7 @@
25
24
  - [Example](https://github.com/parasop/poru-example)
26
25
 
27
26
  # Installation
27
+
28
28
  ```
29
29
  // Using npm
30
30
  npm install poru
@@ -34,6 +34,7 @@ yarn add poru
34
34
  ```
35
35
 
36
36
  # About
37
+
37
38
  To use you need a configured [Lavalink](https://github.com/Frederikam/Lavalink) instance.
38
39
 
39
40
  - Stable client
@@ -43,15 +44,16 @@ To use you need a configured [Lavalink](https://github.com/Frederikam/Lavalink)
43
44
  - Easy to setup
44
45
 
45
46
  ## Implementation
46
- [Poru Music](https://github.com/parasop/poru-example) **Example bot as guide for beginning.**
47
47
 
48
+ [Poru Music](https://github.com/parasop/poru-example) **Example bot as guide for beginning.**
48
49
 
49
50
  ## Example usage basic bot
51
+
50
52
  ```javascript
51
53
  // main file
52
54
  // Require both libraries
53
- const { Client } = require("discord.js");
54
- const { Poru } = require("poru");
55
+ const { Client } = require('discord.js');
56
+ const { Poru } = require('poru');
55
57
 
56
58
  // Initiate both main classes
57
59
  const client = new Client();
@@ -59,39 +61,49 @@ const client = new Client();
59
61
  // Define some options for the node
60
62
  const nodes = [
61
63
  {
62
- host: "localhost",
63
- password: "youshallnotpass",
64
+ host: 'localhost',
65
+ password: 'youshallnotpass',
64
66
  port: 2333,
65
- secure:false
66
- }
67
+ secure: false,
68
+ },
67
69
  ];
68
70
 
71
+ // Define if you want to integrate spotify
72
+ const spotifyOptions = {
73
+ clientID: 'Your Client ID', // You'll find this on https://developers.spotify.com/dashboard/
74
+ clientSecret: 'Your Client Secret', // You'll find this on https://developers.spotify.com/dashboard/
75
+ playlistLimit: 10, // The amount of pages to load when a playlist is searched with each page having 50 tracks.
76
+ albumLimit: 5, // The amount of pages to load when a album is searched with each page having 50 tracks.
77
+ artistLimit: 5, // The amount of pages to load when a artist is searched with each page having 50 tracks.
78
+ searchMarket: 'IN', // The market from where the query should be searched from. Mainly this should contain your country.
79
+ };
80
+
69
81
  // Assign Manager to the client variable
70
- client.poru = new Poru(client,nodes);
82
+ client.poru = new Poru(client, nodes);
71
83
 
72
84
  // Emitted whenever a node connects
73
- client.poru.on("nodeConnect", node => {
74
- console.log(`Node "${node.name}" connected.`)
75
- })
85
+ client.poru.on('nodeConnect', node => {
86
+ console.log(`Node "${node.name}" connected.`);
87
+ });
76
88
 
77
89
  // Emitted whenever a node encountered an error
78
- client.poru.on("nodeError", (node, error) => {
79
- console.log(`Node "${node.name}" encountered an error`)
80
- })
90
+ client.poru.on('nodeError', (node, error) => {
91
+ console.log(`Node "${node.name}" encountered an error`);
92
+ });
81
93
 
82
94
  // Listen for when the client becomes ready
83
- client.once("ready", () => {
84
- client.poru.init(client;
95
+ client.once('ready', () => {
96
+ client.poru.init(client);
85
97
  console.log(`Logged in as ${client.user.tag}`);
86
98
  });
87
99
 
88
- // Finally login at the END of your code
89
- client.login("your bot token here");
90
-
100
+ // this event used to make connections upto date with lavalink
101
+ client.on('raw', async d => await client.poru.packetUpdate(d));
91
102
 
103
+ // Finally login at the END of your code
104
+ client.login('your bot token here');
92
105
  ```
93
106
 
94
-
95
107
  ```javascript
96
108
  // creating player
97
109
  const player = await client.poru.createConnection({
@@ -99,12 +111,13 @@ const player = await client.poru.createConnection({
99
111
  voiceChannel: message.member.voice.channel.id,
100
112
  textChannel: message.channel,
101
113
  selfDeaf: true,
102
- selfMute: false,
103
- })
104
- // Getting tracks
105
- const resolve = await client.poru.resolve('Ignite',"yt");
114
+ selfMute: false,
115
+ });
116
+ // Getting tracks
117
+ const resolve = await client.poru.resolve('Ignite', 'yt');
106
118
  ```
107
119
 
108
120
  ## Need Help?
109
- Feel free to join our [discord server](https://discord.gg/Zmmc47Nrh8), Give us suggestions and advice about errors and new features.
121
+
122
+ Feel free to join our [discord server](https://discord.gg/Zmmc47Nrh8), Give us suggestions and advice about errors and new features.
110
123
  with ❤️ by [Paras](https://github.com/parasop) .
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poru",
3
- "version": "1.2.3",
3
+ "version": "2.0.2",
4
4
  "description": "A stable and powefull lavalink client with so many features",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -19,5 +19,16 @@
19
19
  "dependencies": {
20
20
  "node-fetch": "^3.2.6",
21
21
  "ws": "^8.8.0"
22
- }
22
+ },
23
+ "keywords": [
24
+ "music",
25
+ "lavalink",
26
+ "poru",
27
+ "bot",
28
+ "spotify",
29
+ "apple-music",
30
+ "soundcloud",
31
+ "discordjs",
32
+ "eris"
33
+ ]
23
34
  }
package/src/Node.js CHANGED
@@ -1,16 +1,15 @@
1
1
  const WebSocket = require("ws");
2
- const config = require("./config.json")
2
+ const config = require("./config")
3
3
 
4
4
  class Node {
5
5
  constructor(manager,options,node) {
6
-
7
6
  this.manager = manager
8
7
  this.name= options.name || null;
9
8
  this.host = options.host || "localhost"
10
9
  this.port = options.port || 2333
11
- this.url = `${options.secure ? 'wss' : 'ws'}://${options.host}:${options.port}`;
12
10
  this.password = options.password ||"youshallnotpass"
13
11
  this.secure = options.secure || false;
12
+ this.url = `${this.secure ? 'wss' : 'ws'}://${this.host}:${this.port}/`;
14
13
  this.ws = null;
15
14
  this.reconnectTime = node.reconnectTime || 5000;
16
15
  this.resumeKey = node.resumeKey || null;
@@ -37,132 +36,153 @@ class Node {
37
36
  };
38
37
 
39
38
 
40
- }
41
-
42
- connect() {
43
- if (this.ws) this.ws.close();
44
- const headers = {
45
- Authorization: this.password,
46
- "Num-Shards": this.manager.shards || 1,
47
- "User-Id": this.manager.user,
48
- "Client-Name": config.client
49
- };
50
- if (this.resumeKey) headers["Resume-Key"] = this.resumeKey;
51
- this.ws = new WebSocket(`ws${this.secure ? "s" : ""}:${this.host}:${this.port}/`, { headers });
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
-
58
-
59
- #open(){
60
- if (this.reconnectAttempt) {
61
- clearTimeout(this.reconnectAttempt);
62
- delete this.reconnectAttempt;
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
- }
39
+ }
40
+
41
+
42
+ connect() {
43
+ if (this.ws) this.ws.close();
44
+ const headers = {
45
+ Authorization: this.password,
46
+ "Num-Shards": this.manager.shards || 1,
47
+ "User-Id": this.manager.user,
48
+ "Client-Name": config.clientName
49
+ };
50
+ if (this.resumeKey) headers["Resume-Key"] = this.resumeKey;
51
+ this.ws = new WebSocket(this.url, { headers });
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
+ }
73
57
 
74
- this.manager.emit("nodeConnect", this);
75
- this.isConnected = true;
76
- this.manager.emit('debug', this.name, `[Web Socket] Connection ready ${this.url}`);
77
-
78
- }
58
+ disconnect(){
59
+ if(!this.isConnected) return;
60
+
61
+ this.ws?.removeAllListeners();
62
+ this.ws?.close();
63
+ this.ws = null;
64
+ this.isConnected = false;
79
65
 
80
- #message(payload) {
81
- if (Array.isArray(payload)) payload = Buffer.concat(payload);
82
- else if (payload instanceof ArrayBuffer) payload = Buffer.from(payload);
83
66
 
84
- const packet = JSON.parse(payload);
85
- if (packet.op && packet.op === "stats") {
86
- this.stats = { ...packet };
87
- delete this.stats.op;
88
67
  }
89
- const player = this.manager.players.get(packet.guildId);
90
- if (packet.guildId && player) player.emit(packet.op, packet);
91
68
 
92
- packet.node = this;
93
- this.manager.emit("debug",this.name,`[Web Socket] Lavalink Node Update : ${packet.op} `)
94
- this.manager.emit("raw", packet);
95
- }
96
69
 
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"}`)
100
- if (event !== 1000){
70
+ #open(){
71
+ if (this.reconnectAttempt) {
72
+ clearTimeout(this.reconnectAttempt);
73
+ delete this.reconnectAttempt;
74
+ }
75
+
76
+ if (this.resumeKey){
77
+ this.send({
78
+ op: "configureResuming",
79
+ key: (this.resumeKey).toString(),
80
+ timeout: this.resumeTimeout
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
+
102
+ }
101
103
 
102
- return this.reconnect();
103
104
  }
104
- }
105
105
 
106
+ #message(payload) {
106
107
 
107
- #error(event) {
108
- if (!event) return "Unknown event";
108
+ const packet = JSON.parse(payload);
109
+ if(!packet.op) return;
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);
119
+ }
109
120
 
110
- this.manager.emit("debug",this.name,`[Web Socket] Connection for Lavalink node has error code: ${event.code}`)
111
- this.manager.emit("nodeError", this, event);
112
- return this.reconnect();
113
- }
121
+ #close(event) {
122
+ this.disconnect();
123
+ this.manager.emit("nodeDisconnect",this,event);
124
+ this.manager.emit("debug",this.name,`[Web Socket] Connection with Lavalink closed with Error code : ${event||"Unknown code"}`)
125
+ if (event !== 1000){
126
+
127
+ }
128
+ }
114
129
 
115
- destroy(){
116
- if(!this.isConnected) return;
117
130
 
118
- const players = this.manager.players.filter(p => p.node == this);
119
- if (players.size) players.forEach(p => p.destroy());
120
- this.ws.close(1000, "destroy");
121
- this.ws.removeAllListeners();
122
- this.ws = null;
123
- this.reconnect = 1;
124
- this.destroyed = true;
125
- this.manager.nodes.delete(this.host)
126
- this.manager.emit("nodeDestroy", this);
131
+ #error(event) {
132
+ if (!event) return "Unknown event";
127
133
 
134
+ this.manager.emit("debug",this.name,`[Web Socket] Connection for Lavalink node has error code: ${event.code}`)
135
+ this.manager.emit("nodeError", this, event);
136
+ return this.reconnect();
137
+ }
128
138
 
129
- }
139
+ destroy(){
140
+ if(!this.isConnected) return;
130
141
 
131
- reconnect() {
132
- this.reconnectAttempt = setTimeout(() => {
133
- this.isConnected = false;
142
+ const players = this.manager.players.filter(p => p.node == this);
143
+ if (players.size) players.forEach(p => p.destroy());
144
+ this.ws.close(1000, "destroy");
134
145
  this.ws.removeAllListeners();
135
146
  this.ws = null;
136
- this.manager.emit("nodeReconnect", this);
137
- this.connect();
138
- }, this.reconnectTime);
139
- }
140
-
141
- send(payload) {
142
- this.ws.send(JSON.stringify(payload), (error) => {
143
- if (error) return error;
144
- return null;
145
- });
146
- }
147
+ this.reconnect = 1;
148
+ this.destroyed = true;
149
+ this.manager.nodes.delete(this.host)
150
+ this.manager.emit("nodeDestroy", this);
147
151
 
148
152
 
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
153
  }
159
- return penalties;
160
- }
161
154
 
155
+ reconnect() {
156
+ this.reconnectAttempt = setTimeout(() => {
157
+ this.isConnected = false;
158
+ this.ws.removeAllListeners();
159
+ this.ws = null;
160
+ this.manager.emit("nodeReconnect", this);
161
+ this.connect();
162
+ }, this.reconnectTime);
163
+ }
162
164
 
163
- }
164
-
165
+ send(payload) {
166
+ const data = JSON.stringify(payload);
167
+ this.ws.send(data, (error) => {
168
+ if (error) return error;
169
+ return null;
170
+ });
171
+ this.manager.emit("raw", data, this.name)
172
+ }
165
173
 
174
+ get penalties(){
175
+ let penalties = 0;
176
+ if (!this.isConnected) return penalties;
177
+ penalties += this.stats.players;
178
+ penalties += Math.round(Math.pow(1.05, 100 * this.stats.cpu.systemLoad) * 10 - 10);
179
+ if (this.stats.frameStats) {
180
+ penalties += this.stats.frameStats.deficit;
181
+ penalties += this.stats.frameStats.nulled * 2;
182
+ }
183
+ return penalties;
184
+ }
185
+ }
166
186
 
167
- module.exports = Node;
187
+ module.exports = Node;
168
188
 
package/src/Player.js CHANGED
@@ -23,7 +23,7 @@ class Player extends EventEmitter {
23
23
 
24
24
  this.isPlaying = false;
25
25
 
26
- this.isPause = false;
26
+ this.isPaused = false;
27
27
 
28
28
  this.trackRepeat = false;
29
29
 
@@ -50,26 +50,32 @@ class Player extends EventEmitter {
50
50
  this.manager.emit("playerUpdate", this, packet);
51
51
  });
52
52
  }
53
- async play() {
53
+
54
+ async play(options={}) {
54
55
 
55
56
  if (!this.queue.length) {
56
- return nulll;
57
+ return null;
58
+ }
59
+
60
+ this.currentTrack = this.queue.shift()
61
+
62
+ if(!this.currentTrack.track){
63
+ this.currentTrack = await this.currentTrack.resolve(this.manager);
57
64
  }
58
- this.currentTrack = this.queue.shift();
59
- this.playing = true;
60
- this.timestamp = Date.now();
65
+
66
+ this.isPlaying = true;
61
67
  this.node.send({
62
68
  op: "play",
63
69
  guildId: this.guild,
64
70
  track: this.currentTrack.track,
65
- volume: this.volume || 100,
66
- });
71
+ noReplace:options.noReplace || true,
72
+ });
67
73
  this.position = 0;
68
74
  return this;
69
75
  }
70
76
 
71
77
 
72
- stop() {
78
+ stop() {
73
79
 
74
80
  this.position = 0;
75
81
  this.isConnectd = false
@@ -90,7 +96,7 @@ class Player extends EventEmitter {
90
96
  pause,
91
97
  });
92
98
  this.isPlaying = !pause;
93
- this.isPause = pause;
99
+ this.isPaused = pause;
94
100
 
95
101
  return this;
96
102
  }
@@ -125,6 +131,7 @@ class Player extends EventEmitter {
125
131
  return this;
126
132
  }
127
133
 
134
+
128
135
  async QueueRepeat() {
129
136
  this.loop = 2;
130
137
  this.queueRepeat = true;
@@ -136,9 +143,7 @@ class Player extends EventEmitter {
136
143
  this.loop = 0;
137
144
  this.trackRepeat = false;
138
145
  this.queueRepeat = false;
139
-
140
-
141
- return this;
146
+ return this;
142
147
  }
143
148
 
144
149
  async setTextChannel(channel) {
@@ -179,9 +184,6 @@ class Player extends EventEmitter {
179
184
  return this;
180
185
  }
181
186
 
182
-
183
-
184
-
185
187
  async disconnect() {
186
188
  if (this.voiceChannel === null) return null;
187
189
  this.pause(true);
@@ -209,16 +211,34 @@ class Player extends EventEmitter {
209
211
  this.manager.players.delete(this.guild);
210
212
  }
211
213
 
214
+ restart(){
215
+ this.filters.updateFilters();
216
+ if(this.currentTrack){
217
+
218
+ this.isPlaying = true;
219
+ this.node.send({
220
+ op: "play",
221
+ startTime: this.position,
222
+ noReplace:true,
223
+ guildId: this.guild,
224
+ track: this.currentTrack.track,
225
+ puase: this.isPaused
226
+ });
227
+
228
+
229
+ }
230
+ }
231
+
212
232
  async autoplay(toggle = false) {
213
233
 
214
234
  if (!toggle) return null;
215
235
  try {
216
236
  if (!this.previousTrack) return this.stop();
217
- let data = `https://www.youtube.com/watch?v=${this.previousTrack.identifier}&list=RD${this.previousTrack.identifier}`;
237
+ let data = `https://www.youtube.com/watch?v=${this.previousTrack.info.identifier}&list=RD${this.previousTrack.info.identifier}`;
218
238
 
219
- let response = await this.manager.search(data);
239
+ let response = await this.manager.resolve(data);
220
240
 
221
- if (!response || !response.tracks || ["LOAD_FAILED", "NO_MATCHES"].includes(response.type)) return this.stop();
241
+ if (!response || !response.tracks || ["LOAD_FAILED", "NO_MATCHES"].includes(response.loadType)) return this.stop();
222
242
 
223
243
  let track = response.tracks[Math.floor(Math.random() * Math.floor(response.tracks.length))];
224
244
 
@@ -303,7 +323,6 @@ class Player extends EventEmitter {
303
323
  return events[data.type] || events.default;
304
324
  }
305
325
 
306
-
307
326
  }
308
327
 
309
328
  module.exports = Player;
package/src/Poru.js CHANGED
@@ -2,11 +2,13 @@ const { EventEmitter } = require("events");
2
2
  const fetch = (...args) => import('node-fetch').then(({
3
3
  default: fetch
4
4
  }) => fetch(...args));
5
+ const config = require("./config")
5
6
  const Player = require("./Player");
6
7
  const Node = require("./Node");
7
8
  const Response = require("./guild/Response");
8
- const config = require("./config.json")
9
9
  const Spotify = require("./platform/Spotify")
10
+ const AppleMusic = require("./platform/AppleMusic")
11
+ const Deezer = require("./platform/Deezer")
10
12
  class Poru extends EventEmitter {
11
13
  constructor(client, nodes, options = {}) {
12
14
  super();
@@ -23,6 +25,7 @@ class Poru extends EventEmitter {
23
25
  this.options = options
24
26
  this.shards = options.shards || 1;
25
27
  this.sendData = null;
28
+ this.version = config.version
26
29
  }
27
30
 
28
31
 
@@ -75,21 +78,34 @@ class Poru extends EventEmitter {
75
78
  if (guild) guild.shard.send(data);
76
79
  }
77
80
  client.on("raw", async packet => {
78
- await this.#packetUpdate(packet);
81
+ await this.packetUpdate(packet);
79
82
  })
80
-
83
+
81
84
  this._nodes.forEach((node) => this.addNode(node));
82
85
 
83
86
 
84
- if (this.options.spotify.clientID && this.options.spotify.clientSecret) {
85
- this.spotify = new Spotify(this, {
86
- clientID: this.options.clientID,
87
- clientSecret: this.options.clientSecret
88
- })
87
+ if (this.options.spotify && this.options.spotify.clientID && this.options.spotify.clientSecret) {
88
+ this.spotify = new Spotify(this, this.options)
89
+ }
90
+ if (this.options.apple) {
91
+ if (!this.options.apple.playlistLimit) {
92
+ throw new Error("[Poru Apple Music] playlistLimit must be provided")
93
+ }
94
+ this.apple = new AppleMusic(this, this.options)
95
+ this.apple.requestToken();
96
+ }
97
+ if (this.options.deezer) {
98
+ if (!this.options.deezer.playlistLimit) {
99
+ throw new Error("[Poru Deezer Music] playlistLimit must be provided")
100
+
101
+ }
102
+ this.deezer = new Deezer(this, this.options)
103
+
89
104
  }
90
105
  console.log(`Thanks for using Poru`)
91
106
  }
92
107
 
108
+
93
109
  setServersUpdate(data) {
94
110
  let guild = data.guild_id
95
111
  this.voiceServers.set(guild, data);
@@ -130,7 +146,7 @@ class Poru extends EventEmitter {
130
146
  this.voiceStates.delete(data.guild_id);
131
147
  }
132
148
 
133
- #packetUpdate(packet) {
149
+ packetUpdate(packet) {
134
150
  if (!['VOICE_STATE_UPDATE', 'VOICE_SERVER_UPDATE'].includes(packet.t)) return;
135
151
  const player = this.players.get(packet.d.guild_id);
136
152
  if (!player) return;
@@ -175,15 +191,24 @@ class Poru extends EventEmitter {
175
191
 
176
192
 
177
193
  async resolve(track, source) {
194
+
178
195
  const node = this.leastUsedNodes[0];
179
196
  if (!node) throw new Error("No nodes are available.");
180
- if(this.spotify && this.spotify.check(track)){
181
- return await this.spotify.resolve(track);
197
+
198
+ if (this.spotify && this.spotify.check(track)) {
199
+ return await this.spotify.resolve(track);
200
+ } else if (this.apple && this.apple.check(track)) {
201
+ return await this.apple.resolve(track);
202
+ } else if (this.deezer && this.deezer.check(track)) {
203
+ return await this.deezer.resolve(track);
182
204
  }
205
+
206
+
207
+
183
208
  const regex = /^https?:\/\//;
184
209
  if (!regex.test(track)) {
185
210
  // eslint-disable-next-line no-param-reassign
186
- track = `${source || "yt"}search:${track}`;
211
+ track = `${source || "ytsearch"}:${track}`;
187
212
  }
188
213
  const result = await this.#fetch(node, "loadtracks", `identifier=${encodeURIComponent(track)}`);
189
214