Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

poru

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

poru - npm Package Compare versions

Comparing version 1.1.8 to 1.1.9

.gitpod.yml

23

package.json
{
"name": "poru",
"version": "1.1.8",
"version": "1.1.9",
"description": "A stable and powefull lavalink client with so many features",

@@ -20,8 +20,17 @@ "main": "index.js",

"dependencies": {
"node-fetch": "^3.2.6",
"ws": "^8.8.0",
"axios": "^0.27.2",
"cheerio": "^1.0.0-rc.12"
}
"cheerio": "^1.0.0-rc.12",
"undici": "^5.6.0",
"ws": "^8.8.0"
},
"keywords": [
"music",
"lavalink",
"poru",
"bot",
"spotify",
"apple-music",
"soundcloud",
"discordjs",
"eris"
]
}

@@ -6,7 +6,7 @@ <p align="center">

[![Discord](https://img.shields.io/discord/567705326774779944?style=flat-square)](https://discord.gg/Zmmc47Nrh8)
[![Discord](https://img.shields.io/discord/567705326774779944?style=flat-square)](https://discord.gg/Zmmc47Nrh8)
[![npm](https://img.shields.io/npm/v/poru?style=flat-square)](https://www.npmjs.com/package/poru)
![Github Stars](https://img.shields.io/github/stars/parasop/poru?style=flat-square)
![GitHub issues](https://img.shields.io/github/issues-raw/parasop/poru?style=flat-square)
![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/poru?style=flat-square)
![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/poru?style=flat-square)
![NPM](https://img.shields.io/npm/l/poru?style=flat-square)

@@ -16,3 +16,2 @@

<p align="center">

@@ -30,2 +29,3 @@ <a href="https://nodei.co/npm/poru/"><img src="https://nodei.co/npm/poru.png?downloads=true&downloadRank=true&stars=true"></a>

# Installation
```

@@ -40,2 +40,3 @@ // Using npm

# About
To use you need a configured [Lavalink](https://github.com/Frederikam/Lavalink) instance.

@@ -50,11 +51,12 @@

## Implementation
[Poru Music](https://github.com/parasop/poru-example) **Example bot as guide for beginning.**
[Poru Music](https://github.com/parasop/poru-example) **Example bot as guide for beginning.**
## Example usage basic bot
```javascript
// main file
// Require both libraries
const { Client } = require("discord.js");
const { Poru } = require("poru");
const { Client } = require('discord.js');
const { Poru } = require('poru');

@@ -67,24 +69,34 @@ // Initiate both main classes

{
host: "localhost",
password: "youshallnotpass",
host: 'localhost',
password: 'youshallnotpass',
port: 2333,
secure:false
}
secure: false,
},
];
// Define if you want to integrate spotify
const spotifyOptions = {
clientID: 'Your Client ID', // You'll find this on https://developers.spotify.com/dashboard/
clientSecret: 'Your Client Secret', // You'll find this on https://developers.spotify.com/dashboard/
playlistLimit: 10, // The amount of pages to load when a playlist is searched with each page having 50 tracks.
albumLimit: 5, // The amount of pages to load when a album is searched with each page having 50 tracks.
artistLimit: 5, // The amount of pages to load when a artist is searched with each page having 50 tracks.
searchMarket: 'IN', // The market from where the query should be searched from. Mainly this should contain your country.
};
// Assign Manager to the client variable
client.poru = new Poru(client,nodes);
client.poru = new Poru(client, nodes);
// Emitted whenever a node connects
client.poru.on("nodeConnect", node => {
console.log(`Node "${node.name}" connected.`)
})
client.poru.on('nodeConnect', node => {
console.log(`Node "${node.name}" connected.`);
});
// Emitted whenever a node encountered an error
client.poru.on("nodeError", (node, error) => {
console.log(`Node "${node.name}" encountered an error`)
})
client.poru.on('nodeError', (node, error) => {
console.log(`Node "${node.name}" encountered an error`);
});
// Listen for when the client becomes ready
client.once("ready", () => {
client.once('ready', () => {
client.poru.init(client);

@@ -94,10 +106,9 @@ console.log(`Logged in as ${client.user.tag}`);

// this event used to make connections upto date with lavalink
client.on('raw', async d => await client.poru.packetUpdate(d));
// Finally login at the END of your code
client.login("your bot token here");
client.login('your bot token here');
```
```javascript

@@ -110,10 +121,11 @@ // creating player

selfDeaf: true,
selfMute: false,
})
// Getting tracks
const resolve = await client.poru.resolve('Ignite',"yt");
selfMute: false,
});
// Getting tracks
const resolve = await client.poru.resolve('Ignite', 'yt');
```
## Need Help?
Feel free to join our [discord server](https://discord.gg/Zmmc47Nrh8), Give us suggestions and advice about errors and new features.
Feel free to join our [discord server](https://discord.gg/Zmmc47Nrh8), Give us suggestions and advice about errors and new features.
with ❤️ by [Paras](https://github.com/parasop) .

@@ -1,2 +0,2 @@

const axios = require("axios")
const { fetch } = require('undici');
const Track = require("../guild/Track")

@@ -32,4 +32,3 @@ const cheerio = require("cheerio")

const urlType = await this.decodeUrl(url);
const page = await axios
.get(url)
const page = await fetch(url)
.then((res) => res.data)

@@ -36,0 +35,0 @@ .catch(() => undefined);

@@ -1,253 +0,250 @@

const fetch = (...args) => import('node-fetch').then(({
default: fetch
}) => fetch(...args));
const { fetch } = require('undici');
const Track = require("../guild/Track")
class Spotify {
constructor(manager) {
this.manager = manager;
this.baseURL = "https://api.spotify.com/v1"
this.spotifyPattern = /^(?:https:\/\/open\.spotify\.com\/(?:user\/[A-Za-z0-9]+\/)?|spotify:)(album|playlist|track|artist)(?:[/:])([A-Za-z0-9]+).*$/
this.clientID = manager.options.spotify.clientID;
this.clientSecret = manager.options.spotify.clientSecret
this.authorization = Buffer
.from(`${this.clientID}:${this.clientSecret}`)
.toString("base64");
this.interval = 0;
}
constructor(manager) {
this.manager = manager;
this.baseURL = 'https://api.spotify.com/v1';
this.spotifyPattern =
/^(?:https:\/\/open\.spotify\.com\/(?:user\/[A-Za-z0-9]+\/)?|spotify:)(album|playlist|track|artist)(?:[/:])([A-Za-z0-9]+).*$/;
this.clientID = manager.options.spotify.clientID;
this.clientSecret = manager.options.spotify.clientSecret;
this.playlistLimit = manager.options.spotify.playlistLimit;
this.albumLimit = manager.options.spotify.albumLimit;
this.artistLimit = manager.options.spotify.artistLimit;
this.searchMarket = manager.options.spotify.searchMarket;
this.authorization = Buffer.from(`${this.clientID}:${this.clientSecret}`).toString('base64');
this.interval = 0;
}
check(url) {
return this.spotifyPattern.test(url);
}
check(url) {
return this.spotifyPattern.test(url);
}
async requestToken() {
if (this.nextRequest) return;
async requestToken() {
if (this.nextRequest) return;
try {
const data = await fetch("https://accounts.spotify.com/api/token?grant_type=client_credentials", {
method: "POST",
headers: {
Authorization: `Basic ${this.authorization}`,
'Content-Type': 'application/x-www-form-urlencoded',
}
})
try {
const data = await fetch('https://accounts.spotify.com/api/token?grant_type=client_credentials', {
method: 'POST',
headers: {
Authorization: `Basic ${this.authorization}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const body = await data.json();
const body = await data.json();
this.token = `Bearer ${body.access_token}`;
this.interval = body.expires_in * 1000
} catch (e) {
if (e.status === 400) {
throw new Error("Invalid Spotify client.")
}
}
this.token = `Bearer ${body.access_token}`;
this.interval = body.expires_in * 1000;
} catch (e) {
if (e.status === 400) {
throw new Error('Invalid Spotify client.');
}
}
}
async renew() {
if (Date.now() >= this.interval) {
await this.requestToken();
}
async renew() {
if (Date.now() >= this.interval) {
await this.requestToken();
}
}
async requestData(endpoint) {
await this.renew();
async requestData(endpoint) {
await this.renew();
const req = await fetch(`${this.baseURL}${/^\//.test(endpoint) ? endpoint : `/${endpoint}`}`, {
headers: { Authorization: this.token }
})
const data = await req.json()
return data
}
const req = await fetch(`${this.baseURL}${/^\//.test(endpoint) ? endpoint : `/${endpoint}`}`, {
headers: { Authorization: this.token },
});
const data = await req.json();
return data;
}
async resolve(url) {
if (!this.token) await this.requestToken();
const [, type, id] = this.spotifyPattern.exec(url) ?? [];
async resolve(url) {
if (!this.token) await this.requestToken()
const [, type, id] = await this.spotifyPattern.exec(url) ?? [];
switch (type) {
case 'playlist': {
return this.fetchPlaylist(id);
}
case 'track': {
return this.fetchTrack(id);
}
case 'album': {
return this.fetchAlbum(id);
}
case 'artist': {
return this.fetchArtist(id);
}
switch (type) {
case "playlist":
{
return this.fetchPlaylist(id)
}
case "track":
{
return this.fetchTrack(id)
}
case "album":
{
return this.fetchAlbum(id)
}
case "artist":
{
return this.fetchArtist(id);
}
default: {
return this.manager.resolve(url)
}
}
default: {
return this.manager.resolve(url);
}
}
}
async fetchPlaylist(id) {
try {
const playlist = await this.requestData(`/playlists/${id}`)
await this.fetchPlaylistTracks(playlist);
const unresolvedPlaylistTracks = await Promise.all(playlist.tracks.items.map(x => this.buildUnresolved(x.track)))
async fetchPlaylist(id) {
try {
const playlist = await this.requestData(`/playlists/${id}`);
await this.fetchPlaylistTracks(playlist);
const limitedTracks = this.playlistLimit
? playlist.tracks.items.slice(0, this.playlistLimit * 50)
: playlist.tracks.items;
return this.buildResponse(
"PLAYLIST_LOADED",
unresolvedPlaylistTracks,
playlist.name
);
const unresolvedPlaylistTracks = await Promise.all(limitedTracks.map(x => this.buildUnresolved(x.track)));
} catch (e) {
return this.buildResponse(e.status === 404 ? "NO_MATCHES" : "LOAD_FAILED", [], undefined, e.body?.error.message ?? e.message);
}
return this.buildResponse('PLAYLIST_LOADED', unresolvedPlaylistTracks, playlist.name);
} catch (e) {
return this.buildResponse(
e.status === 404 ? 'NO_MATCHES' : 'LOAD_FAILED',
[],
undefined,
e.body?.error.message ?? e.message,
);
}
}
async fetchAlbum(id) {
try {
const album = await this.requestData(`/albums/${id}`)
async fetchAlbum(id) {
try {
const album = await this.requestData(`/albums/${id}`);
const unresolvedPlaylistTracks = await Promise.all(album.tracks.items.map(x => this.buildUnresolved(x)));
return this.buildResponse(
"PLAYLIST_LOADED",
unresolvedPlaylistTracks,
album.name
);
const limitedTracks = this.albumLimit ? album.tracks.items.slice(0, this.albumLimit * 50) : album.tracks.items;
} catch (e) {
return this.buildResponse(e.body?.error.message === "invalid id" ? "NO_MATCHES" : "LOAD_FAILED", [], undefined, e.body?.error.message ?? e.message);
}
const unresolvedPlaylistTracks = await Promise.all(limitedTracks.map(x => this.buildUnresolved(x)));
return this.buildResponse('PLAYLIST_LOADED', unresolvedPlaylistTracks, album.name);
} catch (e) {
return this.buildResponse(
e.body?.error.message === 'invalid id' ? 'NO_MATCHES' : 'LOAD_FAILED',
[],
undefined,
e.body?.error.message ?? e.message,
);
}
}
async fetchArtist(id) {
try {
const artist = await this.requestData(`/artists/${id}`)
async fetchArtist(id) {
try {
const artist = await this.requestData(`/artists/${id}`);
const data = await this.requestData(`/artists/${id}/top-tracks?market=US`)
const unresolvedPlaylistTracks = await Promise.all(data.tracks.map(x => this.buildUnresolved(x)));
const data = await this.requestData(`/artists/${id}/top-tracks?market=${this.searchMarket ?? 'US'}`);
return this.buildResponse(
"PLAYLIST_LOADED",
unresolvedPlaylistTracks,
artist.name
);
} catch (e) {
return this.buildResponse(e.body?.error.message === "invalid id" ? "NO_MATCHES" : "LOAD_FAILED", [], undefined, e.body?.error.message ?? e.message);
}
const limitedTracks = this.artistLimit ? data.tracks.slice(0, this.artistLimit * 50) : data.tracks;
}
const unresolvedPlaylistTracks = await Promise.all(limitedTracks.map(x => this.buildUnresolved(x)));
async fetchTrack(id) {
try {
const data = await this.requestData(`/tracks/${id}`)
const unresolvedTrack = await this.buildUnresolved(data);
return this.buildResponse(
"TRACK_LOADED",
[unresolvedTrack]
);
} catch (e) {
return this.buildResponse(e.body?.error.message === "invalid id" ? "NO_MATCHES" : "LOAD_FAILED", [], undefined, e.body?.error.message ?? e.message);
}
return this.buildResponse('PLAYLIST_LOADED', unresolvedPlaylistTracks, artist.name);
} catch (e) {
return this.buildResponse(
e.body?.error.message === 'invalid id' ? 'NO_MATCHES' : 'LOAD_FAILED',
[],
undefined,
e.body?.error.message ?? e.message,
);
}
}
async fetch(query) {
try {
if (this.check(query)) return this.resolve(query)
const data = await this.requestData(`/search/?q="${query}"&type=artist,album,track`)
const unresolvedTrack = await this.buildUnresolved(data.tracks.items[0]);
return this.buildResponse(
"TRACK_LOADED",
[unresolvedTrack]
);
} catch (e) {
return this.buildResponse(e.body?.error.message === "invalid id" ? "NO_MATCHES" : "LOAD_FAILED", [], undefined, e.body?.error.message ?? e.message);
}
async fetchTrack(id) {
try {
const data = await this.requestData(`/tracks/${id}`);
const unresolvedTrack = await this.buildUnresolved(data);
return this.buildResponse('TRACK_LOADED', [unresolvedTrack]);
} catch (e) {
return this.buildResponse(
e.body?.error.message === 'invalid id' ? 'NO_MATCHES' : 'LOAD_FAILED',
[],
undefined,
e.body?.error.message ?? e.message,
);
}
}
async fetchPlaylistTracks(spotifyPlaylist) {
let nextPage = spotifyPlaylist.tracks.next;
let pageLoaded = 1;
while (nextPage) {
if (!nextPage) break;
const req = await fetch(nextPage, {
headers: { Authorization: this.token }
})
const body = await req.json()
if (body.error) break;
spotifyPlaylist.tracks.items.push(...body.items);
async fetch(query) {
try {
if (this.check(query)) return this.resolve(query);
nextPage = body.next;
pageLoaded++;
}
}
const data = await this.requestData(
`/search/?q="${query}"&type=artist,album,track&market=${this.searchMarket ?? 'US'}`,
);
const unresolvedTrack = await this.buildUnresolved(data.tracks.items[0]);
async buildUnresolved(track) {
if (!track) throw new ReferenceError("The Spotify track object was not provided");
return new Track({
track: "",
info: {
sourceName: 'spotify',
identifier: track.id,
isSeekable: true,
author: track.artists[0] ? track.artists[0].name : 'Unknown',
length: track.duration_ms,
isStream: false,
title: track.name,
uri: `https://open.spotify.com/track/${track.id}`,
image: track.album?.images[0]?.url,
},
})
return this.buildResponse('TRACK_LOADED', [unresolvedTrack]);
} catch (e) {
return this.buildResponse(
e.body?.error.message === 'invalid id' ? 'NO_MATCHES' : 'LOAD_FAILED',
[],
undefined,
e.body?.error.message ?? e.message,
);
}
}
async fetchMetaData(track) {
async fetchPlaylistTracks(spotifyPlaylist) {
let nextPage = spotifyPlaylist.tracks.next;
let pageLoaded = 1;
while (nextPage) {
if (!nextPage) break;
const req = await fetch(nextPage, {
headers: { Authorization: this.token },
});
const body = await req.json();
if (body.error) break;
spotifyPlaylist.tracks.items.push(...body.items);
const fetch = await this.manager.resolve(`${track.info.title} ${track.info.author}`)
return fetch.tracks[0];
nextPage = body.next;
pageLoaded++;
}
}
async buildTrack(unresolvedTrack) {
const lavaTrack = await this.fetchMetaData(unresolvedTrack);
if (lavaTrack) {
unresolvedTrack.track = lavaTrack.track;
unresolvedTrack.info.identifier = lavaTrack.info.identifier
return unresolvedTrack
}
}
async buildUnresolved(track) {
if (!track) throw new ReferenceError('The Spotify track object was not provided');
return new Track({
track: '',
info: {
sourceName: 'spotify',
identifier: track.id,
isSeekable: true,
author: track.artists[0] ? track.artists[0].name : 'Unknown',
length: track.duration_ms,
isStream: false,
title: track.name,
uri: `https://open.spotify.com/track/${track.id}`,
image: track.album?.images[0]?.url,
},
});
}
compareValue(value) {
return typeof value !== 'undefined' ? value !== null : typeof value !== 'undefined';
}
async fetchMetaData(track) {
const fetch = await this.manager.resolve(`${track.info.title} ${track.info.author}`);
return fetch.tracks[0];
}
buildResponse(loadType, tracks, playlistName, exceptionMsg) {
return Object.assign({
loadType,
tracks,
playlistInfo: playlistName ? { name: playlistName } : {}
}, exceptionMsg ? { exception: { message: exceptionMsg, severity: "COMMON" } } : {});
async buildTrack(unresolvedTrack) {
const lavaTrack = await this.fetchMetaData(unresolvedTrack);
if (lavaTrack) {
unresolvedTrack.track = lavaTrack.track;
unresolvedTrack.info.identifier = lavaTrack.info.identifier;
return unresolvedTrack;
}
}
compareValue(value) {
return typeof value !== 'undefined' ? value !== null : typeof value !== 'undefined';
}
buildResponse(loadType, tracks, playlistName, exceptionMsg) {
return Object.assign(
{
loadType,
tracks,
playlistInfo: playlistName ? { name: playlistName } : {},
},
exceptionMsg ? { exception: { message: exceptionMsg, severity: 'COMMON' } } : {},
);
}
}
module.exports = Spotify
module.exports = Spotify;
const { EventEmitter } = require("events");
const fetch = (...args) => import('node-fetch').then(({
default: fetch
}) => fetch(...args));
const { fetch } = require('undici');
const Player = require("./Player");

@@ -13,22 +11,20 @@ const Node = require("./Node");

class Poru extends EventEmitter {
constructor(client, nodes, options = {}) {
super();
if (!client) throw new Error("[Poru Error] you did't provide a valid client");
if (!nodes) throw new Error("[Poru Error] you did't provide a lavalink nodes");
if (!options) throw new Error("[Poru Error] options must be provided!")
this.client = client;
this._nodes = nodes;
this.nodes = new Map();
this.players = new Map();
this.voiceStates = new Map();
this.voiceServers = new Map();
this.user = null;
this.options = options
this.shards = options.shards || 1;
this.sendData = null;
}
constructor(client, nodes, options = {}) {
super();
if (!client) throw new Error("[Poru Error] you did't provide a valid client");
if (!nodes) throw new Error("[Poru Error] you did't provide a lavalink nodes");
if (!options) throw new Error('[Poru Error] options must be provided!');
this.client = client;
this._nodes = nodes;
this.nodes = new Map();
this.players = new Map();
this.voiceStates = new Map();
this.voiceServers = new Map();
this.user = null;
this.options = options;
this.shards = options.shards || 1;
this.sendData = null;
}
//create a node and connect it with lavalink
//create a node and connect it with lavalink
addNode(options) {

@@ -81,3 +77,3 @@ const node = new Node(this, options, this.options);

client.on("raw", async packet => {
await this.#packetUpdate(packet);
await this.packetUpdate(packet);
})

@@ -119,71 +115,79 @@

return true;
}
this.sendData({
op: 4,
d: {
guild_id: data.guild.id || data.guild,
channel_id: data.voiceChannel.id || data.voiceChannel,
self_mute: data.selfMute || false,
self_deaf: data.selfDeaf || true,
},
});
return this.#Player(data);
}
setStateUpdate(data) {
if (data.user_id !== this.user) return;
if (data.channel_id) {
const guild = data.guild_id;
init(client) {
this.user = client.user.id;
this.sendData = data => {
const guild = client.guilds.cache.get(data.d.guild_id);
if (guild) guild.shard.send(data);
};
client.on('raw', async packet => {
await this.#packetUpdate(packet);
});
this.voiceStates.set(data.guild_id, data);
const server = this.voiceServers.get(guild);
const state = this.voiceStates.get(guild);
if (!server) return false;
const player = this.players.get(guild);
if (!player) return false;
this._nodes.forEach(node => this.addNode(node));
player.connect({
sessionId: state ? state.session_id : player.voiceUpdateState.sessionId,
event: server,
});
return true;
}
this.voiceServers.delete(data.guild_id);
this.voiceStates.delete(data.guild_id);
if (this.options.spotify && this.options.spotify.clientID && this.options.spotify.clientSecret) {
this.spotify = new Spotify(this, {
clientID: this.options.clientID,
clientSecret: this.options.clientSecret,
playlistLimit: this.options.playlistLimit,
albumLimit: this.options.albumLimit,
artistLimit: this.options.artistLimit,
searchMarket: this.options.searchMarket,
});
}
this.voiceServers.delete(data.guild_id);
this.voiceStates.delete(data.guild_id);
}
#packetUpdate(packet) {
if (!['VOICE_STATE_UPDATE', 'VOICE_SERVER_UPDATE'].includes(packet.t)) return;
const player = this.players.get(packet.d.guild_id);
if (!player) return;
#packetUpdate(packet) {
if (!['VOICE_STATE_UPDATE', 'VOICE_SERVER_UPDATE'].includes(packet.t)) return;
const player = this.players.get(packet.d.guild_id);
if (!player) return;
if (packet.t === "VOICE_SERVER_UPDATE") {
this.setServersUpdate(packet.d);
}
if (packet.t === "VOICE_STATE_UPDATE") {
this.setStateUpdate(packet.d);
}
if (packet.t === 'VOICE_SERVER_UPDATE') {
this.setServersUpdate(packet.d);
}
get leastUsedNodes() {
return [...this.nodes.values()]
.filter((node) => node.isConnected)
.sort((a, b) => {
const aLoad = a.stats.cpu ? (a.stats.cpu.systemLoad / a.stats.cpu.cores) * 100 : 0;
const bLoad = b.stats.cpu ? (b.stats.cpu.systemLoad / b.stats.cpu.cores) * 100 : 0;
return aLoad - bLoad;
});
if (packet.t === 'VOICE_STATE_UPDATE') {
this.setStateUpdate(packet.d);
}
}
#Player(data) {
const guild = data.guild.id || data.guild;
const Nodes = this.nodes.get(guild);
if (Nodes) return Nodes;
if (this.leastUsedNodes.length === 0) throw new Error("[Poru Error] No nodes are avaliable");
const node = this.nodes.get(this.leastUsedNodes[0].name
|| this.leastUsedNodes[0].host);
if (!node) throw new Error("[Poru Error] No nodes are avalible");
get leastUsedNodes() {
return [...this.nodes.values()]
.filter(node => node.isConnected)
.sort((a, b) => {
const aLoad = a.stats.cpu ? (a.stats.cpu.systemLoad / a.stats.cpu.cores) * 100 : 0;
const bLoad = b.stats.cpu ? (b.stats.cpu.systemLoad / b.stats.cpu.cores) * 100 : 0;
return aLoad - bLoad;
});
}
// eslint-disable-next-line new-cap
const player = new Player(this, node, data);
this.players.set(guild, player);
player.connect()
return player;
}
#Player(data) {
const guild = data.guild.id || data.guild;
const Nodes = this.nodes.get(guild);
if (Nodes) return Nodes;
if (this.leastUsedNodes.length === 0) throw new Error('[Poru Error] No nodes are avaliable');
const node = this.nodes.get(this.leastUsedNodes[0].name || this.leastUsedNodes[0].host);
if (!node) throw new Error('[Poru Error] No nodes are avalible');
// eslint-disable-next-line new-cap
const player = new Player(this, node, data);
this.players.set(guild, player);
player.connect();
return player;
}
async resolve(track, source) {

@@ -221,21 +225,38 @@

}
const regex = /^https?:\/\//;
if (!regex.test(track)) {
// eslint-disable-next-line no-param-reassign
track = `${source || 'yt'}search:${track}`;
}
const result = await this.#fetch(node, 'loadtracks', `identifier=${encodeURIComponent(track)}`);
#fetch(node, endpoint, param) {
return fetch(`http${node.secure ? "s" : ""}://${node.host}:${node.port}/${endpoint}?${param}`, {
headers: {
Authorization: node.password,
if (!result) throw new Error('[Poru Error] No tracks found.');
return new Response(result);
}
},
})
.then((r) => r.json())
.catch((e) => {
throw new Error(`[Poru Error] Failed to fetch from the lavalink.\n error: ${e}`);
});
}
async decodeTrack(track) {
const node = this.leastUsedNodes[0];
if (!node) throw new Error('No nodes are available.');
const result = await this.#fetch(node, 'decodetrack', `track=${track}`);
if (result.status === 500) return null;
return result;
}
get(guildId) {
return this.players.get(guildId);
}
#fetch(node, endpoint, param) {
return fetch(`http${node.secure ? 's' : ''}://${node.host}:${node.port}/${endpoint}?${param}`, {
headers: {
Authorization: node.password,
},
})
.then(r => r.json())
.catch(e => {
throw new Error(`[Poru Error] Failed to fetch from the lavalink.\n error: ${e}`);
});
}
get(guildId) {
return this.players.get(guildId);
}
}
module.exports = Poru
module.exports = Poru;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc