From 9a235e2602f99ade31498dec78fde834a1491de4 Mon Sep 17 00:00:00 2001 From: Raphix Date: Thu, 14 Mar 2024 18:54:17 +0100 Subject: [PATCH 1/5] Version 2.1.0 - Version avec Moonlink.js --- package-lock.json | 44 +++++------- package.json | 4 +- src/modules/discord-bot.js | 47 ++++++++----- src/modules/nodes-finder.js | 12 ++-- src/modules/sub-auth.js | 1 + src/modules/sub-list.js | 8 ++- src/modules/sub-player.js | 103 ++++++++++++++-------------- src/modules/sub-playlist.js | 2 + src/modules/sub-web.js | 2 +- src/modules/types.d.ts | 7 ++ src/web/public/javascript/basics.js | 2 +- src/web/public/javascript/player.js | 2 +- src/web/public/javascript/queue.js | 2 +- 13 files changed, 127 insertions(+), 109 deletions(-) create mode 100644 src/modules/types.d.ts diff --git a/package-lock.json b/package-lock.json index 9a84384..75e753b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,22 @@ { "name": "subsonics-web", - "version": "2.0.0", + "version": "2.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "subsonics-web", - "version": "2.0.0", + "version": "2.1.0", "dependencies": { "cookie": "^0.5.0", "cookie-parser": "^1.4.6", "discord.js": "^14.9.0", "ejs": "^3.1.9", - "erela.js": "^2.4.0", "express": "^4.18.2", "express-favicon": "^2.0.4", "loguix": "^1.4.2", "markdown-it": "^13.0.1", + "moonlink.js": "^3.6.0", "nodemon": "^2.0.22", "pm2": "^5.3.0", "request": "^2.88.2", @@ -1343,20 +1343,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/erela.js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-2.4.0.tgz", - "integrity": "sha512-wLfPvfzbDZTDV0zwJYXGkjO9Q6mkXi3PNf984apdv58Ktt0cv1Zp8og3hmp7Ose4C4iwAKitHxV/yiP+pt3FRQ==", - "dependencies": { - "@discordjs/collection": "^1.1.0", - "tslib": "^2.4.0", - "undici": "^5.10.0", - "ws": "^8.8.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2284,6 +2270,14 @@ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, + "node_modules/moonlink.js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/moonlink.js/-/moonlink.js-3.6.0.tgz", + "integrity": "sha512-uzXCc8G+bl87TqgoLV1pJZ0WMcGVY5RyjUJpegvKhF5lhqShIPREiH60ZORi832VQoVyg3KCBJLMSKv0D3j8wQ==", + "engines": { + "node": ">=16.6.0" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -4855,17 +4849,6 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" }, - "erela.js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/erela.js/-/erela.js-2.4.0.tgz", - "integrity": "sha512-wLfPvfzbDZTDV0zwJYXGkjO9Q6mkXi3PNf984apdv58Ktt0cv1Zp8og3hmp7Ose4C4iwAKitHxV/yiP+pt3FRQ==", - "requires": { - "@discordjs/collection": "^1.1.0", - "tslib": "^2.4.0", - "undici": "^5.10.0", - "ws": "^8.8.1" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -5552,6 +5535,11 @@ "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, + "moonlink.js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/moonlink.js/-/moonlink.js-3.6.0.tgz", + "integrity": "sha512-uzXCc8G+bl87TqgoLV1pJZ0WMcGVY5RyjUJpegvKhF5lhqShIPREiH60ZORi832VQoVyg3KCBJLMSKv0D3j8wQ==" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", diff --git a/package.json b/package.json index 203e001..44a3aed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "subsonics-web", "author": "Raphix", - "version": "2.0.4", + "version": "2.1.0", "nodemonConfig": { "ext": "js, html", "ignore": [ @@ -16,11 +16,11 @@ "cookie-parser": "^1.4.6", "discord.js": "^14.9.0", "ejs": "^3.1.9", - "erela.js": "^2.4.0", "express": "^4.18.2", "express-favicon": "^2.0.4", "loguix": "^1.4.2", "markdown-it": "^13.0.1", + "moonlink.js": "^3.6.0", "nodemon": "^2.0.22", "pm2": "^5.3.0", "request": "^2.88.2", diff --git a/src/modules/discord-bot.js b/src/modules/discord-bot.js index ee164b6..caf010f 100644 --- a/src/modules/discord-bot.js +++ b/src/modules/discord-bot.js @@ -1,12 +1,14 @@ const { Client, GatewayIntentBits, Collection, ActivityType, REST, Routes } = require("discord.js") const fs = require("node:fs") const path = require("path") -const { Manager } = require("erela.js") const { __glob } = require("./global-variables") const { LogType } = require("loguix") const { List } = require("./sub-list") const nodeFinder = require("./nodes-finder") const metric = require("webmetrik") +const { MoonlinkManager } = require("moonlink.js") + +/// const client = new Client({ intents:[GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers], @@ -153,16 +155,17 @@ function startErelaManager(dlog, config) { const elog = new LogType("Lavalink-Manager") const nodes = nodeFinder.getNodes() - client.manager = new Manager({ + client.manager = new MoonlinkManager( // The nodes to connect to, optional if using default lavalink options nodes, - // Method to send voice data to Discord - send: (id, payload) => { - const guild = client.guilds.cache.get(id); - // NOTE: FOR ERIS YOU NEED JSON.stringify() THE PAYLOAD - if (guild) guild.shard.send(payload); + { + /* Options */ + }, + (guild, sPayload) => { + // Sending payload information to the server + client.guilds.cache.get(guild).shard.send(JSON.parse(sPayload)); } - }); + ); const plog = new LogType("Lavalink-Player") @@ -196,6 +199,7 @@ function startErelaManager(dlog, config) { plog.log("Nouveau Player instancié dans : " + channel.name) }) + player.setVolume(100) process.emit("MUSIC_UPDATE_STATE") @@ -220,12 +224,12 @@ function startErelaManager(dlog, config) { songPlayed.setValue(songPlayed.getValue() + 1) if(player) { - plog.log("Lecture de '" + player.queue.current.title + "' de '" + player.queue.current.author + "'") - // Create a metric to count the number of minutes played by the bot using player.queue.current.duration which is in ms (milliseconds) and verify if it's not a livestream + plog.log("Lecture de '" + player.current.title + "' de '" + player.current.author + "'") + // Create a metric to count the number of minutes played by the bot using player.current.duration which is in ms (milliseconds) and verify if it's not a livestream - if(player.queue.current.duration && player.queue.current.duration != 9223372036854776000) { + if(player.current.duration && player.current.duration != 9223372036854776000) { const songDuration = new metric.Metric("songDuration", "Durée totale des musiques jouées en secondes") - songDuration.setValue(songDuration.getValue() + (player.queue.current.duration / 1000)) + songDuration.setValue(songDuration.getValue() + (player.current.duration / 1000)) } await list.setCurrent(player) @@ -252,29 +256,36 @@ function startErelaManager(dlog, config) { process.emit("MUSIC_UPDATE_STATE") }) + client.manager.on("playerUpdate", (player) => { + require("./sub-player").updateMusicState(client) + }) + // Emitted whenever a node connects - client.manager.on("nodeConnect", node => { - elog.log(`Connecté au serveur Lavalink : "${node.options.identifier}"` ) - nodeFinder.setNodeState(node.options.identifier, true) + client.manager.on("nodeReady", node => { + elog.log(`Connecté au serveur Lavalink : "${node.host}"` ) + nodeFinder.setNodeState(node.host, true) }) // Emitted whenever a node encountered an error client.manager.on("nodeError", (node, error) => { - elog.warn(`Node "${node.options.identifier}" encountered an error: ${error.message}.`) + elog.warn(`Node "${node.host}" encountered an error: ${error.message}.`) }) client.manager.on("nodeDisconnect", (node) => { - nodeFinder.setNodeState(node.options.identifier, false) + nodeFinder.setNodeState(node.host, false) }) // THIS IS REQUIRED. Send raw events to Erela.js - client.on("raw", d => client.manager.updateVoiceState(d)); + client.on("raw", data => { + + client.manager.packetUpdate(data); + }); } diff --git a/src/modules/nodes-finder.js b/src/modules/nodes-finder.js index d9ad335..18b4a61 100644 --- a/src/modules/nodes-finder.js +++ b/src/modules/nodes-finder.js @@ -7,6 +7,8 @@ const nlog = new LogType("Node-Finder") const nodesState = new Map() +/// + function checkAndCreate() { if (!fs.existsSync(__glob.NODES)) { try { @@ -32,14 +34,16 @@ function saveNodesFile(data) { module.exports.reloadNode = function (data) { const client = discord.getClient() + if (client.manager) { const nodesPresent = client.manager.nodes if (nodesPresent.get(data.host)) { - client.manager.destroyNode(data.host) + client.manager.nodes.remove(data.host) } nlog.log("Redémarrage de la node : " + data.host) - client.manager.createNode(data) + client.manager.nodes.add(data) client.manager.nodes.get(data.host).connect() + } } @@ -99,7 +103,7 @@ module.exports.addNodes = function (data) { if (client.manager) { const nodesPresent = client.manager.nodes if (!nodesPresent.get(data.host)) { - client.manager.createNode(data) + client.manager.nodes.add(data) } client.manager.nodes.get(data.host).connect() } @@ -123,7 +127,7 @@ module.exports.deleteNode = function (data) { if (client.manager) { const nodesPresent = client.manager.nodes if (nodesPresent.get(data.host)) { - client.manager.destroyNode(data.host) + client.manager.nodes.remove(data.host) } } saveNodesFile(nodes_data) diff --git a/src/modules/sub-auth.js b/src/modules/sub-auth.js index b979c69..276f850 100644 --- a/src/modules/sub-auth.js +++ b/src/modules/sub-auth.js @@ -8,6 +8,7 @@ const alog = new LogType("Authentification") var users = new Map() var sessions = new Array() +/// var packageJson = JSON.parse(fs.readFileSync(__glob.PACKAGE)) diff --git a/src/modules/sub-list.js b/src/modules/sub-list.js index 988b2eb..6d40307 100644 --- a/src/modules/sub-list.js +++ b/src/modules/sub-list.js @@ -6,6 +6,8 @@ const fs = require('fs') const dlog = new LogType("Queue-List") +/// + var next = new Array() var current = null; var shuffle = false @@ -182,7 +184,7 @@ module.exports.List = class { .setDescription('**Demandé par **' + interaction.member.user.username) .addFields({name: "Auteur", value: song.author}, {name: "URL", value: song.uri}) - .setThumbnail(song.thumbnail) + .setThumbnail(song.artworkUrl) .setTimestamp(); interaction.reply({embeds: [embed]}) @@ -323,8 +325,8 @@ module.exports.List = class { } - player = client.manager.create({ - guild: "137291455336022018", + player = client.manager.players.create({ + guildId: "137291455336022018", voiceChannel: channelId, textChannel: "664355637685256203", }); diff --git a/src/modules/sub-player.js b/src/modules/sub-player.js index aae0e63..d6a6661 100644 --- a/src/modules/sub-player.js +++ b/src/modules/sub-player.js @@ -9,6 +9,8 @@ const { Metric } = require("webmetrik"); const list = new List() +/// + module.exports.getSong = async function (url) { var client = discord.getClient() const songs = await client.manager.search(url) @@ -25,8 +27,8 @@ module.exports.play = async function (client, interaction) { if(!player) { - player = client.manager.create({ - guild: interaction.guild.id, + player = client.manager.players.create({ + guildId: interaction.guild.id, voiceChannel: interaction.member.voice.channel.id, textChannel: interaction.channel.id, }); @@ -68,8 +70,8 @@ module.exports.play = async function (client, interaction) { .setTitle('**Lecture de : **' + songs.tracks[0].title) .setDescription('**Demandé par **' + interaction.member.user.username) .addFields({name: "Auteur", value: songs.tracks[0].author}, - {name: "URL", value: songs.tracks[0].uri}) - .setThumbnail(songs.tracks[0].thumbnail) + {name: "URL", value: songs.tracks[0].url}) + .setThumbnail(songs.tracks[0].artworkUrl) .setTimestamp(); interaction.reply({embeds: [embed]}) @@ -90,7 +92,7 @@ module.exports.play = async function (client, interaction) { } - process.emit("MUSIC_UPDATE_STATE") + } @@ -100,10 +102,10 @@ module.exports.pause = function (client, interaction) { if(interaction) { let player = client.manager.players.get(interaction.guild.id) - + if(player) { - - if(player.playing) { + + if(!player.paused) { const embed = new EmbedBuilder() .setColor(0x03ff2d) @@ -114,7 +116,7 @@ module.exports.pause = function (client, interaction) { interaction.reply({embeds: [embed]}) - player.pause(true) + player.pause() } else { const embed = new EmbedBuilder() @@ -125,8 +127,8 @@ module.exports.pause = function (client, interaction) { interaction.reply({embeds: [embed]}) - - player.pause(false) + + player.resume() } } else { @@ -145,19 +147,21 @@ module.exports.pause = function (client, interaction) { if(player) { - if(player.playing) { - player.pause(true) + if(!player.paused) { + player.pause() + console.log("Paused") } else { - player.pause(false) - } + player.resume() + console.log("Unpaused") + } } } - process.emit("MUSIC_UPDATE_STATE") + } @@ -171,11 +175,11 @@ module.exports.getState = function(client, interaction) { let embed = new EmbedBuilder() .setColor(0x32a875) .setTitle('Information sur la musique') - .addFields({name:"Titre", value: player.queue.current.title}, - {name:"Auteur", value: player.queue.current.author}, - {name:"URL", value: player.queue.current.uri}) + .addFields({name:"Titre", value: player.current.title}, + {name:"Auteur", value: player.current.author}, + {name:"URL", value: player.current.url}) .setTimestamp() - .setThumbnail(player.queue.current.thumbnail); + .setThumbnail(player.current.artworkUrl); interaction.reply({embeds: [embed]}) @@ -222,8 +226,8 @@ module.exports.addSong = async function (data, userId, quick, playlist) { if(!player) { - player = client.manager.create({ - guild: "137291455336022018", + player = client.manager.players.create({ + guildId: "137291455336022018", voiceChannel: channelId, textChannel: "664355637685256203", }); @@ -240,7 +244,7 @@ module.exports.addSong = async function (data, userId, quick, playlist) { } else { - songs = await client.manager.search(data.uri) + songs = await client.manager.search(data.url) } if(quick) { @@ -266,7 +270,7 @@ module.exports.addSong = async function (data, userId, quick, playlist) { - process.emit("MUSIC_UPDATE_STATE") + } @@ -289,7 +293,7 @@ module.exports.addSongsFromPlaylist = async function (data, userId, quick) { - process.emit("MUSIC_UPDATE_STATE") + } @@ -318,7 +322,7 @@ module.exports.skip = function (client, interaction) { .setColor(0x03ff2d) .setTitle('On change de morceau !!!') .setDescription("**Ok, On est reparti avec "+ list.getNextSong().title + " et c'est demandée par " + interaction.member.user.username + "**") - .setThumbnail(list.getNextSong().thumbnail) + .setThumbnail(list.getNextSong().artworkUrl) .setTimestamp(); player.stop() @@ -353,7 +357,7 @@ module.exports.skip = function (client, interaction) { } - process.emit("MUSIC_UPDATE_STATE") + } module.exports.seek = function (data) { @@ -366,13 +370,13 @@ module.exports.seek = function (data) { let player = client.manager.players.get("137291455336022018") if(player) { - + player.seek(data) } - process.emit("MUSIC_UPDATE_STATE") + @@ -394,7 +398,7 @@ module.exports.setVol = function (data) { } - process.emit("MUSIC_UPDATE_STATE") + @@ -421,7 +425,7 @@ module.exports.loop = function (client) { } - process.emit("MUSIC_UPDATE_STATE") + } @@ -447,7 +451,7 @@ module.exports.changeShuffle = function (client) { } - process.emit("MUSIC_UPDATE_STATE") + } @@ -483,9 +487,6 @@ module.exports.search = async function (data, client) { return answer - - - } @@ -511,14 +512,14 @@ module.exports.previous = function (client, interaction) { interaction.reply({embeds: [embed]}) } else { - list.__next_add(player.queue.current) + list.__next_add(player.current) player.play(list.previous()) embed = new EmbedBuilder() .setColor(0x03ff2d) .setTitle('Retour vers le passé !!!') - .setDescription("**Ok, On est reparti avec "+ player.queue.current.title +" et c'est demandée par " + interaction.member.user.username + "**") + .setDescription("**Ok, On est reparti avec "+ player.current.title +" et c'est demandée par " + interaction.member.user.username + "**") .setTimestamp(); @@ -540,13 +541,13 @@ module.exports.previous = function (client, interaction) { let player = client.manager.players.get("137291455336022018") if(list.havePreviousSongs()){ - list.__next_add(player.queue.current) + list.__next_add(player.current) player.play(list.previous()) } } - process.emit("MUSIC_UPDATE_STATE") + } const clog = new LogType("Actualisation") @@ -658,7 +659,7 @@ module.exports.updateMusicState = function (client, action) { data["shuffle"] = true } - data["current"] = player.queue.current + data["current"] = player.current if(player.queueRepeat == true) { @@ -668,18 +669,18 @@ module.exports.updateMusicState = function (client, action) { data["volume"] = player.volume * 10 - if(player.queue.current) { - data["durationNow"] = player.position - data["durationAll"] = player.queue.current.duration - currentTitle = player.queue.current.title + if(player.current) { + data["durationNow"] = player.current.position + data["durationAll"] = player.current.duration + currentTitle = player.current.title } + console.log(player.paused) + if(player.paused) { - if(player.playing == true && player.paused == false) { - - data["playing"] = 1 - } else { data["playing"] = 0 + } else { + data["playing"] = 1 } @@ -698,6 +699,7 @@ module.exports.updateMusicState = function (client, action) { } clog.log("Actualisation Clients - Titre : " + currentTitle + " - Loop : " + data.loop + " - Shuffle : " + data.shuffle + " - Playing : " + data.playing + " - Volume : " + Math.trunc(data.volume / 10) ) + return data @@ -750,7 +752,7 @@ module.exports.leave = function (client, interaction) { } - process.emit("MUSIC_UPDATE_STATE") + } @@ -798,4 +800,5 @@ function playStats(username) { var userMusicPlayed = new Metric("userMusicPlayed_" + username, "Nombre de musiques jouées par l'utilisateur : " + username) userMusicPlayed.setValue(userMusicPlayed.getValue() + 1) -} \ No newline at end of file +} + diff --git a/src/modules/sub-playlist.js b/src/modules/sub-playlist.js index 9e7b9c3..0f02d3e 100644 --- a/src/modules/sub-playlist.js +++ b/src/modules/sub-playlist.js @@ -8,6 +8,8 @@ const { url } = require("inspector"); var playlists = {} const plog = new LogType("Playlist-Manager") +/// + check() diff --git a/src/modules/sub-web.js b/src/modules/sub-web.js index 5afe81f..1a8346a 100644 --- a/src/modules/sub-web.js +++ b/src/modules/sub-web.js @@ -19,7 +19,7 @@ const markdownit = require("markdown-it")({ typographer: true }) - +/// module.exports.WebServer = class { diff --git a/src/modules/types.d.ts b/src/modules/types.d.ts new file mode 100644 index 0000000..57a069d --- /dev/null +++ b/src/modules/types.d.ts @@ -0,0 +1,7 @@ +import { MoonlinkManager } from 'moonlink.js'; + +declare module 'discord.js' { + interface Client { + manager: MoonlinkManager; + } +} \ No newline at end of file diff --git a/src/web/public/javascript/basics.js b/src/web/public/javascript/basics.js index db65b99..f7fd02a 100644 --- a/src/web/public/javascript/basics.js +++ b/src/web/public/javascript/basics.js @@ -229,7 +229,7 @@ class VideoComponent { this.onPlaylist = false this.title = data.title this.author = data.author - this.thumbnail = data.thumbnail + this.thumbnail = data.artworkUrl this.url = data.uri this.duration = data.duration this.identifier = data.identifier diff --git a/src/web/public/javascript/player.js b/src/web/public/javascript/player.js index 05fcfca..913974d 100644 --- a/src/web/public/javascript/player.js +++ b/src/web/public/javascript/player.js @@ -94,7 +94,7 @@ AlwaysRequest("MUSIC_STATE", async (data) => { if(data.current) { - var thumbnail = data.current.thumbnail + var thumbnail = data.current.artworkUrl if(thumbnail) { video_img.innerHTML = '' diff --git a/src/web/public/javascript/queue.js b/src/web/public/javascript/queue.js index 938740b..d25749f 100644 --- a/src/web/public/javascript/queue.js +++ b/src/web/public/javascript/queue.js @@ -153,7 +153,7 @@ class VideoQueue { console.log(data) this.title = data.title this.author = data.author - this.thumbnail = data.thumbnail + this.thumbnail = data.artworkUrl this.url = data.uri this.duration = data.duration this.identifier = data.numList + "_" + data.identifier From ad08c4dac2215f4b8e9f3101a448e45cfc3882c6 Mon Sep 17 00:00:00 2001 From: Raphix Date: Tue, 16 Apr 2024 15:17:19 +0200 Subject: [PATCH 2/5] Update .gitignore to include node_modules/moonlink.js/dist --- .gitignore | 5 ++ data/nodes.json | 4 +- data/users.json | 3 +- package-lock.json | 14 +++--- package.json | 2 +- src/modules/discord-bot.js | 34 +++++++++++-- src/modules/sub-list.js | 6 ++- src/modules/sub-player.js | 57 ++++++++++++---------- src/web/public/javascript/player.js | 12 ++--- src/web/public/stylesheets/style.css | 73 ++++++++++++++++++---------- src/web/templates/index.ejs | 12 +++-- 11 files changed, 145 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index ead1583..987f48d 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,12 @@ bower_components build/Release # Dependency directories + node_modules/ +!node_modules/moonlink.js/ +!node_modules/moonlink.js/dist/ + + jspm_packages/ # Snowpack dependency directory (https://snowpack.dev/) diff --git a/data/nodes.json b/data/nodes.json index 583b088..56832d1 100644 --- a/data/nodes.json +++ b/data/nodes.json @@ -1,8 +1,8 @@ [ { - "host": "omega.raphix.fr", + "host": "localhost", "port": 2333, "password": "youshallnotpass", - "retryAmount": 1 + "retryAmount": 5 } ] \ No newline at end of file diff --git a/data/users.json b/data/users.json index 4543774..71d52ba 100644 --- a/data/users.json +++ b/data/users.json @@ -481,7 +481,8 @@ "e18b2d89-2494-4cfe-af55-dad6dfbc0c60", "0a0b75f3-6a42-4ccf-92f9-d992a63545a4", "419a246f-e7b3-4aa4-9fa0-816dffc22a19", - "471c4c81-b8bc-42e7-af1a-d33df30cff2b" + "471c4c81-b8bc-42e7-af1a-d33df30cff2b", + "9f299250-6017-457b-87b6-23181288150a" ], "picture": "/userspictures/486943594893017119.png", "banned": false, diff --git a/package-lock.json b/package-lock.json index 75e753b..c93d937 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "express-favicon": "^2.0.4", "loguix": "^1.4.2", "markdown-it": "^13.0.1", - "moonlink.js": "^3.6.0", + "moonlink.js": "^3.6.4", "nodemon": "^2.0.22", "pm2": "^5.3.0", "request": "^2.88.2", @@ -2271,9 +2271,9 @@ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "node_modules/moonlink.js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/moonlink.js/-/moonlink.js-3.6.0.tgz", - "integrity": "sha512-uzXCc8G+bl87TqgoLV1pJZ0WMcGVY5RyjUJpegvKhF5lhqShIPREiH60ZORi832VQoVyg3KCBJLMSKv0D3j8wQ==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/moonlink.js/-/moonlink.js-3.6.4.tgz", + "integrity": "sha512-qaL/FxrWtwLLJmUHyFIh+kQauM1TUEb1qeK1oeoPxQ175SXPFgGySCV01h/RGc0Ki4Erke5rKAERt/aP1xVA4w==", "engines": { "node": ">=16.6.0" } @@ -5536,9 +5536,9 @@ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" }, "moonlink.js": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/moonlink.js/-/moonlink.js-3.6.0.tgz", - "integrity": "sha512-uzXCc8G+bl87TqgoLV1pJZ0WMcGVY5RyjUJpegvKhF5lhqShIPREiH60ZORi832VQoVyg3KCBJLMSKv0D3j8wQ==" + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/moonlink.js/-/moonlink.js-3.6.4.tgz", + "integrity": "sha512-qaL/FxrWtwLLJmUHyFIh+kQauM1TUEb1qeK1oeoPxQ175SXPFgGySCV01h/RGc0Ki4Erke5rKAERt/aP1xVA4w==" }, "ms": { "version": "2.0.0", diff --git a/package.json b/package.json index 44a3aed..657242c 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "express-favicon": "^2.0.4", "loguix": "^1.4.2", "markdown-it": "^13.0.1", - "moonlink.js": "^3.6.0", + "moonlink.js": "^3.6.4", "nodemon": "^2.0.22", "pm2": "^5.3.0", "request": "^2.88.2", diff --git a/src/modules/discord-bot.js b/src/modules/discord-bot.js index caf010f..f420eed 100644 --- a/src/modules/discord-bot.js +++ b/src/modules/discord-bot.js @@ -194,11 +194,14 @@ function startErelaManager(dlog, config) { const list = new List() + client.manager.on("playerCreate", async (player) => { + await client.channels.fetch(player.options.voiceChannel).then(channel => { plog.log("Nouveau Player instancié dans : " + channel.name) }) + player.setVolume(100) process.emit("MUSIC_UPDATE_STATE") @@ -242,6 +245,7 @@ function startErelaManager(dlog, config) { client.manager.on("queueEnd", async () => { let player = await client.manager.players.get("137291455336022018") + console.log("END OF QUEUE") if(player) { await list.addCurrentToPrevious() @@ -256,9 +260,33 @@ function startErelaManager(dlog, config) { process.emit("MUSIC_UPDATE_STATE") }) - client.manager.on("playerUpdate", (player) => { - require("./sub-player").updateMusicState(client) - }) + let events = [ + "playerConnected", + "playerCreated", + "playerPaused", + "playerRestarted", + "playerResume", + "playerStopped", + "playerSetVoiceChannel", + "playerAutoPlayTriggered", + "playerAutoLeaveTriggered", + "playerSetTextChannel", + "playerVolumeChanged", + "playerSkipped", + "playerSeeking", + "playerLoopSet", + "playerShuffled", + "playerMove", + "playerDisconnect", + "playerDestroyed", + "playerUpdate" + ]; + + events.forEach(event => { + client.manager.on(event, (player) => { + process.emit("MUSIC_UPDATE_STATE"); + }); + }); // Emitted whenever a node connects client.manager.on("nodeReady", node => { diff --git a/src/modules/sub-list.js b/src/modules/sub-list.js index 6d40307..44698d9 100644 --- a/src/modules/sub-list.js +++ b/src/modules/sub-list.js @@ -118,12 +118,14 @@ module.exports.List = class { } setCurrent(song) { - - current = song.queue.current + + + current = song.current } addCurrentToPrevious() { + if(current) { var previousList = getPreviousFile() previousList.unshift(current) diff --git a/src/modules/sub-player.js b/src/modules/sub-player.js index d6a6661..55ee059 100644 --- a/src/modules/sub-player.js +++ b/src/modules/sub-player.js @@ -92,7 +92,7 @@ module.exports.play = async function (client, interaction) { } - + process.emit("MUSIC_UPDATE_STATE") } @@ -117,6 +117,7 @@ module.exports.pause = function (client, interaction) { interaction.reply({embeds: [embed]}) player.pause() + process.emit("MUSIC_UPDATE_STATE") } else { const embed = new EmbedBuilder() @@ -129,6 +130,7 @@ module.exports.pause = function (client, interaction) { interaction.reply({embeds: [embed]}) player.resume() + process.emit("MUSIC_UPDATE_STATE") } } else { @@ -161,7 +163,6 @@ module.exports.pause = function (client, interaction) { } - } @@ -193,7 +194,7 @@ module.exports.getState = function(client, interaction) { } - + process.emit("MUSIC_UPDATE_STATE") } @@ -204,7 +205,7 @@ module.exports.playPlaylist = function (id, data, quick) { playlist.videos = data list.playlistAdd(playlist, null, id, quick) - + process.emit("MUSIC_UPDATE_STATE") } @@ -270,7 +271,7 @@ module.exports.addSong = async function (data, userId, quick, playlist) { - + process.emit("MUSIC_UPDATE_STATE") } @@ -293,7 +294,7 @@ module.exports.addSongsFromPlaylist = async function (data, userId, quick) { - + process.emit("MUSIC_UPDATE_STATE") } @@ -356,7 +357,7 @@ module.exports.skip = function (client, interaction) { } - + process.emit("MUSIC_UPDATE_STATE") } @@ -366,19 +367,21 @@ module.exports.seek = function (data) { client = discord.getClient() - + /** + * @type {import("moonlink.js").MoonlinkPlayer} + */ let player = client.manager.players.get("137291455336022018") if(player) { - player.seek(data) + player.seek((Number(data) - 1000)) } - + process.emit("MUSIC_UPDATE_STATE") } @@ -397,7 +400,7 @@ module.exports.setVol = function (data) { } - + process.emit("MUSIC_UPDATE_STATE") @@ -412,20 +415,24 @@ module.exports.loop = function (client) { client = discord.getClient() } + /** + * @type {import("moonlink.js").MoonlinkPlayer} + */ let player = client.manager.players.get("137291455336022018") if(player) { - if(player.queueRepeat == true) { - player.setQueueRepeat(false) + if(player.loop == 1) { + player.setLoop(0) } else { - player.setQueueRepeat(true) + player.setLoop(1) + } } - + process.emit("MUSIC_UPDATE_STATE") } @@ -451,7 +458,7 @@ module.exports.changeShuffle = function (client) { } - + process.emit("MUSIC_UPDATE_STATE") } @@ -486,7 +493,7 @@ module.exports.search = async function (data, client) { } return answer - + process.emit("MUSIC_UPDATE_STATE") } @@ -547,7 +554,7 @@ module.exports.previous = function (client, interaction) { } - + process.emit("MUSIC_UPDATE_STATE") } const clog = new LogType("Actualisation") @@ -622,7 +629,7 @@ module.exports.report = async function (client, interaction, data) { interaction.reply({embeds: [membed]}) } - + process.emit("MUSIC_UPDATE_STATE") } @@ -661,7 +668,7 @@ module.exports.updateMusicState = function (client, action) { data["current"] = player.current - if(player.queueRepeat == true) { + if(player.loop == 1) { data["loop"] = true } @@ -675,7 +682,6 @@ module.exports.updateMusicState = function (client, action) { currentTitle = player.current.title } - console.log(player.paused) if(player.paused) { data["playing"] = 0 @@ -699,9 +705,10 @@ module.exports.updateMusicState = function (client, action) { } clog.log("Actualisation Clients - Titre : " + currentTitle + " - Loop : " + data.loop + " - Shuffle : " + data.shuffle + " - Playing : " + data.playing + " - Volume : " + Math.trunc(data.volume / 10) ) - + + return data - + } @@ -753,7 +760,7 @@ module.exports.leave = function (client, interaction) { } - + process.emit("MUSIC_UPDATE_STATE") } @@ -775,7 +782,7 @@ module.exports.moveOut = function(userId) { } } - + process.emit("MUSIC_UPDATE_STATE") } // FINI diff --git a/src/web/public/javascript/player.js b/src/web/public/javascript/player.js index 913974d..a1efd12 100644 --- a/src/web/public/javascript/player.js +++ b/src/web/public/javascript/player.js @@ -29,7 +29,7 @@ var durationTotal = 0 var interval = null -var currentTitle = "" +var currentTitle = null var playerState = "DISCONNECTED" @@ -37,7 +37,7 @@ AlwaysRequest("MUSIC_STATE", async (data) => { durationAct = 0 durationTotal = 0 playerState = "DISCONNECTED" - currentTitle = "" + currentTitle = null stopInterval() console.log(data) @@ -131,7 +131,7 @@ AlwaysRequest("MUSIC_STATE", async (data) => { play.classList.add("disabled") - currentTitle = "" + currentTitle = null } if(data.queue) { @@ -153,7 +153,7 @@ AlwaysRequest("MUSIC_STATE", async (data) => { if(data.volume) { volume.step = 1 - volume.max = 200 + volume.max = 150 volume.min = 1 volume.value = Math.trunc(data.volume / 10) volTxt.innerHTML = Math.trunc(data.volume / 10) + "%" @@ -305,7 +305,7 @@ lyrics.addEventListener('click', (e) => { } else { - if(currentTitle != "") { + if(currentTitle) { showLyrics(currentTitle) } else { @@ -406,7 +406,7 @@ function startInterval() { interval = setInterval(() => { - if(playerState == "PLAYING") { + if(playerState == "PLAYING" && currentTitle) { setTime() } diff --git a/src/web/public/stylesheets/style.css b/src/web/public/stylesheets/style.css index ca298eb..9989fc6 100644 --- a/src/web/public/stylesheets/style.css +++ b/src/web/public/stylesheets/style.css @@ -9,7 +9,7 @@ body { flex-direction: column; align-items: flex-start; - background: #160120; + background: #19001e; display: flex; color: #FFF; font-family: 'Inter', sans-serif; @@ -351,11 +351,21 @@ button:hover { padding: 20px 20px 20px 20px; flex-direction: column; align-items: center; - gap: 20px; + gap: 7px; align-self: stretch; background: #131313; } +hr { + width: 100%; + display: block; + height: 1px; + border: 0; + border-top: 1px solid #cccccc87; + margin: 1em 0; + padding: 0; +} + /*Title*/ .title { @@ -393,11 +403,11 @@ button:hover { .homeselector { display: flex; width: 344px; - padding: 20px; + justify-content: space-around; align-items: flex-start; - border-radius: 10px; - background: #2F2F2F; + border-radius: 5px; + } .homeselector_div:hover { @@ -420,7 +430,7 @@ button:hover { .homeselector_icon { border: 2px solid #ffffff; - border-radius: 10px; + border-radius: 5px; font-size: 23px; justify-content: center; align-items: center; @@ -432,7 +442,7 @@ button:hover { } .homeselector_icon:hover { - background-color: #ffffff; + /* background-color: #ffffff; */ color: #000000; transform: scale(0.95); } @@ -441,14 +451,14 @@ button:hover { .playlist { display: flex; - padding: 20px; + flex-direction: column; align-items: flex-start; gap: 20px; flex: 1 0 0; align-self: stretch; - border-radius: 10px; - background: #2F2F2F; + border-radius: 5px; + } @@ -519,9 +529,9 @@ button:hover { align-items: center; flex: 1 0 0; align-self: stretch; - padding: 20px; - border-radius: 10px; - background: rgba(217, 217, 217, 0.30); + + border-radius: 5px; + } .view-other { @@ -549,7 +559,7 @@ button:hover { align-items: flex-start; gap: 10px; align-self: stretch; - border-radius: 10px; + border-radius: 5px; height: 30%; background: rgba(217, 217, 217, 0.30); @@ -599,7 +609,7 @@ button:hover { flex: 1; min-height: 0; align-self: stretch; - border-radius: 10px; + border-radius: 5px; background: rgba(217, 217, 217, 0.30); } @@ -1064,7 +1074,7 @@ button:hover { .playlist-add { background-color: #545454; padding: 5px; - border-radius: 10px; + border-radius: 5px; cursor: pointer; transition: 0.2s; font-size: 14px; @@ -1108,7 +1118,7 @@ button:hover { border: 2px solid #ffffff; - border-radius: 10px; + border-radius: 5px; font-size: 20px; width: 56px; height: 56px; @@ -1191,7 +1201,7 @@ button:hover { gap: 10px; align-self: stretch; - border-radius: 10px; + border-radius: 5px; @@ -1447,6 +1457,12 @@ button:hover { width: 100px !important; } + +.vol_px { + display: flex; + gap: 5px !important; +} + .oobe-list { display: flex; flex-direction: column; @@ -1454,7 +1470,7 @@ button:hover { align-items: flex-start; align-self: stretch; padding: 20px; - border-radius: 10px; + border-radius: 5px; background: rgba(217, 217, 217, 0.30); width: 30%; @@ -1491,7 +1507,7 @@ button:hover { align-items: flex-start; align-self: stretch; padding: 20px; - border-radius: 10px; + border-radius: 5px; background: #2F2F2F; width: 30%; } @@ -1503,7 +1519,7 @@ button:hover { align-items: flex-start; align-self: stretch; padding: 20px; - border-radius: 10px; + border-radius: 5px; background: #2F2F2F; } @@ -1551,7 +1567,7 @@ button:hover { .oobe-search { background: #2d2d2d; padding: 20px; - border-radius: 10px; + border-radius: 5px; } @@ -1607,15 +1623,20 @@ input[type="range"] { } /*Scrollbar */ ::-webkit-scrollbar { - width: 10px; + width: 5px; margin-right: 20px; } ::-webkit-scrollbar-track { border-radius: 12px; } ::-webkit-scrollbar-thumb { + background: #ffffff56; + border-radius: 5px; + transition: 0.2s; + } + +::-webkit-scrollbar-thumb:hover { background: #ffffffa8; - border-radius: 10px; } @@ -1626,7 +1647,7 @@ input[type="range"] { display: flex; flex-direction: column; width: 150px; - border-radius: 10px; + border-radius: 5px; z-index: 3; height: auto; } @@ -1676,7 +1697,7 @@ input[type="range"] { padding: 20px; box-shadow: 4px 5px 12px 5px rgba(0,0,0,0.6); width: 50%; - border-radius: 10px; + border-radius: 5px; color: #FFF; } diff --git a/src/web/templates/index.ejs b/src/web/templates/index.ejs index 3363651..a28d62c 100644 --- a/src/web/templates/index.ejs +++ b/src/web/templates/index.ejs @@ -28,6 +28,7 @@ Soundboard --> +

Playlists

@@ -42,6 +43,7 @@
+
@@ -126,10 +128,12 @@
- - - - +
+ + + +
+
From aa153aea725f499fd7db75a6ac9c22aefc52f547 Mon Sep 17 00:00:00 2001 From: Raphix Date: Tue, 16 Apr 2024 15:17:42 +0200 Subject: [PATCH 3/5] Update .gitignore to include node_modules/moonlink.js/dist --- Jenkinsfile_ntpd | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Jenkinsfile_ntpd diff --git a/Jenkinsfile_ntpd b/Jenkinsfile_ntpd new file mode 100644 index 0000000..b16e51a --- /dev/null +++ b/Jenkinsfile_ntpd @@ -0,0 +1,20 @@ +pipeline { + agent any + + stages { + stage('[Subsonics] - Déploiement') { + steps { + script { + + echo "[Subsonics-Deploy] - Deploy Stage" + sh "ssh raphix@raphix.fr sudo apt update -y" + sh "ssh raphix@raphix.fr sudo apt upgrade -y" + sh "ssh raphix@raphix.fr sudo -S -u gitlab-ci /home/gitlab-ci/subsonics_deploy.sh" + + + } + + } + } + } +} From 960cbeabc36608f8773ebf3024ba017e1f9392ce Mon Sep 17 00:00:00 2001 From: Raphix Date: Tue, 16 Apr 2024 15:17:57 +0200 Subject: [PATCH 4/5] Update .gitignore to include node_modules/moonlink.js/dist --- Jenkinsfile | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index b16e51a..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,20 +0,0 @@ -pipeline { - agent any - - stages { - stage('[Subsonics] - Déploiement') { - steps { - script { - - echo "[Subsonics-Deploy] - Deploy Stage" - sh "ssh raphix@raphix.fr sudo apt update -y" - sh "ssh raphix@raphix.fr sudo apt upgrade -y" - sh "ssh raphix@raphix.fr sudo -S -u gitlab-ci /home/gitlab-ci/subsonics_deploy.sh" - - - } - - } - } - } -} From 22411367299288c3363543d10374c1d3e4132549 Mon Sep 17 00:00:00 2001 From: Raphix Date: Tue, 16 Apr 2024 16:05:21 +0200 Subject: [PATCH 5/5] Version 2.1.0 - Passage sur Lavalink V4 et Moonlink.js --- .gitignore | 11 +- DONTREADME.md | 17 - Jenkinsfile_ntpd => Jenkinsfile | 0 node_modules/moonlink.js/LICENSE | 172 ++++++++ node_modules/moonlink.js/README.md | 216 +++++++++ node_modules/moonlink.js/dist/index.d.ts | 14 + node_modules/moonlink.js/dist/index.js | 31 ++ node_modules/moonlink.js/dist/index.mjs | 17 + .../database-1094727789682380922.json | 5 + .../dist/src/@Entities/MoonlinkNode.d.ts | 44 ++ .../dist/src/@Entities/MoonlinkNode.js | 352 +++++++++++++++ .../dist/src/@Entities/MoonlinkPlayer.d.ts | 52 +++ .../dist/src/@Entities/MoonlinkPlayer.js | 415 ++++++++++++++++++ .../dist/src/@Entities/MoonlinkQueue.d.ts | 19 + .../dist/src/@Entities/MoonlinkQueue.js | 99 +++++ .../dist/src/@Managers/MoonlinkManager.d.ts | 61 +++ .../dist/src/@Managers/MoonlinkManager.js | 148 +++++++ .../dist/src/@Managers/NodeManager.d.ts | 19 + .../dist/src/@Managers/NodeManager.js | 89 ++++ .../dist/src/@Managers/PlayerManager.d.ts | 19 + .../dist/src/@Managers/PlayerManager.js | 160 +++++++ .../src/@Services/MoonlinkMakeRequest.d.ts | 7 + .../dist/src/@Services/MoonlinkMakeRequest.js | 128 ++++++ .../dist/src/@Services/MoonlinkRestFul.d.ts | 28 ++ .../dist/src/@Services/MoonlinkRestFul.js | 112 +++++ .../dist/src/@Services/MoonlinkWebSocket.d.ts | 19 + .../dist/src/@Services/MoonlinkWebSocket.js | 243 ++++++++++ .../moonlink.js/dist/src/@Typings/index.d.ts | 267 +++++++++++ .../moonlink.js/dist/src/@Typings/index.js | 2 + .../dist/src/@Utils/MoonlinkDatabase.d.ts | 15 + .../dist/src/@Utils/MoonlinkDatabase.js | 113 +++++ .../dist/src/@Utils/MoonlinkFilters.d.ts | 29 ++ .../dist/src/@Utils/MoonlinkFilters.js | 131 ++++++ .../dist/src/@Utils/MoonlinkTrack.d.ts | 20 + .../dist/src/@Utils/MoonlinkTrack.js | 52 +++ .../dist/src/@Utils/Structure.d.ts | 13 + .../moonlink.js/dist/src/@Utils/Structure.js | 46 ++ node_modules/moonlink.js/package.json | 55 +++ src/modules/discord-bot.js | 6 +- src/modules/sub-list.js | 13 +- src/web/public/javascript/player.js | 126 +++--- src/web/public/javascript/queue.js | 2 +- src/web/templates/index.ejs | 2 +- 43 files changed, 3298 insertions(+), 91 deletions(-) delete mode 100644 DONTREADME.md rename Jenkinsfile_ntpd => Jenkinsfile (100%) create mode 100644 node_modules/moonlink.js/LICENSE create mode 100644 node_modules/moonlink.js/README.md create mode 100644 node_modules/moonlink.js/dist/index.d.ts create mode 100644 node_modules/moonlink.js/dist/index.js create mode 100644 node_modules/moonlink.js/dist/index.mjs create mode 100644 node_modules/moonlink.js/dist/src/@Datastore/database-1094727789682380922.json create mode 100644 node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.js create mode 100644 node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.js create mode 100644 node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.js create mode 100644 node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.js create mode 100644 node_modules/moonlink.js/dist/src/@Managers/NodeManager.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Managers/NodeManager.js create mode 100644 node_modules/moonlink.js/dist/src/@Managers/PlayerManager.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Managers/PlayerManager.js create mode 100644 node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.js create mode 100644 node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.js create mode 100644 node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.js create mode 100644 node_modules/moonlink.js/dist/src/@Typings/index.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Typings/index.js create mode 100644 node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.js create mode 100644 node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.js create mode 100644 node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.js create mode 100644 node_modules/moonlink.js/dist/src/@Utils/Structure.d.ts create mode 100644 node_modules/moonlink.js/dist/src/@Utils/Structure.js create mode 100644 node_modules/moonlink.js/package.json diff --git a/.gitignore b/.gitignore index 987f48d..16feaf4 100644 --- a/.gitignore +++ b/.gitignore @@ -42,9 +42,12 @@ build/Release # Dependency directories -node_modules/ -!node_modules/moonlink.js/ -!node_modules/moonlink.js/dist/ +# Ignorer tous les dossiers dans node_modules +node_modules/* + +# Ne pas ignorer node_modules/moonlink.js et ses sous-dossiers +!node_modules/moonlink.js +!node_modules/moonlink.js/** jspm_packages/ @@ -96,7 +99,7 @@ out # Nuxt.js build / generate output .nuxt -dist + # Gatsby files .cache/ diff --git a/DONTREADME.md b/DONTREADME.md deleted file mode 100644 index cd802b1..0000000 --- a/DONTREADME.md +++ /dev/null @@ -1,17 +0,0 @@ -# **Easter Egg Subsonics** - -> Un savant fou fait des recherches sur les gens du CLP et a caché son système et ses recherches sur le site du bot - -**Etapes** - -* Page caché -* Confirmation avec le bot -* Erreur assembler le programme -* Accès aux donnés - - -# Idéés - -- Faille dans le bot (à) la recherche -- C'est moi le grand méchant et il doivent arrêter mon plan macchiavélique -- Etape : Me parler pour me soutirer des infos : Genre une histoire \ No newline at end of file diff --git a/Jenkinsfile_ntpd b/Jenkinsfile similarity index 100% rename from Jenkinsfile_ntpd rename to Jenkinsfile diff --git a/node_modules/moonlink.js/LICENSE b/node_modules/moonlink.js/LICENSE new file mode 100644 index 0000000..cee9c3c --- /dev/null +++ b/node_modules/moonlink.js/LICENSE @@ -0,0 +1,172 @@ +Open Software License ("OSL") v. 3.0 + +This Open Software License (the "License") applies to any original work of +authorship (the "Original Work") whose owner (the "Licensor") has placed the +following licensing notice adjacent to the copyright notice for the Original +Work: + + Licensed under the Open Software License version 3.0 + +1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free, +non-exclusive, sublicensable license, for the duration of the copyright, to do +the following: + + a) to reproduce the Original Work in copies, either alone or as part of a + collective work; + + b) to translate, adapt, alter, transform, modify, or arrange the Original + Work, thereby creating derivative works ("Derivative Works") based upon the + Original Work; + + c) to distribute or communicate copies of the Original Work and Derivative + Works to the public, with the proviso that copies of Original Work or + Derivative Works that You distribute or communicate shall be licensed under + this Open Software License; + + d) to perform the Original Work publicly; and + + e) to display the Original Work publicly. + +2) Grant of Patent License. Licensor grants You a worldwide, royalty-free, +non-exclusive, sublicensable license, under patent claims owned or controlled +by the Licensor that are embodied in the Original Work as furnished by the +Licensor, for the duration of the patents, to make, use, sell, offer for sale, +have made, and import the Original Work and Derivative Works. + +3) Grant of Source Code License. The term "Source Code" means the preferred +form of the Original Work for making modifications to it and all available +documentation describing how to modify the Original Work. Licensor agrees to +provide a machine-readable copy of the Source Code of the Original Work along +with each copy of the Original Work that Licensor distributes. Licensor +reserves the right to satisfy this obligation by placing a machine-readable +copy of the Source Code in an information repository reasonably calculated to +permit inexpensive and convenient access by You for as long as Licensor +continues to distribute the Original Work. + +4) Exclusions From License Grant. Neither the names of Licensor, nor the names +of any contributors to the Original Work, nor any of their trademarks or +service marks, may be used to endorse or promote products derived from this +Original Work without express prior permission of the Licensor. Except as +expressly stated herein, nothing in this License grants any license to +Licensor's trademarks, copyrights, patents, trade secrets or any other +intellectual property. No patent license is granted to make, use, sell, offer +for sale, have made, or import embodiments of any patent claims other than the +licensed claims defined in Section 2. No license is granted to the trademarks +of Licensor even if such marks are included in the Original Work. Nothing in +this License shall be interpreted to prohibit Licensor from licensing under +terms different from this License any Original Work that Licensor otherwise +would have a right to license. + +5) External Deployment. The term "External Deployment" means the use, +distribution, or communication of the Original Work or Derivative Works in any +way such that the Original Work or Derivative Works may be used by anyone +other than You, whether those works are distributed or communicated to those +persons or made available as an application intended for use over a network. +As an express condition for the grants of license hereunder, You must treat +any External Deployment by You of the Original Work or a Derivative Work as a +distribution under section 1(c). + +6) Attribution Rights. You must retain, in the Source Code of any Derivative +Works that You create, all copyright, patent, or trademark notices from the +Source Code of the Original Work, as well as any notices of licensing and any +descriptive text identified therein as an "Attribution Notice." You must cause +the Source Code for any Derivative Works that You create to carry a prominent +Attribution Notice reasonably calculated to inform recipients that You have +modified the Original Work. + +7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that +the copyright in and to the Original Work and the patent rights granted herein +by Licensor are owned by the Licensor or are sublicensed to You under the +terms of this License with the permission of the contributor(s) of those +copyrights and patent rights. Except as expressly stated in the immediately +preceding sentence, the Original Work is provided under this License on an "AS +IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without +limitation, the warranties of non-infringement, merchantability or fitness for +a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK +IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this +License. No license to the Original Work is granted by this License except +under this disclaimer. + +8) Limitation of Liability. Under no circumstances and under no legal theory, +whether in tort (including negligence), contract, or otherwise, shall the +Licensor be liable to anyone for any indirect, special, incidental, or +consequential damages of any character arising as a result of this License or +the use of the Original Work including, without limitation, damages for loss +of goodwill, work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses. This limitation of liability shall not +apply to the extent applicable law prohibits such limitation. + +9) Acceptance and Termination. If, at any time, You expressly assented to this +License, that assent indicates your clear and irrevocable acceptance of this +License and all of its terms and conditions. If You distribute or communicate +copies of the Original Work or a Derivative Work, You must make a reasonable +effort under the circumstances to obtain the express assent of recipients to +the terms of this License. This License conditions your rights to undertake +the activities listed in Section 1, including your right to create Derivative +Works based upon the Original Work, and doing so without honoring these terms +and conditions is prohibited by copyright law and international treaty. +Nothing in this License is intended to affect copyright exceptions and +limitations (including "fair use" or "fair dealing"). This License shall +terminate immediately and You may no longer exercise any of the rights granted +to You by this License upon your failure to honor the conditions in Section +1(c). + +10) Termination for Patent Action. This License shall terminate automatically +and You may no longer exercise any of the rights granted to You by this +License as of the date You commence an action, including a cross-claim or +counterclaim, against Licensor or any licensee alleging that the Original Work +infringes a patent. This termination provision shall not apply for an action +alleging patent infringement by combinations of the Original Work with other +software or hardware. + +11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this +License may be brought only in the courts of a jurisdiction wherein the +Licensor resides or in which Licensor conducts its primary business, and under +the laws of that jurisdiction excluding its conflict-of-law provisions. The +application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. Any use of the Original +Work outside the scope of this License or after its termination shall be +subject to the requirements and penalties of copyright or patent law in the +appropriate jurisdiction. This section shall survive the termination of this +License. + +12) Attorneys' Fees. In any action to enforce the terms of this License or +seeking damages relating thereto, the prevailing party shall be entitled to +recover its costs and expenses, including, without limitation, reasonable +attorneys' fees and costs incurred in connection with such action, including +any appeal of such action. This section shall survive the termination of this +License. + +13) Miscellaneous. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary +to make it enforceable. + +14) Definition of "You" in This License. "You" throughout this License, +whether in upper or lower case, means an individual or a legal entity +exercising rights under, and complying with all of the terms of, this License. +For legal entities, "You" includes any entity that controls, is controlled by, +or is under common control with you. For purposes of this definition, +"control" means (i) the power, direct or indirect, to cause the direction or +management of such entity, whether by contract or otherwise, or (ii) ownership +of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial +ownership of such entity. + +15) Right to Use. You may use the Original Work in all ways not otherwise +restricted or conditioned by this License or by law, and Licensor promises not +to interfere with or be responsible for such uses by You. + +16) Modification of This License. This License is Copyright © 2005 Lawrence +Rosen. Permission is granted to copy, distribute, or communicate this License +without modification. Nothing in this License permits You to modify this +License as applied to the Original Work or to Derivative Works. However, You +may modify the text of this License and copy, distribute or communicate your +modified version (the "Modified License") and apply it to other original works +of authorship subject to the following conditions: (i) You may not indicate in +any way that your Modified License is the "Open Software License" or "OSL" and +you may not use those names in the name of your Modified License; (ii) You +must replace the notice specified in the first paragraph above with the notice +"Licensed under " or with a notice of your own +that is not confusingly similar to the notice in this License; and (iii) You +may not claim that your original works are open source software unless your +Modified License has been approved by Open Source Initiative (OSI) and You +comply with its license review and certification process. \ No newline at end of file diff --git a/node_modules/moonlink.js/README.md b/node_modules/moonlink.js/README.md new file mode 100644 index 0000000..aa20d6e --- /dev/null +++ b/node_modules/moonlink.js/README.md @@ -0,0 +1,216 @@ +# Imagine a Music... + +![MoonImage](https://media.discordapp.net/attachments/1211812380850528267/1213558016771625011/48_Sem_Titulo_20231206185046.png?ex=65f5e8fa&is=65e373fa&hm=19170abb2481ba1b9a24bbe136b428bc6cfbfedc95cf53498a10bfbcf735c53d&) +[![NPM](https://nodei.co/npm/moonlink.js.png)](https://nodei.co/npm/moonlink.js) + +[![Made with ♥️ in - Brazil](https://img.shields.io/badge/Made_with_♥️_in-Brazil-ED186A?style=for-the-badge)](https://github.com/1Lucas1apk) + +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/7dd9288acdc94dacaa11ad80f36a9bd3)](https://www.codacy.com/gh/1Lucas1apk/moonlink.js/dashboard?utm_source=github.com&utm_medium=referral&utm_content=1Lucas1apk/moonlink.js&utm_campaign=Badge_Grade) [![Downloads](https://img.shields.io/npm/dt/moonlink.js.svg?color=3884FF)](https://www.npmjs.com/package/moonlink.js) [![Version](https://img.shields.io/npm/v/moonlink.js.svg?color=3884FF&label=version)](https://www.npmjs.com/package/moonlink.js) [![install size](https://packagephobia.com/badge?p=moonlink.js)](https://packagephobia.com/result?p=moonlink.js) ![node](https://img.shields.io/node/v/moonlink.js) [![Netlify Status](https://api.netlify.com/api/v1/badges/4f4a2a64-a8db-4db3-ad1d-0c4ac7274d0e/deploy-status)](https://app.netlify.com/sites/moonlinkjs/deploys) + +Envision a musical journey where creativity knows no bounds, accompanied by the enchantment of the holiday season. 🌌 Moonlink.js invites you to unlock your complete musical potential, designed exclusively for Lavalink clients. Step into a world of seamless communication and fluid interaction, where Moonlink.js elevates your projects to new heights, sprinkled with holiday charm. With full TypeScript support, it empowers your creativity and productivity. 🎵 + +## Table of Contents + +- [Features](#features) +- [Documentation](#documentation) +- [Installation](#installation) +- [How to Use](#how-to-use) +- [Attributions](#attributions) +- [Contributors](#contributors) +- [Final Thanks](#final-thanks) +- [License](#license) +- [Support](#support) + +## Features + +**Moonlink.js** offers essential features for creating exceptional music bots: + +1. **Seamless Communication:** Developed for Lavalink clients, it ensures an uninterrupted musical experience. 🎧 + +2. **Full TypeScript Support:** Enjoy complete TypeScript support to enhance your productivity and creativity. 💻 + +3. **Active Community:** Be part of a community of passionate developers and benefit from our active support system. Our project is not just about minimizing package size but maximizing its quality and potential for developers. 🤝 + +## Documentation + +For comprehensive documentation and more examples, visit [moonlink.js.org](https://moonlink.js.org). 📖 + +## Installation + +```bash +npm install moonlink.js +yarn add moonlink.js +pnpm install moonlink.js +bun install moonlink.js +``` + +## How to Use + +```javascript +// Creating an instance of the Discord.js clien +const client = new Client({ + intents: [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.GuildVoiceStates + ] +}); + +// Configuring the Moonlink.js package +client.moon = new MoonlinkManager( + [ + { + host: "localhost", + port: 2333, + secure: true, + password: "password" + } + ], + { + /* Options */ + }, + (guild, sPayload) => { + // Sending payload information to the server + client.guilds.cache.get(guild).shard.send(JSON.parse(sPayload)); + } +); + +// Event: Node created +client.moon.on("nodeCreate", node => { + console.log(`${node.host} was connected, and the magic is in the air`); +}); + +// Event: Track start +client.moon.on("trackStart", async (player, track) => { + // Sending a message when the track starts playing + client.channels.cache + .get(player.textChannel) + .send(`${track.title} is playing now, bringing holiday joy`); +}); + +// Event: Track end +client.moon.on("trackEnd", async (player, track) => { + // Sending a message when the track finishes playing + client.channels.cache + .get(player.textChannel) + .send(`The track is over, but the magic continues`); +}); + +// Event: Ready +client.on("ready", () => { + // Initializing the Moonlink.js package with the client's user ID + client.moon.init(client.user.id); +}); + +// Event: Raw data +client.on("raw", data => { + // Updating the Moonlink.js package with the necessary data + client.moon.packetUpdate(data); +}); + +// Event: Interaction created +client.on("interactionCreate", async interaction => { + if (!interaction.isChatInputCommand()) return; + let commandName = interaction.commandName; + if (commandName === "play") { + if (!interaction.member.voice.channel) { + // Responding with a message if the user is not in a voice channel + return interaction.reply({ + content: `You are not in a voice channel`, + ephemeral: true + }); + } + + let query = interaction.options.getString("query"); + let player = client.moon.players.create({ + guildId: interaction.guild.id, + voiceChannel: interaction.member.voice.channel.id, + textChannel: interaction.channel.id, + autoPlay: true + }); + + if (!player.connected) { + // Connecting to the voice channel if not already connected + player.connect({ + setDeaf: true, + setMute: false + }); + } + + let res = await client.moon.search({ + query, + source: "youtube", + requester: interaction.user.id + }); + + if (res.loadType === "loadfailed") { + // Responding with an error message if loading fails + return interaction.reply({ + content: `:x: Load failed - the system is not cooperating.` + }); + } else if (res.loadType === "empty") { + // Responding with a message if the search returns no results + return interaction.reply({ + content: `:x: No matches found!` + }); + } + + if (res.loadType === "playlist") { + interaction.reply({ + content: `${res.playlistInfo.name} This playlist has been added to the waiting list, spreading joy` + }); + + for (const track of res.tracks) { + // Adding tracks to the queue if it's a playlist + player.queue.add(track); + } + } else { + player.queue.add(res.tracks[0]); + interaction.reply({ + content: `${res.tracks[0].title} was added to the waiting list` + }); + } + + if (!player.playing) { + // Starting playback if not already playing + player.play(); + } +}); + +// Logging in with the Discord token +client.login(process.env["DISCORD_TOKEN"]); +``` + +## Contributors + +We would like to express our gratitude to the amazing individuals who contributed to this project. Their hard work and dedication have been instrumental in making it a success. 🎉 + +1. **1Lucas1apk** - Lead Developer, responsible for project architecture and key feature implementation. 🚀 + +2. **MotoG.js** - Project Ideator and Designer, contributing to the concept and visual design. 🎨 + +3. **WilsontheWolf** - Contributed to the track position logic in real time, rather than just receiving the payload from lavalink. + +4. **PiscesXD** - First sponsor and contributed to making the shuffle method reversible, and autoLeave. + +5. **Suryansh** - Second contributor and helped discover bugs 🌷 + +Other contributors: Nah, ItzGG, SuperPlayerBot, ddemile, Tasty-Kiwi, rrm, WilsontheWolf, Aertic, 'Forster, Fireball, Ghos't, loulou310 - Xotak + +We sincerely thank all the contributors mentioned above and everyone who contributed to this project in any way. Your support is truly appreciated. 🙏 + +## Final Thanks + +Thank you to everyone who contributed to the growth of moonlink.js, reporting bugs, installing the package and everyone else's patience, I apologize for any time I wasn't able to help someone + +have a great day :) + +## License + +This project is licensed under the [Open Software License ("OSL") v. 3.0](LICENSE) - see the [LICENSE](LICENSE) file for details. + +## Support + +Join our Discord server at [Moonlink.js - Imagine a Music Bot](https://discord.com/invite/xQq2A8vku3) to connect with other users, ask questions, and participate in discussions. 🤝 + +For any inquiries or assistance, we're here to help! 🌟 diff --git a/node_modules/moonlink.js/dist/index.d.ts b/node_modules/moonlink.js/dist/index.d.ts new file mode 100644 index 0000000..fb80339 --- /dev/null +++ b/node_modules/moonlink.js/dist/index.d.ts @@ -0,0 +1,14 @@ +export declare const version: string; +export * from "./src/@Managers/MoonlinkManager"; +export * from "./src/@Managers/PlayerManager"; +export * from "./src/@Managers/NodeManager"; +export * from "./src/@Entities/MoonlinkNode"; +export * from "./src/@Entities/MoonlinkPlayer"; +export * from "./src/@Entities/MoonlinkQueue"; +export * from "./src/@Services/MoonlinkMakeRequest"; +export * from "./src/@Services/MoonlinkRestFul"; +export * from "./src/@Typings/"; +export * from "./src/@Utils/MoonlinkDatabase"; +export * from "./src/@Utils/MoonlinkFilters"; +export * from "./src/@Utils/MoonlinkTrack"; +export * from "./src/@Utils/Structure"; diff --git a/node_modules/moonlink.js/dist/index.js b/node_modules/moonlink.js/dist/index.js new file mode 100644 index 0000000..4f3a8ee --- /dev/null +++ b/node_modules/moonlink.js/dist/index.js @@ -0,0 +1,31 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.version = void 0; +exports.version = require("../package.json").version; +__exportStar(require("./src/@Managers/MoonlinkManager"), exports); +__exportStar(require("./src/@Managers/PlayerManager"), exports); +__exportStar(require("./src/@Managers/NodeManager"), exports); +__exportStar(require("./src/@Entities/MoonlinkNode"), exports); +__exportStar(require("./src/@Entities/MoonlinkPlayer"), exports); +__exportStar(require("./src/@Entities/MoonlinkQueue"), exports); +__exportStar(require("./src/@Services/MoonlinkMakeRequest"), exports); +__exportStar(require("./src/@Services/MoonlinkRestFul"), exports); +__exportStar(require("./src/@Typings/"), exports); +__exportStar(require("./src/@Utils/MoonlinkDatabase"), exports); +__exportStar(require("./src/@Utils/MoonlinkFilters"), exports); +__exportStar(require("./src/@Utils/MoonlinkTrack"), exports); +__exportStar(require("./src/@Utils/Structure"), exports); diff --git a/node_modules/moonlink.js/dist/index.mjs b/node_modules/moonlink.js/dist/index.mjs new file mode 100644 index 0000000..ce35081 --- /dev/null +++ b/node_modules/moonlink.js/dist/index.mjs @@ -0,0 +1,17 @@ +import mod from "./index.js"; + +export default mod; +export const MoonlinkDatabase = mod.MoonlinkDatabase; +export const MoonlinkFilters = mod.MoonlinkFilters; +export const MoonlinkManager = mod.MoonlinkManager; +export const MoonlinkNode = mod.MoonlinkNode; +export const MoonlinkPlayer = mod.MoonlinkPlayer; +export const MoonlinkQueue = mod.MoonlinkQueue; +export const MoonlinkRestFul = mod.MoonlinkRestFul; +export const MoonlinkTrack = mod.MoonlinkTrack; +export const NodeManager = mod.NodeManager; +export const PlayerManager = mod.PlayerManager; +export const Plugin = mod.Plugin; +export const Structure = mod.Structure; +export const makeRequest = mod.makeRequest; +export const version = mod.version; diff --git a/node_modules/moonlink.js/dist/src/@Datastore/database-1094727789682380922.json b/node_modules/moonlink.js/dist/src/@Datastore/database-1094727789682380922.json new file mode 100644 index 0000000..4706c16 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Datastore/database-1094727789682380922.json @@ -0,0 +1,5 @@ +{ + "queue": { + "137291455336022018": [] + } +} \ No newline at end of file diff --git a/node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.d.ts b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.d.ts new file mode 100644 index 0000000..8b42f43 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.d.ts @@ -0,0 +1,44 @@ +/// +import { INode, INodeStats } from "../@Typings"; +import { MoonlinkWebSocket } from "../@Services/MoonlinkWebSocket"; +import { MoonlinkRestFul } from "../../index"; +export declare class MoonlinkNode { + private _manager; + private reconnectTimeout?; + private reconnectAttempts; + private retryAmount; + private retryDelay; + private resumeStatus; + host: string; + identifier?: string; + password: string; + port?: number; + secure: boolean; + regions?: string[]; + http: string; + rest: MoonlinkRestFul; + info?: Record; + version?: string; + resume?: boolean; + resumed?: boolean; + autoResume?: boolean; + resumeTimeout?: number; + sessionId: string; + socket: MoonlinkWebSocket | null; + state: string; + stats: INodeStats | Record; + calls: number; + constructor(node: INode); + get address(): string; + check(node: INode): void; + request(endpoint: string, params: any): Promise; + connect(): Promise; + open(): void; + private reconnect; + protected close(code: number, reason: any): void; + protected error(error: Error): void; + protected message(data: Buffer | string): Promise; + protected handleEvent(payload: any): Promise; + private movePlayers; + private get getAllPlayers(); +} diff --git a/node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.js b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.js new file mode 100644 index 0000000..bb9b196 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkNode.js @@ -0,0 +1,352 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkNode = void 0; +const MoonlinkWebSocket_1 = require("../@Services/MoonlinkWebSocket"); +const index_1 = require("../../index"); +class MoonlinkNode { + _manager = index_1.Structure.manager; + reconnectTimeout; + reconnectAttempts = 1; + retryAmount = 6; + retryDelay = 120000; + resumeStatus = false; + host; + identifier; + password; + port; + secure; + regions; + http; + rest; + info = {}; + version; + resume = index_1.Structure.manager.options?.resume; + resumed; + autoResume = index_1.Structure.manager.options?.autoResume; + resumeTimeout = 30000; + sessionId; + socket; + state = "DISCONNECTED"; + stats = {}; + calls = 0; + constructor(node) { + this.check(node); + this.host = node.host; + this.identifier = node.identifier || null; + this.password = node.password ? node.password : "youshallnotpass"; + this.port = node.port ? node.port : node.secure == true ? 443 : 80; + this.secure = node.secure || false; + this.regions = node.regions; + this.http = `http${node.secure ? "s" : ""}://${this.address}/v4/`; + this.rest = new (index_1.Structure.get("MoonlinkRestFul"))(this); + if (node.sessionId) + this.sessionId = node.sessionId; + this.connect(); + } + get address() { + return `${this.host}:${this.port}`; + } + check(node) { + if (typeof node.host !== "string" && typeof node.host !== "undefined") + throw new Error('@Moonlink(Nodes) - "host" option is not configured correctly'); + if (typeof node.password !== "string" && + typeof node.password !== "undefined") + throw new Error('@Moonlink(Nodes) - the option "password" is not set correctly'); + if ((node.port && typeof node.port !== "number") || + node.port > 65535 || + node.port < 0) + throw new Error('@Moonlink(Nodes) - the "port" option is not set correctly'); + if (typeof node.retryAmount !== "undefined" && + typeof node.retryAmount !== "number") + throw new Error('@Moonlink(Nodes) - the "retryAmount" option is not set correctly'); + if (typeof node.retryDelay !== "undefined" && + typeof node.retryDelay !== "number") + throw new Error('@Moonlink(Nodes) - the "retryDelay" option is not set correctly'); + } + request(endpoint, params) { + this.calls++; + return this.rest.get(`${endpoint}?${params}`); + } + async connect() { + if (this.state == "CONNECTED" || this.state == "READY") + return; + this.state = "CONNECTING"; + let headers = { + Authorization: this.password, + "User-Id": this._manager.options.clientId, + "Client-Name": this._manager.options.clientName + }; + if (this.resume) + headers["Session-Id"] = index_1.Structure.db.get(`sessionId.${this.identifier ?? this.host.replace(/\./g, "-")}`); + this.socket = new MoonlinkWebSocket_1.MoonlinkWebSocket(`ws${this.secure ? "s" : ""}://${this.address}/v4/websocket`, { headers }); + this.socket.on("open", this.open.bind(this)); + this.socket.on("close", this.close.bind(this)); + this.socket.on("message", this.message.bind(this)); + this.socket.on("error", this.error.bind(this)); + } + open() { + if (this.reconnectTimeout) + clearTimeout(this.reconnectTimeout); + this._manager.emit("debug", `@Moonlink(Node) - The Node ${this.identifier ?? this.host} has been connected successfully`); + this._manager.emit("nodeCreate", this); + this.state = "CONNECTED"; + } + reconnect() { + if (this.reconnectAttempts >= this.retryAmount) { + this._manager.emit("debug", `@Moonlink(Node) - Node ${this.identifier ?? this.host} was destroyed due to inactivity, attempts to reconnect were failed`); + this._manager.emit("nodeDestroy", this); + this.socket.close(1000, "destroy"); + this.socket.removeAllListeners(); + } + else { + this.reconnectTimeout = setTimeout(() => { + this.socket.removeAllListeners(); + this.socket = null; + this.state = "RECONNECTING"; + this._manager.emit("nodeReconnect", this); + this.connect(); + this._manager.emit("debug", `@Moonlink(Node) - We are trying to reconnect node ${this.identifier ?? this.host}, attempted number ${this.reconnectAttempts} + `); + if (this.getAllPlayers.length && + this._manager.options?.switchPlayersAnotherNode) + this.movePlayers(); + this.reconnectAttempts++; + }, this.retryDelay); + } + } + close(code, reason) { + if (code !== 1000 || reason !== "destroy") + this.reconnect(); + this._manager.emit("debug", `@Moonlink(Node) - The node connection ${this.identifier ?? this.host} has been closed`); + this._manager.emit("nodeClose", this, code, reason); + this.getAllPlayers.forEach(player => { + player.playing = false; + }); + this.state = "DISCONNECTED"; + } + error(error) { + if (!error) + return; + this._manager.emit("nodeError", this, error); + this._manager.emit("debug", `@Moonlink(Nodes) - The ${this.identifier ?? this.host} an error has occurred: + ${error}`); + } + async message(data) { + if (Array.isArray(data)) + data = Buffer.concat(data); + else if (data instanceof ArrayBuffer) + data = Buffer.from(data); + let payload = JSON.parse(data.toString("utf8")); + if (!payload.op) + return; + this._manager.emit("nodeRaw", this, payload); + switch (payload.op) { + case "ready": + this.sessionId = payload.sessionId; + this.resume + ? index_1.Structure.db.set(`sessionId.${this.identifier ?? this.host.replace(/\./g, "-")}`, this.sessionId) + : null; + this.resumed = payload.resumed; + this.rest.setSessionId(this.sessionId); + this.state = "READY"; + if (!this._manager.initiated && !this.resumed) { + index_1.Structure.db.delete("queue"); + index_1.Structure.db.delete("players"); + } + this._manager.emit("debug", `@Moonlink(Node) - ${this.resumed ? ` session was resumed,` : ``} session is currently ${this.sessionId}`); + this._manager.emit("nodeReady", this, this.sessionId, this.resumed); + if (this.resume) { + this.rest.patch(`sessions/${this.sessionId}`, { + data: { + resuming: this.resume, + timeout: this.resumeTimeout + } + }); + this._manager.emit("debug", `@Moonlink(Nodes) - Resuming configured`); + } + this.version = await this.rest.getVersion(); + this.info = await this.rest.getInfo(); + if (this.autoResume) { + let resumePlayers = this.getAllPlayers; + for (const resumePlayer of resumePlayers) { + resumePlayer.restart(); + } + } + if (this.resumed) { + const resumedPlayers = await this.rest.get(`sessions/${this.sessionId}/players`); + for (const resumedPlayer of resumedPlayers) { + const previousInfosPlayer = index_1.Structure.db.get(`players.${resumedPlayer.guildId}`) || {}; + const player = this._manager.players.create({ + guildId: resumedPlayer.guildId, + voiceChannel: previousInfosPlayer.voiceChannel, + textChannel: previousInfosPlayer.textChannel, + volume: previousInfosPlayer.volume, + loop: previousInfosPlayer.loop, + autoPlay: previousInfosPlayer.autoPlay, + autoLeave: previousInfosPlayer.autoLeave, + node: this.identifier ?? this.host, + notBackup: true + }); + player.previous = previousInfosPlayer.previous; + if (resumedPlayer.track) { + const track = new (index_1.Structure.get("MoonlinkTrack"))(resumedPlayer.track); + player.current = track; + player.current.position = + resumedPlayer.state.position; + await player.restart(); + } + } + this._manager.emit("nodeResumed", this, resumedPlayers); + } + break; + case "stats": + delete payload.op; + this.stats = { ...payload }; + break; + case "playerUpdate": + let player = this._manager.players.get(payload.guildId); + if (!player) + return; + player.ping = payload.state.ping; + if (!player.current) + return; + player.current.position = payload.state.position; + player.current.time = payload.state.time; + this._manager.emit("playerUpdate", player, payload, this); + break; + case "event": + this.handleEvent(payload); + break; + default: + this._manager.emit("nodeError", this, new Error(`@Moonlink(Nodes) - Unexpected op "${payload.op}" with data: ${payload}`)); + } + } + async handleEvent(payload) { + if (!payload) + return; + if (!payload.guildId) + return; + if (!this._manager.players.has(payload.guildId)) + return; + let player = this._manager.players.get(payload.guildId); + switch (payload.type) { + case "TrackStartEvent": { + if (!player.current) + player.current = new (index_1.Structure.get("MoonlinkTrack"))(payload.track); + player.playing = true; + player.paused = false; + this._manager.emit("trackStart", player, player.current); + break; + } + case "TrackEndEvent": { + let track = player.current; + let queue = player.queue.all; + player.playing = false; + if (this._manager.options.previousTracksInArray) + player.previous.push(track); + else + player.previous = track; + if (["loadFailed", "cleanup"].includes(payload.reason)) { + if (!queue) { + player.queue.clear(); + { + this._manager.emit("trackEnd", player, track, payload); + this._manager.emit("queueEnd", player, track); + return; + } + } + player.play(); + return; + } + if (payload.reason === "replaced") { + this._manager.emit("trackEnd", player, track, payload); + return; + } + if (track && player.loop) { + if (player.loop == 1) { + await this.rest.update({ + guildId: payload.guildId, + data: { track: { encoded: payload.track.encoded } } + }); + if (this.resumed) + player.current = new (index_1.Structure.get("MoonlinkTrack"))(payload.track); + return; + } + if (player.loop == 2) { + player.queue.add(new (index_1.Structure.get("MoonlinkTrack"))(payload.track)); + if (!queue || queue.length === 0) + return this._manager.emit("trackEnd", player, track, payload); + player.play(); + return; + } + else { + this._manager.emit("trackEnd", player, track); + this._manager.emit("debug", "@Manager(Nodes) - invalid loop value will be ignored!"); + } + } + if (player.queue.size) { + this._manager.emit("trackEnd", player, track); + player.play(); + return; + } + if (typeof player.autoPlay === "boolean" && + player.autoPlay === true) { + if (payload.reason == "stopped") + return; + let uri = `https://www.youtube.com/watch?v=${track.identifier}&list=RD${track.identifier}`; + let req = await this._manager.search(uri); + if (!req || + !req.tracks || + ["loadFailed", "cleanup"].includes(req.loadType)) + return player.stop(); + let data = req.tracks[Math.floor(Math.random() * Math.floor(req.tracks.length))]; + player.queue.add(data); + player.play(); + return; + } + if (player.autoLeave) { + player.destroy(); + this._manager.emit("autoLeaved", player, track); + } + if (!player.queue.size) { + this._manager.emit("debug", "@Moonlink(Nodes) - The queue is empty"); + this._manager.emit("trackEnd", player, track, payload); + this._manager.emit("queueEnd", player); + player.current = null; + player.queue.clear(); + } + break; + } + case "TrackStuckEvent": { + this._manager.emit("trackStuck", player, player.current); + player.stop(); + break; + } + case "TrackExceptionEvent": { + this._manager.emit("trackError", player, player.current); + player.stop(); + break; + } + case "WebSocketClosedEvent": { + this._manager.emit("socketClosed", player, payload); + break; + } + default: { + const error = new Error(`@Moonlink(Nodes) - unknown event '${payload.type}'.`); + this._manager.emit("nodeError", this, error); + } + } + } + movePlayers() { + this.getAllPlayers.forEach(player => { + let anotherNode = this._manager.nodes.sortByUsage(this._manager.options?.sortNode ?? "players")[0]; + this._manager.emit("debug", `@Moonlink(Node) - Moving player ${player.guildId} to ${anotherNode.identifier ?? anotherNode.host}`); + player.transferNode(anotherNode); + }); + return true; + } + get getAllPlayers() { + return Object.values(this._manager.players.all).filter(player => player.node === this); + } +} +exports.MoonlinkNode = MoonlinkNode; diff --git a/node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.d.ts b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.d.ts new file mode 100644 index 0000000..6c50264 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.d.ts @@ -0,0 +1,52 @@ +/// +import { EventEmitter } from "node:events"; +import { MoonlinkManager, MoonlinkQueue, MoonlinkNode, MoonlinkTrack, MoonlinkFilters } from "../../index"; +import { MoonlinkWebSocket } from "../@Services/MoonlinkWebSocket"; +import { IPlayerData, connectOptions } from "../@Typings"; +export declare class MoonlinkPlayer { + manager: MoonlinkManager; + guildId: string; + textChannel: string; + voiceChannel: string; + voiceRegion: string; + autoPlay: boolean | null; + autoLeave: boolean | null; + connected: boolean | null; + playing: boolean | null; + paused: boolean | null; + loop: number | null; + volume: number; + ping: number; + queue: MoonlinkQueue; + filters: MoonlinkFilters; + current: Record; + previous: MoonlinkTrack[] | MoonlinkTrack | Record; + data: Record; + node: MoonlinkNode | any; + voiceReceiverWs: MoonlinkWebSocket | any; + constructor(data: IPlayerData); + set(key: string, value: unknown): void; + get(key: string): T; + setTextChannel(channelId: string): boolean; + setVoiceChannel(channelId: string): boolean; + setAutoLeave(mode?: boolean | null): boolean | null; + setAutoPlay(mode: boolean): boolean; + connect(options: connectOptions): boolean | null; + disconnect(): boolean; + restart(): Promise; + play(track?: MoonlinkTrack | string): Promise; + pause(): Promise; + resume(): Promise; + private updatePlaybackStatus; + stop(destroy?: boolean): Promise; + skip(position?: number): Promise; + setVolume(percent: number): Promise; + setLoop(mode: number | string | null): number | string | null; + destroy(): Promise; + private validateNumberParam; + seek(position: number): Promise; + shuffle(): boolean; + transferNode(node: MoonlinkNode | string): Promise; + listenVoice(): EventEmitter | boolean; + stopListeningVoice(): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.js b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.js new file mode 100644 index 0000000..8acd768 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkPlayer.js @@ -0,0 +1,415 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkPlayer = void 0; +const node_events_1 = require("node:events"); +const index_1 = require("../../index"); +const MoonlinkWebSocket_1 = require("../@Services/MoonlinkWebSocket"); +class MoonlinkPlayer { + manager = index_1.Structure.manager; + guildId; + textChannel; + voiceChannel; + voiceRegion; + autoPlay; + autoLeave; + connected; + playing; + paused; + loop; + volume; + ping; + queue; + filters; + current; + previous; + data; + node; + voiceReceiverWs; + constructor(data) { + this.guildId = data.guildId; + this.textChannel = data.textChannel; + this.voiceChannel = data.voiceChannel; + this.voiceRegion = data.voiceRegion; + this.autoPlay = data.autoPlay; + this.autoLeave = data.autoLeave || false; + this.connected = data.connected || false; + this.playing = data.playing || false; + this.paused = data.paused || false; + this.loop = data.loop || 0; + this.volume = data.volume || 100; + this.ping = data.ping || 0; + this.queue = new (index_1.Structure.get("MoonlinkQueue"))(this.manager, this.guildId); + this.current = null; + this.previous = []; + this.data = {}; + this.node = this.manager.nodes.get(data.node); + this.filters = new (index_1.Structure.get("MoonlinkFilters"))(this); + this.voiceReceiverWs = null; + if (!data.notBackup && this.manager.options.resume) + this.manager.players.backup(this); + } + set(key, value) { + this.data[key] = value; + } + get(key) { + return this.data[key] || null; + } + setTextChannel(channelId) { + if (!channelId) { + throw new Error('@Moonlink(Player) - "channelId" option is empty'); + } + if (typeof channelId !== "string") { + throw new Error('@Moonlink(Player) - option "channelId" is different from a string'); + } + this.manager.emit("playerSetTextChannel", this, this.textChannel, channelId); + this.textChannel = channelId; + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + setVoiceChannel(channelId) { + if (!channelId) { + throw new Error('@Moonlink(Player) - "channelId" option is empty'); + } + if (typeof channelId !== "string") { + throw new Error('@Moonlink(Player) - option "channelId" is different from a string'); + } + this.manager.emit("playerSetVoiceChannel", this, this.voiceChannel, channelId); + this.voiceChannel = channelId; + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + setAutoLeave(mode) { + if (typeof mode !== "boolean") { + throw new Error('@Moonlink(Player) - "mode" option is empty or different from a boolean'); + } + mode ? mode : (mode = !this.autoLeave); + this.autoLeave = mode; + this.manager.emit("playerAutoLeaveTriggered", this, mode); + if (this.manager.options.resume) + this.manager.players.backup(this); + return mode; + } + setAutoPlay(mode) { + if (typeof mode !== "boolean") { + throw new Error('@Moonlink(Player) - "mode" option is empty or different from a boolean'); + } + this.autoPlay = mode; + this.manager.emit("playerAutoPlayTriggered", this, mode); + if (this.manager.options.resume) + this.manager.players.backup(this); + return mode; + } + connect(options) { + options = options || { setDeaf: false, setMute: false }; + const { setDeaf, setMute } = options; + this.manager._SPayload(this.guildId, JSON.stringify({ + op: 4, + d: { + guild_id: this.guildId, + channel_id: this.voiceChannel, + self_mute: setMute, + self_deaf: setDeaf + } + })); + this.connected = true; + this.manager.emit("playerConnected", this); + return true; + } + disconnect() { + this.manager._SPayload(this.guildId, JSON.stringify({ + op: 4, + d: { + guild_id: this.guildId, + channel_id: null, + self_mute: false, + self_deaf: false + } + })); + this.connected = false; + this.voiceChannel = null; + return true; + } + async restart() { + this.connect({ + setDeaf: true, + setMute: false + }); + await this.manager.players.attemptConnection(this.guildId); + if (!this.current && this.queue.size) { + this.play(); + return; + } + else { + await this.node.rest.update({ + guildId: this.guildId, + data: { + track: { + encoded: this.current.encoded + }, + position: this.current.position, + volume: this.volume + } + }); + } + this.manager.emit("playerRestarted", this); + if (this.manager.options.resume) + this.manager.players.backup(this); + } + async play(track) { + if (!track && !this.queue.size) + return false; + let data = track + ? track + : this.queue.shift(); + if (!data) + return false; + if (this.loop && Object.keys(this.current).length != 0) { + this.current.time ? (this.current.time = 0) : false; + this.ping = undefined; + this.queue.push(this.current); + } + if (typeof data == "string") { + try { + let resolveTrack = await this.node.rest.decodeTrack(data); + data = new (index_1.Structure.get("MoonlinkTrack"))(resolveTrack, null); + } + catch (err) { + this.manager.emit("debug", "@Moonlink(Player) - Fails when trying to decode a track " + + data + + ", error: " + + err); + return; + } + } + this.current = data; + await this.node.rest.update({ + guildId: this.guildId, + data: { + track: { + encoded: data.encoded + }, + volume: this.volume + } + }); + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + async pause() { + if (this.paused) + return true; + await this.updatePlaybackStatus(true); + this.manager.emit("playerPaused", this); + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + async resume() { + if (this.playing) + return true; + await this.updatePlaybackStatus(false); + this.manager.emit("playerResume", this); + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + async updatePlaybackStatus(paused) { + await this.node.rest.update({ + guildId: this.guildId, + data: { paused } + }); + this.paused = paused; + this.playing = !paused; + } + async stop(destroy) { + if (!this.queue.size) { + await this.node.rest.update({ + guildId: this.guildId, + data: { + track: { encoded: null } + } + }); + if (this.manager.options.resume) + this.manager.players.backup(this); + } + this.manager.emit("playerStopped", this, this.current); + this.manager.options?.destroyPlayersStopped && destroy + ? this.destroy() + : this.queue.clear(); + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + async skip(position) { + if (position) { + this.validateNumberParam(position, "position"); + let queue = this.queue.all(); + if (!queue[position - 1]) { + throw new Error(`@Moonlink(Player) - the indicated position does not exist, make security in your code to avoid errors`); + } + let data = queue.splice(position - 1, 1)[0]; + this.manager.emit("playerSkipped", this, this.current, data); + this.current = data; + this.queue.setQueue(queue); + await this.play(data); + return true; + } + if (this.queue.size) { + this.manager.emit("playerSkipped", this, this.current, this.queue.all[0]); + this.play(); + return false; + } + else { + this.stop(); + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + } + async setVolume(percent) { + if (typeof percent == "undefined" || isNaN(percent)) { + throw new Error('@Moonlink(Player) - option "percent" is empty or different from a number'); + } + var beforeChange = this.volume; + this.volume = percent; + await this.node.rest.update({ + guildId: this.guildId, + data: { volume: percent } + }); + this.manager.emit("playerVolumeChanged", this, beforeChange, percent); + + if (this.manager.options.resume) + this.manager.players.backup(this); + return percent; + } + setLoop(mode) { + if (typeof mode == "string" && + ["off", "track", "queue"].includes(mode)) { + mode == "track" + ? (mode = 1) + : mode == "queue" + ? (mode = 2) + : (mode = 0); + } + if (typeof mode !== "number" || + (mode !== null && (mode < 0 || mode > 2))) { + throw new Error('@Moonlink(Player) - the option "mode" is different from a number and string or the option does not exist'); + } + this.manager.emit("playerLoopSet", this, this.loop, mode); + this.loop = mode; + if (this.manager.options.resume) + this.manager.players.backup(this); + return mode; + } + async destroy() { + if (this.connected) + this.disconnect(); + await this.node.rest.destroy(this.guildId); + this.queue.clear(); + this.manager.players.delete(this.guildId); + this.manager.emit("debug", "@Moonlink(Player) - Destroyed player " + this.guildId); + this.manager.emit("playerDestroyed", this.guildId); + if (this.manager.options.resume) + this.manager.players.backup(this); + return true; + } + validateNumberParam(param, paramName) { + if (typeof param !== "number") { + throw new Error(`@Moonlink(Player) - option "${paramName}" is empty or different from a number`); + } + } + async seek(position) { + this.validateNumberParam(position, "position"); + if (position >= this.current.duration) { + throw new Error(`@Moonlink(Player) - parameter "position" is greater than the duration of the current track`); + } + if (!this.current.isSeekable && this.current.isStream) { + throw new Error(`@Moonlink(Player) - seek function cannot be applied on live video or cannot be applied in "isSeekable"`); + } + this.manager.emit("playerSeeking", this, this.current.position, position); + await this.node.rest.update({ + guildId: this.guildId, + data: { position } + }); + if (this.manager.options.resume) + this.manager.players.backup(this); + return position; + } + shuffle() { + if (!this.queue.size) { + throw new Error("@Moonlink(Player)the one that is empty so that the shuffle can be performed"); + } + let oldQueue = Array.from(this.queue.all); + let shuffleStatus = this.queue.shuffle(); + this.manager.emit("playerShuffled", this, oldQueue, this.queue.all, shuffleStatus); + if (this.manager.options.resume) + this.manager.players.backup(this); + return shuffleStatus; + } + async transferNode(node) { + typeof node == "string" ? (node = this.manager.nodes.get(node)) : null; + if (!node) + return false; + this.node = node; + if (this.current || this.queue.size) { + await this.restart(); + return true; + } + else { + await this.manager.players.attemptConnection(this.guildId); + return true; + } + } + listenVoice() { + if (!this.node.info.isNodeLink) + return false; + this.voiceReceiverWs = new MoonlinkWebSocket_1.MoonlinkWebSocket(`ws${this.node.secure ? "s" : ""}://${this.node.address}/connection/data`, { + headers: { + Authorization: this.node.password, + "Client-Name": `Moonlink/${this.manager.version}`, + "guild-id": this.guildId, + "user-id": this.manager.clientId + } + }); + const listener = new node_events_1.EventEmitter(); + this.voiceReceiverWs.on("message", (data) => { + const payload = JSON.parse(data); + switch (payload?.type) { + case "startSpeakingEvent": { + listener.emit("start", { + ...payload.data + }); + break; + } + case "endSpeakingEvent": { + payload.data.data = Buffer.from(payload.data.data, "base64"); + listener.emit("end", { + ...payload.data + }); + break; + } + default: { + listener.emit("unknown", { + ...payload + }); + } + } + }); + this.voiceReceiverWs.on("close", () => { + listener.emit("close"); + }); + this.voiceReceiverWs.on("error", error => { + listener.emit("error", error); + }); + return listener; + } + stopListeningVoice() { + if (!this.voiceReceiverWs) + return; + this.voiceReceiverWs.close(); + this.voiceReceiverWs = null; + } +} +exports.MoonlinkPlayer = MoonlinkPlayer; diff --git a/node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.d.ts b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.d.ts new file mode 100644 index 0000000..1d6182f --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.d.ts @@ -0,0 +1,19 @@ +import { MoonlinkDatabase, MoonlinkManager, MoonlinkTrack } from "../.."; +export declare class MoonlinkQueue { + db: MoonlinkDatabase; + private guildId; + private manager; + constructor(manager: MoonlinkManager, guildId: string); + add(data: MoonlinkTrack, position?: number): void; + has(identifier: string): boolean; + first(): any; + shift(): any; + push(data: any): void; + clear(): boolean; + get size(): number; + shuffle(): boolean; + remove(position: number): boolean; + get all(): any; + getQueue(): MoonlinkTrack[]; + setQueue(queue: MoonlinkTrack[]): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.js b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.js new file mode 100644 index 0000000..15860c9 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Entities/MoonlinkQueue.js @@ -0,0 +1,99 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkQueue = void 0; +const __1 = require("../.."); +class MoonlinkQueue { + db = __1.Structure.db; + guildId; + manager; + constructor(manager, guildId) { + if (!manager || !guildId) { + throw new Error("[ @Moonlink/Queue ]: Invalid constructor arguments"); + } + this.guildId = guildId; + this.manager = __1.Structure.manager; + } + add(data, position) { + if (!data) + throw new Error('[ @Moonlink/Queue ]: "data" option is empty'); + let queue = this.getQueue(); + position = + position !== undefined && position >= 1 + ? position - 1 + : queue.length; + if (position < 0 || position > queue.length) { + throw new Error("@Moonlink(Queue) - Invalid position specified"); + } + queue.splice(position, 0, data); + this.setQueue(queue); + } + has(identifier) { + if (!identifier || typeof identifier !== "string") { + throw new Error("@Moonlink(Queue) - Invalid identifier specified"); + } + const queue = this.getQueue(); + return queue.some(track => track.identifier === identifier); + } + first() { + const queue = this.getQueue(); + return queue.length > 0 ? queue[0] : null; + } + shift() { + let queue = this.getQueue(); + if (!queue.length) + return null; + let track = queue.shift(); + this.setQueue(queue); + return track; + } + push(data) { + let queue = this.getQueue(); + queue.push(data); + this.setQueue(queue); + } + clear() { + const queue = this.getQueue(); + if (queue.length > 0) { + this.setQueue([]); + return true; + } + return false; + } + get size() { + return this.getQueue().length; + } + shuffle() { + const currentQueue = this.all; + for (let i = currentQueue.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [currentQueue[i], currentQueue[j]] = [ + currentQueue[j], + currentQueue[i] + ]; + } + this.setQueue(currentQueue); + return true; + } + remove(position) { + if (!position || typeof position !== "number" || position < 1) { + throw new Error("[ @Moonlink/Queue ]: Invalid position specified"); + } + const queue = this.getQueue(); + if (position > queue.length) { + throw new Error("[ @Moonlink/Queue ]: Position exceeds queue length"); + } + queue.splice(position - 1, 1); + this.setQueue(queue); + return true; + } + get all() { + return this.getQueue(); + } + getQueue() { + return this.db.get(`queue.${this.guildId}`) || []; + } + setQueue(queue) { + this.db.set(`queue.${this.guildId}`, queue); + } +} +exports.MoonlinkQueue = MoonlinkQueue; diff --git a/node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.d.ts b/node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.d.ts new file mode 100644 index 0000000..3be779b --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.d.ts @@ -0,0 +1,61 @@ +/// +import { EventEmitter } from "node:events"; +import { MoonlinkPlayer, MoonlinkTrack, MoonlinkNode, PlayerManager, NodeManager } from "../../index"; +import { INode, IOptions, VoicePacket, SearchResult, SearchQuery } from "../@Typings"; +export interface MoonlinkEvents { + autoLeaved: (player: MoonlinkPlayer, track?: any) => void; + debug: (...args: any) => void; + nodeCreate: (node: MoonlinkNode) => void; + nodeReady: (node: MoonlinkNode, sessionId: string, resumed: boolean) => void; + nodeDestroy: (node: MoonlinkNode) => void; + nodeResumed: (node: MoonlinkNode, players: MoonlinkEvents[]) => void; + nodeReconnect: (node: MoonlinkNode) => void; + nodeClose: (node: MoonlinkNode, code: number, reason: string) => void; + nodeRaw: (node: MoonlinkNode, payload: object) => void; + nodeError: (node: MoonlinkNode, error: Error) => void; + trackStart: (player: MoonlinkPlayer, current: any) => void; + trackEnd: (player: MoonlinkPlayer, track: any, payload?: Record) => void; + trackStuck: (player: MoonlinkPlayer, track: any) => void; + trackError: (player: MoonlinkPlayer, track: any) => void; + queueEnd: (player: MoonlinkPlayer, track?: any) => void; + playerConnected: (player: MoonlinkPlayer) => void; + playerCreated: (guildId: string) => void; + playerPaused: (player: MoonlinkPlayer) => void; + playerRestarted: (player: MoonlinkPlayer) => void; + playerResume: (player: MoonlinkPlayer) => void; + playerStopped: (player: MoonlinkPlayer, current: MoonlinkTrack) => void; + playerSetVoiceChannel: (player: MoonlinkPlayer, oldChannel: string, newChannel: string) => void; + playerAutoPlayTriggered: (player: MoonlinkPlayer, mode: boolean) => void; + playerAutoLeaveTriggered: (player: MoonlinkPlayer, mode: boolean) => void; + playerSetTextChannel: (player: MoonlinkPlayer, oldChannel: string, newChannel: string) => void; + playerVolumeChanged: (player: MoonlinkPlayer, oldVolume: number, newVolume: number) => void; + playerSkipped: (player: MoonlinkPlayer, oldCurrent: MoonlinkTrack, newCurrent: MoonlinkTrack) => void; + playerSeeking: (player: MoonlinkPlayer, oldPosition: number, newPosition: number) => void; + playerLoopSet: (player: MoonlinkPlayer, oldMode: number, mode: number) => void; + playerShuffled: (player: MoonlinkPlayer, oldQueue: unknown[], newQueue: MoonlinkTrack[], status: boolean) => void; + playerMove: (player: MoonlinkPlayer, newVoiceChannel: string, oldVoiceChannel: string) => void; + playerDisconnect: (player: MoonlinkPlayer) => void; + playerDestroyed: (guildId: string) => void; + playerUpdate: (player: MoonlinkPlayer, node: MoonlinkNode, payload: Record) => void; + socketClosed: (player: MoonlinkPlayer, track: MoonlinkTrack) => void; +} +export declare interface MoonlinkManager { + on(event: K, listener: MoonlinkEvents[K]): this; + once(event: K, listener: MoonlinkEvents[K]): this; + emit(event: K, ...args: Parameters): boolean; + off(event: K, listener: MoonlinkEvents[K]): this; +} +export declare class MoonlinkManager extends EventEmitter { + clientId: string; + readonly _nodes: INode[]; + readonly _SPayload: Function; + readonly players: PlayerManager; + readonly nodes: NodeManager; + readonly version: number; + options: IOptions; + initiated: boolean; + constructor(nodes: INode[], options: IOptions, SPayload: Function); + init(clientId?: string): Promise; + search(options: string | SearchQuery): Promise; + packetUpdate(packet: VoicePacket): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.js b/node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.js new file mode 100644 index 0000000..bcc00d6 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Managers/MoonlinkManager.js @@ -0,0 +1,148 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkManager = void 0; +const node_events_1 = require("node:events"); +const index_1 = require("../../index"); +class MoonlinkManager extends node_events_1.EventEmitter { + clientId; + _nodes; + _SPayload; + players; + nodes; + version = require("../../index").version; + options; + initiated = false; + constructor(nodes, options, SPayload) { + super(); + this._nodes = nodes; + this._SPayload = SPayload; + this.players = new (index_1.Structure.get("PlayerManager"))(); + this.nodes = new (index_1.Structure.get("NodeManager"))(); + this.options = options; + if (options.plugins) { + options.plugins.forEach(plugin => { + plugin.load(this); + }); + } + if (!this.options.clientName) + this.options.clientName = `Moonlink/${this.version} (https://github.com/Ecliptia/moonlink.js)`; + } + async init(clientId) { + if (this.initiated) + return this; + this.emit("debug", "@Moonlink - moonlink.js has started the initialization process, do not attempt to use functions until everything is initialized correctly "); + if (!clientId && !this.options.clientId) + throw new TypeError('@Moonlink(Manager): "clientId" option is required.'); + this.options.clientId = clientId; + this.clientId = clientId; + index_1.Structure.init(this); + await index_1.Structure.db.fetch(); + this.nodes.init(); + this.players.init(); + this.initiated = true; + return this; + } + async search(options) { + return new Promise(async (resolve, reject) => { + try { + if (!options) { + throw new Error("@Moonlink(Manager) - the search option has to be in string format or in an array"); + } + let query; + let source; + let requester; + let node; + if (typeof options === "object") { + query = options.query; + source = options.source; + requester = options.requester; + node = options.node; + } + else { + query = options; + } + if (requester && + typeof requester !== "string" && + typeof requester !== "object") { + throw new Error('@Moonlink(Manager) - The "requester" option in the search function must be in string or array format'); + } + if (source && typeof source !== "string") { + throw new Error("@Moonlink(Manager) - the source option has to be in string format"); + } + if (typeof query !== "string" && typeof query !== "object") { + throw new Error("@Moonlink(Manager) - (search) the search option has to be in string or array format"); + } + (node && (node = this.nodes.get(node))) ?? + (node = this.nodes.sortByUsage("memory")[0]); + const sources = { + youtube: "ytsearch", + youtubemusic: "ytmsearch", + soundcloud: "scsearch" + }; + let searchIdentifier = query.startsWith("http://") || query.startsWith("https://") + ? query + : source + ? sources[source] + ? `${sources[source]}:${query}` + : `${source}:${query}` + : `ytsearch:${query}`; + const params = new URLSearchParams({ + identifier: searchIdentifier + }); + const res = await node.request("loadtracks", params); + if (["error", "empty"].includes(res.loadType)) { + this.emit("debug", "@Moonlink(Manager) - not found or there was an error loading the track"); + return resolve(res); + } + if (["track"].includes(res.loadType)) { + res.data = [res.data]; + } + if (["playlist"].includes(res.loadType)) { + res.playlistInfo = { + duration: res.data.tracks.reduce((acc, cur) => acc + cur.info.length, 0), + name: res.data.info.name, + selectedTrack: res.data.info.selectedTrack + }; + res.pluginInfo = res.data.pluginInfo; + res.data = [...res.data.tracks]; + } + const tracks = res.data.map(track => new (index_1.Structure.get("MoonlinkTrack"))(track, requester)); + resolve({ + ...res, + tracks + }); + } + catch (error) { + this.emit("debug", "@Moonlink(Manager) - An error occurred: " + error); + reject(error); + } + }); + } + packetUpdate(packet) { + const { t, d } = packet; + if (!["VOICE_STATE_UPDATE", "VOICE_SERVER_UPDATE"].includes(t)) + return; + const update = d; + const guildId = update.guild_id; + const player = this.players.get(guildId); + if (!update.token && !update.session_id) + return; + if (t === "VOICE_SERVER_UPDATE") { + this.players.handleVoiceServerUpdate(update, guildId); + } + if (t === "VOICE_STATE_UPDATE" && update.user_id === this.clientId) { + if (!player) + return; + if (!update.channel_id) { + this.players.handlePlayerDisconnect(guildId); + } + if (update.channel_id && + update.channel_id !== player.voiceChannel) { + this.players.handlePlayerMove(update.channel_id, player.voiceChannel, guildId); + } + this.players.updateVoiceStates(guildId, update); + this.players.attemptConnection(guildId); + } + } +} +exports.MoonlinkManager = MoonlinkManager; diff --git a/node_modules/moonlink.js/dist/src/@Managers/NodeManager.d.ts b/node_modules/moonlink.js/dist/src/@Managers/NodeManager.d.ts new file mode 100644 index 0000000..d25e3ed --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Managers/NodeManager.d.ts @@ -0,0 +1,19 @@ +import { MoonlinkManager, MoonlinkNode, INode, SortType } from "../../index"; +export declare class NodeManager { + initiated: boolean; + _manager: MoonlinkManager; + map: Map; + constructor(); + init(): void; + check(): void; + add(node: INode): void; + remove(name: string): boolean; + get(name: any): any; + sortByUsage(sortType: SortType): MoonlinkNode[]; + private sortNodesByMemoryUsage; + private sortNodesByLavalinkCpuLoad; + private sortNodesBySystemCpuLoad; + private sortNodesByCalls; + private sortNodesByPlayingPlayers; + private sortNodesByPlayers; +} diff --git a/node_modules/moonlink.js/dist/src/@Managers/NodeManager.js b/node_modules/moonlink.js/dist/src/@Managers/NodeManager.js new file mode 100644 index 0000000..ab8b595 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Managers/NodeManager.js @@ -0,0 +1,89 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NodeManager = void 0; +const index_1 = require("../../index"); +class NodeManager { + initiated = false; + _manager; + map; + constructor() { + this.map = new Map(); + } + init() { + this._manager = index_1.Structure.manager; + this.check(); + this._manager.emit("debug", "@Moonlink(Nodes) - Structure(Nodes) was successfully initialized and assigned the value of the main class and checked the nodes"); + this.initiated = true; + } + check() { + if (!this._manager?._nodes) + throw new Error('@Moonlink(Nodes) - "nodes" option is empty'); + if (this._manager?._nodes && !Array.isArray(this._manager?._nodes)) + throw new Error('@Moonlink(Nodes) - the "nodes" option has to be in an array'); + if (this._manager?._nodes && this._manager?._nodes.length == 0) + throw new Error('@Moonlink(Nodes) - there are no parameters with "node(s)" information in the object'); + this._manager?._nodes.forEach(node => this.add(node)); + } + add(node) { + this._manager.emit("debug", `@Moonlink(Nodes) - The node ${node.host || node.identifier} has been added, and is starting its initialization process`); + const NodeInstance = new (index_1.Structure.get("MoonlinkNode"))(node); + if (node.identifier) + this.map.set(node.identifier, NodeInstance); + else + this.map.set(node.host, NodeInstance); + return; + } + remove(name) { + if (!name) { + throw new Error('[ @Moonlink/Manager ]: option "name" is empty'); + } + const removed = this.map.delete(name); + this._manager.emit("debug", `@Moonlink(Nodes) - The node ${name} has been successfully deleted`); + return removed; + } + get(name) { + return this.map.get(name) ? this.map.get(name) : null; + } + sortByUsage(sortType) { + this._manager.emit("debug", `@Moonlink(Nodes) - A new lavalink server is being drawn, sorting the type ${sortType}`); + const connectedNodes = [...this.map.values()].filter(node => node.state == "READY"); + if (connectedNodes.length == 0) + throw new TypeError("[ @Moonlink/Manager ]: No lavalink server connected"); + switch (sortType) { + case "memory": + return this.sortNodesByMemoryUsage(connectedNodes); + case "cpuLavalink": + return this.sortNodesByLavalinkCpuLoad(connectedNodes); + case "cpuSystem": + return this.sortNodesBySystemCpuLoad(connectedNodes); + case "calls": + return this.sortNodesByCalls(connectedNodes); + case "playingPlayers": + return this.sortNodesByPlayingPlayers(connectedNodes); + case "players": + default: + return this.sortNodesByPlayers(connectedNodes); + } + } + sortNodesByMemoryUsage(nodes) { + return nodes.sort((a, b) => (a.stats?.memory?.used || 0) - (b.stats?.memory?.used || 0)); + } + sortNodesByLavalinkCpuLoad(nodes) { + return nodes.sort((a, b) => (a.stats?.cpu?.lavalinkLoad || 0) - + (b.stats?.cpu?.lavalinkLoad || 0)); + } + sortNodesBySystemCpuLoad(nodes) { + return nodes.sort((a, b) => (a.stats?.cpu?.systemLoad || 0) - + (b.stats?.cpu?.systemLoad || 0)); + } + sortNodesByCalls(nodes) { + return nodes.sort((a, b) => a.calls - b.calls); + } + sortNodesByPlayingPlayers(nodes) { + return nodes.sort((a, b) => (a.stats?.playingPlayers || 0) - (b.stats?.playingPlayers || 0)); + } + sortNodesByPlayers(nodes) { + return nodes.sort((a, b) => (a.stats?.players || 0) - (b.stats?.players || 0)); + } +} +exports.NodeManager = NodeManager; diff --git a/node_modules/moonlink.js/dist/src/@Managers/PlayerManager.d.ts b/node_modules/moonlink.js/dist/src/@Managers/PlayerManager.d.ts new file mode 100644 index 0000000..46e5829 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Managers/PlayerManager.d.ts @@ -0,0 +1,19 @@ +import { MoonlinkPlayer, MoonlinkManager, createOptions } from "../../index"; +export declare class PlayerManager { + _manager: MoonlinkManager; + cache: Record; + private voices; + constructor(); + init(): void; + handleVoiceServerUpdate(update: any, guildId: string): void; + handlePlayerDisconnect(guildId: string): void; + handlePlayerMove(newChannelId: string, oldChannelId: string, guildId: string): void; + updateVoiceStates(guildId: string, update: any): void; + attemptConnection(guildId: string): Promise; + has(guildId: string): boolean; + get(guildId: string): MoonlinkPlayer | null; + create(data: createOptions): MoonlinkPlayer; + get all(): Record | null; + backup(player: any): boolean; + delete(guildId: any): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Managers/PlayerManager.js b/node_modules/moonlink.js/dist/src/@Managers/PlayerManager.js new file mode 100644 index 0000000..9c67cd7 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Managers/PlayerManager.js @@ -0,0 +1,160 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PlayerManager = void 0; +const index_1 = require("../../index"); +class PlayerManager { + _manager; + cache = {}; + voices = {}; + constructor() { } + init() { + this._manager = index_1.Structure.manager; + this._manager.emit("debug", "@Moonlink(Players) - Structure(Players) has been initialized, and assigned the value of the main class "); + } + handleVoiceServerUpdate(update, guildId) { + this.voices[guildId] = { + ...this.voices[guildId], + endpoint: update.endpoint, + token: update.token + }; + this.attemptConnection(guildId); + } + handlePlayerDisconnect(guildId) { + this._manager.emit("playerDisconnect", this.cache[guildId]); + this._manager.emit("debug", `@Moonlink(PlayerManager) - a player(${guildId}) was disconnected, issuing stop and resolving information`); + Object.assign(this.cache[guildId], { + connected: false, + voiceChannel: null, + playing: false + }); + this.cache[guildId].stop(); + } + handlePlayerMove(newChannelId, oldChannelId, guildId) { + this._manager.emit("playerMove", this.cache[guildId], newChannelId, oldChannelId); + this._manager.emit("debug", `@Moonlink(PlayerManager) - a player(${guildId}) was moved channel, resolving information`); + this.cache[guildId].voiceChannel = newChannelId; + if (this._manager.options.resume) + this.backup(this.cache[guildId]); + } + updateVoiceStates(guildId, update) { + this.voices[guildId] = { + ...this.voices[guildId], + sessionId: update.session_id + }; + } + async attemptConnection(guildId) { + if (!this.cache[guildId]) + return false; + if (this.voices[guildId] && + !this.voices[guildId]?.token && + !this.voices[guildId]?.endpoint && + !this.voices[guildId]?.sessionId) + return false; + if (this._manager.options?.balancingPlayersByRegion) { + const voiceRegion = this.voices[guildId]?.endpoint?.match(/([a-zA-Z-]+)\d+/)?.[1]; + if (!this.cache[guildId].voiceRegion) { + const connectedNodes = [ + ...this._manager.nodes.map.values() + ].filter(node => node.state == "READY"); + const matchingNode = connectedNodes.find(node => node.regions.includes(voiceRegion)); + this.cache[guildId].voiceRegion = voiceRegion; + if (matchingNode) { + this.cache[guildId].node = matchingNode; + } + } + } + else if (!this.cache[guildId].voiceRegion) { + const voiceRegion = this.voices[guildId]?.endpoint?.match(/([a-zA-Z-]+)\d+/)?.[1]; + this.cache[guildId].voiceRegion = voiceRegion; + } + await this.cache[guildId].node.rest.update({ + guildId, + data: { + voice: this.voices[guildId] + } + }); + return true; + } + has(guildId) { + return !!this.cache[guildId]; + } + get(guildId) { + if (!guildId && typeof guildId !== "string") + throw new Error('@Moonlink(PlayerManager) - "guildId" option in parameter to get player is empty or type is different from string'); + if (!this.has(guildId)) + return null; + return this.cache[guildId]; + } + create(data) { + if (typeof data !== "object" || + !data.guildId || + typeof data.guildId !== "string" || + !data.textChannel || + typeof data.textChannel !== "string" || + !data.voiceChannel || + typeof data.voiceChannel !== "string" || + (data.autoPlay !== undefined && + typeof data.autoPlay !== "boolean") || + (data.node && typeof data.node !== "string")) { + const missingParams = []; + if (!data.guildId || typeof data.guildId !== "string") + missingParams.push("guildId"); + if (!data.textChannel || typeof data.textChannel !== "string") + missingParams.push("textChannel"); + if (!data.voiceChannel || typeof data.voiceChannel !== "string") + missingParams.push("voiceChannel"); + if (data.autoPlay !== undefined && + typeof data.autoPlay !== "boolean") + missingParams.push("autoPlay"); + if (data.node && typeof data.node !== "string") + missingParams.push("node"); + throw new Error(`@Moonlink(PlayerManager) - Missing parameters for player creation: ${missingParams.join(", ")}`); + } + if (this.has(data.guildId)) + return this.get(data.guildId); + let nodeSorted = this._manager.nodes.sortByUsage(`${this._manager.options.sortNode ?? "players"}`)[0]; + data.node = nodeSorted.identifier ?? nodeSorted.host; + this._manager.emit("debug", `@Moonlink(Players) - A server player was created (${data.guildId})`); + this._manager.emit("playerCreated", data.guildId); + this.cache[data.guildId] = new (index_1.Structure.get("MoonlinkPlayer"))(data); + return this.cache[data.guildId]; + } + get all() { + return this.cache ?? null; + } + backup(player) { + const playerData = {}; + const playerKeys = Object.keys(player); + playerKeys.forEach(key => { + if ([ + "guildId", + "voiceChannel", + "textChannel", + "volume", + "loop", + "autoPlay", + "autoLeave", + "data", + "previous" + ].includes(key)) { + const value = index_1.Structure.db.get(`players.${player.guildId}.${key}`); + if (player[key] !== undefined && + player[key] !== null && + player[key] !== value) { + playerData[key] = player[key]; + } + else if (value !== undefined && value !== null) { + playerData[key] = value; + } + } + }); + index_1.Structure.db.set(`players.${player.guildId}`, playerData); + return true; + } + delete(guildId) { + delete this.cache[guildId]; + if (index_1.Structure.db.get(`players.${guildId}`)) + index_1.Structure.db.delete(`players.${guildId}`); + } +} +exports.PlayerManager = PlayerManager; diff --git a/node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.d.ts b/node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.d.ts new file mode 100644 index 0000000..bc9e47e --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.d.ts @@ -0,0 +1,7 @@ +/// +/// +import * as http from "http"; +import * as https from "https"; +export declare function makeRequest(uri: string, options: http.RequestOptions | (https.RequestOptions & { + method?: string; +}), data?: Record): Promise; diff --git a/node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.js b/node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.js new file mode 100644 index 0000000..aa7a77f --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Services/MoonlinkMakeRequest.js @@ -0,0 +1,128 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.makeRequest = void 0; +const http = __importStar(require("http")); +const https = __importStar(require("https")); +const http2 = __importStar(require("http2")); +const zlib = __importStar(require("zlib")); +const index_1 = require("../../index"); +function makeRequest(uri, options, data) { + return new Promise(resolve => { + const url = new URL(uri); + if (index_1.Structure.manager.options.http2 === true) { + let client = http2.connect(url.origin, { + protocol: url.protocol === "https:" ? "https:" : "http:", + rejectUnauthorized: false + }); + const reqOptions = { + ":method": options.method, + ":path": url.pathname + url.search, + "User-Agent": "Moonlink(Bot)", + "Content-Type": "application/json", + ...(options.headers || {}) + }; + let chunks = ""; + const req = client.request(reqOptions); + req.on("error", error => { + index_1.Structure.manager.emit("debug", `@Moonlink(MakeRequest[HTTP/2]) - An error occurred when requesting the ${url}: ${error}`); + client.close(); + resolve(error); + }); + req.on("response", headers => { + req.setEncoding("utf8"); + req.on("data", chunk => (chunks += chunk)); + req.on("end", () => { + client.close(); + try { + const parsedData = JSON.parse(chunks); + resolve(parsedData); + } + catch (parseError) { + resolve(parseError); + } + }); + req.on("error", error => { + index_1.Structure.manager.emit("debug", `@Moonlink(MakeRequest[HTTP/2]) - An error occurred when requesting the ${url}: ${error}`); + client.close(); + resolve(error); + }); + }); + data ? req.end(JSON.stringify(data)) : req.end(); + } + else { + let requestModule = http; + if (url.protocol === "https:") { + requestModule = https; + } + options.headers = { + "Content-Type": "application/json", + "Accept-Encoding": "br", + ...(options.headers || {}) + }; + const reqOptions = { + host: url.hostname, + port: url.port + ? parseInt(url.port) + : url.protocol === "https:" + ? 443 + : 80, + path: url.pathname + url.search, + method: options.method || "GET", + ...options + }; + const req = requestModule.request(url, reqOptions, async (res) => { + let newStream = res; + if (res.headers["content-encoding"] === "br") { + newStream = res.pipe(zlib.createBrotliDecompress()); + } + const chunks = []; + newStream.on("data", async (chunk) => { + chunks.push(chunk); + }); + newStream.on("end", async () => { + try { + const responseData = Buffer.concat(chunks).toString(); + if (reqOptions.path == "/version") + resolve(responseData); + const parsedData = JSON.parse(responseData); + resolve(parsedData); + } + catch (err) { + resolve(err); + } + }); + res.on("error", (err) => { + resolve(err); + }); + }); + if (data) { + req.write(JSON.stringify(data)); + } + req.end(); + } + }); +} +exports.makeRequest = makeRequest; diff --git a/node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.d.ts b/node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.d.ts new file mode 100644 index 0000000..4a3849e --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.d.ts @@ -0,0 +1,28 @@ +import { MoonlinkManager, MoonlinkNode } from "../../index"; +import { RestOptions, Endpoint } from "../@Typings"; +export declare class MoonlinkRestFul { + manager: MoonlinkManager; + sessionId: string; + node: MoonlinkNode; + url: string; + constructor(node: MoonlinkNode); + setSessionId(sessionId: string): void; + update(data: RestOptions): Promise>; + destroy(guildId: string): Promise>; + get(endpoint: Endpoint): Promise; + post(endpoint: Endpoint, data: RestOptions): Promise>; + patch(endpoint: Endpoint, data: RestOptions | any): Promise>; + delete(endpoint: Endpoint): Promise>; + decodeTrack(encodedTrack: string): Promise>; + decodeTracks(data: RestOptions): Promise>; + getInfo(): Promise>; + getStats(): Promise>; + getVersion(): Promise; + routePlannerFreeAddress(data: RestOptions): Promise>; + routePlannerFreeAll(data: RestOptions): Promise>; + private ensureUrlIsSet; + private makeGetRequest; + private makePostRequest; + private makePatchRequest; + private makeDeleteRequest; +} diff --git a/node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.js b/node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.js new file mode 100644 index 0000000..5b2fc41 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Services/MoonlinkRestFul.js @@ -0,0 +1,112 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkRestFul = void 0; +const index_1 = require("../../index"); +class MoonlinkRestFul { + manager; + sessionId; + node; + url; + constructor(node) { + this.manager = index_1.Structure.manager; + this.node = node; + } + setSessionId(sessionId) { + this.sessionId = sessionId; + this.ensureUrlIsSet(); + } + async update(data) { + this.ensureUrlIsSet(); + return this.makePatchRequest(`sessions/${this.sessionId}/players/${data.guildId}`, data.data); + } + async destroy(guildId) { + return this.makeDeleteRequest(`sessions/${this.sessionId}/players/${guildId}`); + } + async get(endpoint) { + this.ensureUrlIsSet(); + return this.makeGetRequest(endpoint); + } + async post(endpoint, data) { + this.ensureUrlIsSet(); + return this.makePostRequest(endpoint, data); + } + async patch(endpoint, data) { + this.ensureUrlIsSet(); + return this.makePatchRequest(endpoint, data.data); + } + async delete(endpoint) { + this.ensureUrlIsSet(); + return this.makeDeleteRequest(endpoint); + } + async decodeTrack(encodedTrack) { + return this.get(`decodetrack?encodedTrack=${encodedTrack}`); + } + async decodeTracks(data) { + return this.post("decodetracks", data); + } + async getInfo() { + return this.get("info"); + } + async getStats() { + return this.get("stats"); + } + async getVersion() { + const headers = { + Authorization: this.node.password + }; + return (0, index_1.makeRequest)((this.node.secure + ? "https://" + : "http://") + this.node.address + "/version", { + method: "GET", + headers + }).catch(err => err); + } + async routePlannerFreeAddress(data) { + return this.post("routeplanner/free/address", data); + } + async routePlannerFreeAll(data) { + return this.post("routeplanner/free/all", data); + } + ensureUrlIsSet() { + if (!this.url) { + this.url = this.node.http; + } + } + async makeGetRequest(endpoint) { + const headers = { + Authorization: this.node.password + }; + return (0, index_1.makeRequest)(this.url + endpoint, { + method: "GET", + headers + }).catch(err => err); + } + async makePostRequest(endpoint, data) { + const headers = { + Authorization: this.node.password + }; + return (0, index_1.makeRequest)(this.url + endpoint, { + method: "POST", + headers + }, data).catch(err => err); + } + async makePatchRequest(endpoint, data) { + const headers = { + Authorization: this.node.password + }; + return (0, index_1.makeRequest)(this.url + endpoint, { + method: "PATCH", + headers + }, data).catch(err => err); + } + async makeDeleteRequest(endpoint) { + const headers = { + Authorization: this.node.password + }; + return (0, index_1.makeRequest)(this.url + endpoint, { + method: "DELETE", + headers + }).catch(err => err); + } +} +exports.MoonlinkRestFul = MoonlinkRestFul; diff --git a/node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.d.ts b/node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.d.ts new file mode 100644 index 0000000..831c288 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.d.ts @@ -0,0 +1,19 @@ +/// +/// +import { EventEmitter } from "events"; +export declare class MoonlinkWebSocket extends EventEmitter { + private url; + private options; + private socket; + private established; + private closing; + private headers?; + private partialMessage?; + constructor(uri: string, options: any); + private buildRequestOptions; + private buildHandshake; + connect(): void; + private parseFrame; + writeFrame(data: any): Buffer; + close(code?: number, reason?: string): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.js b/node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.js new file mode 100644 index 0000000..470e565 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Services/MoonlinkWebSocket.js @@ -0,0 +1,243 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkWebSocket = void 0; +const http_1 = __importDefault(require("http")); +const https_1 = __importDefault(require("https")); +const crypto_1 = __importDefault(require("crypto")); +const events_1 = require("events"); +class MoonlinkWebSocket extends events_1.EventEmitter { + url; + options; + socket; + established; + closing = false; + headers; + partialMessage = null; + constructor(uri, options) { + super(); + this.url = new URL(uri); + this.options = { + port: this.url.port + ? this.url.port + : this.url.protocol === "wss:" + ? 443 + : 80, + method: "GET", + protocol: this.url.protocol === "wss:" ? "https:" : "http:", + secure: this.url.protocol === "wss:", + ...options + }; + if (process.versions && + process.versions.node && + process.versions.node.match(/20\.[0-2]\.0/)) { + require("net").setDefaultAutoSelectFamily(false); + } + this.connect(); + } + buildRequestOptions() { + const requestOptions = { + port: this.options.port, + headers: this.buildHandshake(this.options), + method: "GET", + keepAlive: true, + noDelay: true, + keepAliveInitialDelay: 0, + timeout: 0 + }; + return this.options.secure + ? requestOptions + : { ...requestOptions, protocol: "http:" }; + } + buildHandshake(options) { + const headers = { ...options.headers }; + headers["Host"] = this.url.host; + headers["Upgrade"] = "websocket"; + headers["Connection"] = "Upgrade"; + headers["Sec-WebSocket-Key"] = crypto_1.default + .randomBytes(16) + .toString("base64"); + headers["Sec-WebSocket-Version"] = "13"; + return headers; + } + connect() { + const { request } = this.options.secure ? https_1.default : http_1.default; + const requestOptions = this.buildRequestOptions(); + const req = request(`${this.options.secure ? "https://" : "http://"}${this.url.host}${this.url.pathname}${this.url.search || ""}`, requestOptions); + req.on("upgrade", (res, socket, head) => { + this.established = true; + this.socket = socket; + this.emit("open", this.socket); + if (res.headers.upgrade.toLowerCase() !== "websocket" || + res.headers["sec-websocket-accept"] !== + crypto_1.default + .createHash("sha1") + .update(requestOptions.headers["Sec-WebSocket-Key"] + + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11") + .digest("base64")) { + socket.destroy(); + return; + } + if (head && head.length > 0) + socket.unshift(head); + this.headers = res.headers; + socket.on("data", data => { + const frame = this.parseFrame(data); + switch (frame.opcode) { + case 0: { + if (frame.fin) { + if (!this.partialMessage) { + this.partialMessage = frame.payload; + } + else { + this.partialMessage = Buffer.concat([ + this.partialMessage, + frame.payload + ]); + ; + } + const message = this.partialMessage.toString("utf-8"); + this.emit("message", message); + this.partialMessage = null; + } + else { + if (!this.partialMessage) { + this.partialMessage = frame.payload; + } + else { + this.partialMessage = Buffer.concat([ + this.partialMessage, + frame.payload + ]); + } + } + break; + } + case 1: { + if (frame.fin) { + this.emit("message", frame.payload.toString("utf-8")); + } + else { + this.partialMessage = frame.payload; + } + break; + } + case 8: { + const code = frame.payload.readUInt16BE(0); + const reason = frame.payload.slice(2).toString("utf8"); + this.emit("close", code, reason); + break; + } + default: { + console.log("Emitted data that has not been implemented; opcode: " + + frame.opcode); + if (frame.payloadLength + frame.payloadOffset < + data.length) { + this.socket.unshift(data.slice(frame.payloadLength + frame.payloadOffset)); + } + } + } + }); + socket.on("close", hadError => { + if (hadError) + this.emit("error", hadError); + if (!this.closing) + this.emit("close"); + }); + socket.on("error", error => this.emit("error", error)); + }); + req.on("error", error => { + this.emit("error", error); + }); + req.on("close", code => { + if (!this.established) + this.emit("close", code); + }); + req.end(); + } + parseFrame(data) { + const opcode = data[0] & 0x0f; + const fin = (data[0] & 0x80) === 0x80; + const mask = (data[1] & 0x80) === 0x80; + let payloadOffset = 2; + let payloadLength = data[1] & 0x7f; + if (payloadLength === 126) { + payloadLength = data.readUInt16BE(2); + payloadOffset += 2; + } + else if (payloadLength === 127) { + payloadLength = data.readUInt32BE(2); + payloadOffset += 8; + } + const maskingKey = mask + ? data.slice(payloadOffset, payloadOffset + 4) + : null; + payloadOffset += mask ? 4 : 0; + const payload = data.slice(payloadOffset, payloadOffset + payloadLength); + if (mask && maskingKey) { + for (let i = 0; i < payload.length; i++) { + payload[i] ^= maskingKey[i % 4]; + } + } + return { + opcode, + fin, + mask, + maskingKey, + payloadLength, + payloadOffset, + payload + }; + } + writeFrame(data) { + const { fin, opcode, mask, payload } = data; + const header1 = (fin ? 128 : 0) | (opcode & 15); + const header2 = (mask ? 128 : 0) | (payload.length & 127); + let frame = Buffer.allocUnsafe(2); + frame.writeUInt8(header1, 0); + frame.writeUInt8(header2, 1); + if (payload.length > 125 && payload.length < 65535) { + let extendedFrame = Buffer.allocUnsafe(2); + extendedFrame.writeUInt16BE(payload.length, 0); + frame = Buffer.concat([frame, extendedFrame]); + } + else if (payload.length > 65535) { + let extendedFrame = Buffer.allocUnsafe(8); + extendedFrame.writeUInt32BE(0, 0); + extendedFrame.writeUInt32BE(payload.length, 4); + frame = Buffer.concat([frame, extendedFrame]); + } + if (mask) { + let maskingKey = Buffer.from([ + Math.floor(Math.random() * 256), + Math.floor(Math.random() * 256), + Math.floor(Math.random() * 256), + Math.floor(Math.random() * 256) + ]); + frame = Buffer.concat([frame, maskingKey]); + for (let i = 0; i < payload.length; i++) { + payload[i] ^= maskingKey[i % 4]; + } + } + frame = Buffer.concat([frame, payload]); + return frame; + } + close(code = 1000, reason = "normal closing") { + if (this.socket && this.established) { + this.closing = true; + const buffer = Buffer.alloc(2 + Buffer.byteLength(reason)); + buffer.writeUInt16BE(code, 0); + buffer.write(reason, 2, Buffer.byteLength(reason), "utf-8"); + let frame = this.writeFrame({ + fin: true, + opcode: 8, + mask: false, + payload: buffer + }); + this.socket.write(frame); + } + } +} +exports.MoonlinkWebSocket = MoonlinkWebSocket; diff --git a/node_modules/moonlink.js/dist/src/@Typings/index.d.ts b/node_modules/moonlink.js/dist/src/@Typings/index.d.ts new file mode 100644 index 0000000..1c9edec --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Typings/index.d.ts @@ -0,0 +1,267 @@ +import { MoonlinkManager, MoonlinkPlayer, MoonlinkFilters, MoonlinkDatabase, MoonlinkRestFul, MoonlinkQueue, MoonlinkNode, MoonlinkTrack, PlayerManager, NodeManager, Plugin } from "../../index"; +export type Constructor = new (...args: any[]) => T; +export interface createOptions { + guildId: string; + textChannel: string; + voiceChannel: string; + autoPlay?: boolean; + autoLeave?: boolean; + notBackup?: boolean; + loop?: number; + volume?: number; + node?: string; +} +export type SortType = "memory" | "cpuLavalink" | "cpuSystem" | "calls" | "playingPlayers" | "players"; +export interface VoiceState { + op: "voiceUpdate"; + guildId: string; + event: VoiceServer; + sessionId?: string; +} +export interface VoiceServer { + token: string; + guild_id: string; + endpoint: string; +} +export interface VoiceState { + guild_id: string; + user_id: string; + session_id: string; + channel_id: string; +} +export interface VoicePacket { + t?: "VOICE_SERVER_UPDATE" | "VOICE_STATE_UPDATE"; + d: VoiceState | VoiceServer; +} +export type LoadType = "track" | "playlist" | "search" | "empty" | "error"; +export interface TrackData { + encoded?: string; + info: TrackDataInfo; + pluginInfo: object; +} +export interface TrackDataInfo { + title: string; + identifier: string; + author: string; + length: number; + position: number; + isSeekable: boolean; + isStream: boolean; + uri: string; +} +export type SearchPlatform = "youtube" | "youtubemusic" | "soundcloud" | string; +export interface SearchQuery { + source?: SearchPlatform | string | undefined | null; + query: string | string[]; + requester?: string | object | any; + node?: string; +} +export interface SearchResult { + loadType: LoadType; + tracks: MoonlinkTrack[]; + playlistInfo?: PlaylistInfo; + exception?: { + message: string; + severity: string; + }; +} +export interface INodeStats { + players: number; + playingPlayers: number; + uptime: number; + memory: { + reservable: number; + used: number; + free: number; + allocated: number; + }; + frameStats: { + sent: number; + deficit: number; + nulled: number; + }; + cpu: { + cores: number; + systemLoad: number; + lavalinkLoad: number; + }; +} +export interface INode { + host: string; + identifier?: string; + password: string; + port: number; + secure: boolean; + regions?: string[]; + retryAmount?: number; + retryDelay?: number; + sessionId?: string; +} +export interface IOptions { + clientId?: string; + clientName?: string; + sortNode?: SortType; + autoResume?: boolean; + resume?: boolean; + plugins?: Plugin[]; + http2?: boolean; + doNotSaveToFiles?: boolean; + switchPlayersAnotherNode?: boolean; + destroyPlayersStopped?: boolean; + balancingPlayersByRegion?: boolean; + previousTracksInArray?: boolean; +} +export interface IHeaders { + Authorization: string; + "User-Id": string; + "Client-Name": string; +} +export interface Extendable { + MoonlinkManager: typeof MoonlinkManager; + MoonlinkPlayer: typeof MoonlinkPlayer; + MoonlinkDatabase: typeof MoonlinkDatabase; + MoonlinkFilters: typeof MoonlinkFilters; + MoonlinkRestFul: typeof MoonlinkRestFul; + MoonlinkQueue: typeof MoonlinkQueue; + MoonlinkNode: typeof MoonlinkNode; + MoonlinkTrack: typeof MoonlinkTrack; + PlayerManager: typeof PlayerManager; + NodeManager: typeof NodeManager; +} +export interface PlaylistInfo { + name: string; + selectedTrack?: MoonlinkTrack; + duration: number; +} +export interface LavalinkResult { + data: TrackData[]; + loadType: LoadType; + exception?: { + message: string; + severity: string; + }; + playlistInfo: { + name: string; + selectedTrack?: number; + }; +} +export interface VoiceOptions { + endpoint: string; + token: string; + sessionId: string; + connected?: boolean; + ping?: number; +} +export type Endpoint = string; +export interface objectTrack { + encoded: string; +} +export interface PreviousInfosPlayer { + voiceChannel?: string; + textChannel?: string; + guildId?: string; + volume?: number; + autoPlay?: boolean; + autoLeave?: boolean; + previous?: object | MoonlinkTrack; + loop?: number; + current?: Record; +} +export interface RestOptions { + guildId: string; + data: { + track?: objectTrack; + identifier?: string; + startTime?: number; + endTime?: number; + volume?: number; + position?: number; + paused?: Boolean; + filters?: Object; + voice?: VoiceOptions; + }; +} +export interface connectOptions { + setMute?: boolean; + setDeaf?: boolean; +} +export interface IPlayerData { + guildId: string; + textChannel: string | null; + voiceChannel: string | null; + voiceRegion?: string | null; + autoPlay?: boolean | null; + autoLeave?: boolean | null; + connected?: boolean | null; + playing?: boolean | null; + paused?: boolean | null; + shuffled?: boolean | null; + loop?: number | null; + volume?: number | null; + notBackup?: boolean; + ping?: number; + node?: string; +} +export interface TrackInfo { + identifier: string; + isSeekable: boolean; + author: string; + isStream: boolean; + length: number; + position: number; + title: string; + uri?: string; + artworkUrl?: string; + sourceName: string; + isrc?: string; +} +export interface MoonlinkTrackOptions { + info: TrackInfo; + encoded?: string; + pluginInfo?: object; +} +export interface Equalizer { + band: number; + gain: number; +} +export interface Karaoke { + level?: number; + monoLevel?: number; + filterBand?: number; + filterWidth?: number; +} +export interface Timescale { + speed?: number; + pitch?: number; + rate?: number; +} +export interface Tremolo { + frequency?: number; + depth?: number; +} +export interface Vibrato { + frequency?: number; + depth?: number; +} +export interface Rotation { + rotationHz?: number; +} +export interface Distortion { + sinOffset?: number; + sinScale?: number; + cosOffset?: number; + cosScale?: number; + tanOffset?: number; + tanScale?: number; + offset?: number; + scale?: number; +} +export interface ChannelMix { + leftToLeft?: number; + leftToRight?: number; + rightToLeft?: number; + rightToRight?: number; +} +export interface LowPass { + smoothing?: number; +} diff --git a/node_modules/moonlink.js/dist/src/@Typings/index.js b/node_modules/moonlink.js/dist/src/@Typings/index.js new file mode 100644 index 0000000..c8ad2e5 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Typings/index.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.d.ts b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.d.ts new file mode 100644 index 0000000..6cfaac3 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.d.ts @@ -0,0 +1,15 @@ +type Data = Record; +export declare class MoonlinkDatabase { + data: Data; + id: string; + constructor(clientId: string); + set(key: string, value: T): void; + get(key: string): T | undefined; + push(key: string, value: T): void; + delete(key: string): boolean; + private updateData; + private getFilePath; + fetch(): void; + private save; +} +export {}; diff --git a/node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.js b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.js new file mode 100644 index 0000000..f8635d4 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkDatabase.js @@ -0,0 +1,113 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkDatabase = void 0; +const fs_1 = __importDefault(require("fs")); +const path_1 = __importDefault(require("path")); +class MoonlinkDatabase { + data = {}; + id; + constructor(clientId) { + this.fetch(); + this.id = clientId; + } + set(key, value) { + if (!key) + throw new Error('@Moonlink(Database) - "key" is empty'); + const keys = key.split("."); + if (keys.length === 0) + return; + this.updateData(this.data, keys, value); + this.save(); + } + get(key) { + if (!key) + throw new Error('[ @Moonlink(Database) - "key" is empty'); + if (Object.keys(this.data).length === 0) + this.fetch(); + return (key.split(".").reduce((acc, curr) => acc?.[curr], this.data) ?? null); + } + push(key, value) { + if (!key) + throw new Error('@Moonlink(Database) - "key" is empty'); + const oldArray = this.get(key) || []; + if (Array.isArray(oldArray)) { + oldArray.push(value); + this.set(key, oldArray); + } + else { + throw new Error("@Moonlink(Database) - Key does not point to an array"); + } + } + delete(key) { + if (!key) + throw new Error('@Moonlink(Database) - "key" is empty'); + const keys = key.split("."); + if (keys.length === 0) + return false; + const lastKey = keys.pop() || ""; + let currentObj = this.data; + keys.forEach(k => { + if (typeof currentObj[k] === "object") { + currentObj = currentObj[k]; + } + else { + throw new Error(`@Moonlink(Database) - Key path "${key}" does not exist`); + } + }); + if (currentObj && lastKey in currentObj) { + delete currentObj[lastKey]; + this.save(); + return true; + } + return false; + } + updateData(data, keys, value) { + let currentObj = data; + keys.forEach((key, index) => { + if (index === keys.length - 1) { + currentObj[key] = value; + } + else { + if (typeof currentObj[key] !== "object") { + currentObj[key] = {}; + } + currentObj = currentObj[key]; + } + }); + } + getFilePath() { + return path_1.default.join(__dirname, "../@Datastore", `database-${this.id}.json`); + } + fetch() { + try { + const directory = path_1.default.join(__dirname, "../@Datastore"); + if (!fs_1.default.existsSync(directory)) { + fs_1.default.mkdirSync(directory, { recursive: true }); + } + const filePath = this.getFilePath(); + const rawData = fs_1.default.readFileSync(filePath, "utf-8"); + this.data = JSON.parse(rawData) || {}; + } + catch (err) { + if (err.code === "ENOENT") { + this.data = {}; + } + else { + throw new Error("@Moonlink(Database) - Failed to fetch data (Error):", err); + } + } + } + save() { + try { + const filePath = this.getFilePath(); + fs_1.default.writeFileSync(filePath, JSON.stringify(this.data, null, 2)); + } + catch (error) { + throw new Error("@Moonlink(Database) - Failed to save data"); + } + } +} +exports.MoonlinkDatabase = MoonlinkDatabase; diff --git a/node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.d.ts b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.d.ts new file mode 100644 index 0000000..bd1be8e --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.d.ts @@ -0,0 +1,29 @@ +import { Equalizer, Karaoke, Timescale, Tremolo, Vibrato, Rotation, Distortion, ChannelMix, LowPass } from "../@Typings"; +export declare class MoonlinkFilters { + private player; + private manager; + private rest; + volume: number | null; + equalizer: Equalizer[] | null; + karaoke: Karaoke | null; + timescale: Timescale | null; + tremolo: Tremolo | null; + vibrato: Vibrato | null; + rotation: Rotation | null; + distortion: Distortion | null; + channelMix: ChannelMix | null; + lowPass: LowPass | null; + constructor(player: any); + setVolume(volume: number | null): this; + setEqualizer(equalizer: Equalizer[] | null): this; + setKaraoke(karaoke: Karaoke | null): this; + setTimescale(timescale: Timescale | null): this; + setTremolo(tremolo: Tremolo | null): this; + setVibrato(vibrato: Vibrato | null): this; + setRotation(rotation: Rotation | null): this; + setDistortion(distortion: Distortion | null): this; + setChannelMix(channelMix: ChannelMix | null): this; + setLowPass(lowPass: LowPass | null): this; + resetFilters(): this; + private updateFiltersFromRest; +} diff --git a/node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.js b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.js new file mode 100644 index 0000000..547b640 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkFilters.js @@ -0,0 +1,131 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkFilters = void 0; +const index_1 = require("../../index"); +class MoonlinkFilters { + player; + manager; + rest; + volume; + equalizer; + karaoke; + timescale; + tremolo; + vibrato; + rotation; + distortion; + channelMix; + lowPass; + constructor(player) { + this.player = player; + this.rest = player.node.rest; + this.manager = index_1.Structure.manager; + this.volume = this.player.get("Fvolume") || null; + this.equalizer = this.player.get("equalizer") || null; + this.karaoke = this.player.get("karaoke") || null; + this.timescale = this.player.get("timescale") || null; + this.tremolo = this.player.get("tremolo") || null; + this.vibrato = this.player.get("vibrato") || null; + this.rotation = this.player.get("rotation") || null; + this.distortion = this.player.get("distortion") || null; + this.channelMix = this.player.get("channelMix") || null; + this.lowPass = this.player.get("lowPass") || null; + } + setVolume(volume) { + this.player.set("Fvolume", volume); + this.volume = volume; + this.updateFiltersFromRest(); + return this; + } + setEqualizer(equalizer) { + this.player.set("equalizer", equalizer); + this.equalizer = equalizer; + this.updateFiltersFromRest(); + return this; + } + setKaraoke(karaoke) { + this.player.set("karaoke", karaoke); + this.karaoke = karaoke; + this.updateFiltersFromRest(); + return this; + } + setTimescale(timescale) { + this.player.set("timescale", timescale); + this.timescale = timescale; + this.updateFiltersFromRest(); + return this; + } + setTremolo(tremolo) { + this.player.set("tremolo", tremolo); + this.tremolo = tremolo; + this.updateFiltersFromRest(); + return this; + } + setVibrato(vibrato) { + this.player.set("vibrato", vibrato); + this.vibrato = vibrato; + this.updateFiltersFromRest(); + return this; + } + setRotation(rotation) { + this.player.set("rotation", rotation); + this.rotation = rotation; + this.updateFiltersFromRest(); + return this; + } + setDistortion(distortion) { + this.player.set("distortion", distortion); + this.distortion = distortion; + this.updateFiltersFromRest(); + return this; + } + setChannelMix(channelMix) { + this.player.set("channelMix", channelMix); + this.channelMix = channelMix; + this.updateFiltersFromRest(); + return this; + } + setLowPass(lowPass) { + this.player.set("lowPass", lowPass); + this.lowPass = lowPass; + this.updateFiltersFromRest(); + return this; + } + resetFilters() { + this.setVolume(null); + this.setEqualizer(null); + this.setKaraoke(null); + this.setTimescale(null); + this.setTremolo(null); + this.setVibrato(null); + this.setRotation(null); + this.setDistortion(null); + this.setChannelMix(null); + this.setLowPass(null); + this.updateFiltersFromRest(); + return this; + } + async updateFiltersFromRest() { + let { volume, equalizer, karaoke, timescale, tremolo, vibrato, rotation, distortion, channelMix, lowPass } = this; + const dataToUpdate = { + guildId: this.player.guildId, + data: { + filters: { + ...(volume !== null && { volume }), + ...(equalizer !== null && { equalizer }), + ...(karaoke !== null && { karaoke }), + ...(timescale !== null && { timescale }), + ...(tremolo !== null && { tremolo }), + ...(vibrato !== null && { vibrato }), + ...(rotation !== null && { rotation }), + ...(distortion !== null && { distortion }), + ...(channelMix !== null && { channelMix }), + ...(lowPass !== null && { lowPass }) + } + } + }; + await this.rest.update(dataToUpdate); + return true; + } +} +exports.MoonlinkFilters = MoonlinkFilters; diff --git a/node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.d.ts b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.d.ts new file mode 100644 index 0000000..5d5361d --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.d.ts @@ -0,0 +1,20 @@ +import { MoonlinkTrackOptions } from "../@Typings"; +export declare class MoonlinkTrack { + encoded: string | null; + identifier: string; + title: string; + author: string; + url: string; + duration: number; + position: number; + isSeekable: boolean; + isStream: boolean; + sourceName: string; + requester: any; + artworkUrl: string; + isrc: string; + time?: number; + constructor(data?: MoonlinkTrackOptions, requester?: string | any); + get calculateRealTimePosition(): number; + setRequester(data: any): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.js b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.js new file mode 100644 index 0000000..ca200a0 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/MoonlinkTrack.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MoonlinkTrack = void 0; +class MoonlinkTrack { + encoded; + identifier; + title; + author; + url; + duration; + position; + isSeekable; + isStream; + sourceName; + requester; + artworkUrl; + isrc; + time = 0; + constructor(data, requester) { + this.encoded = data.encoded; + this.title = data.info.title; + this.author = data.info.author; + this.url = data.info.uri; + this.duration = data.info.length; + this.position = data.info.position; + this.identifier = data.info.identifier; + this.isSeekable = Boolean(data.info.isSeekable); + this.isStream = Boolean(data.info.isStream); + this.sourceName = data.info.sourceName || null; + this.requester = requester; + this.artworkUrl = data.info.artworkUrl; + this.isrc = data.info.isrc; + } + get calculateRealTimePosition() { + if (this.position >= this.duration) { + return this.duration; + } + if (this.time) { + const elapsed = Date.now() - this.time; + const calculatedPosition = this.position + elapsed / 1000; + if (calculatedPosition >= this.duration) { + return this.duration; + } + return calculatedPosition; + } + return this.position; + } + setRequester(data) { + this.requester = data; + } +} +exports.MoonlinkTrack = MoonlinkTrack; diff --git a/node_modules/moonlink.js/dist/src/@Utils/Structure.d.ts b/node_modules/moonlink.js/dist/src/@Utils/Structure.d.ts new file mode 100644 index 0000000..84f1f68 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/Structure.d.ts @@ -0,0 +1,13 @@ +import { Extendable } from "../@Typings"; +import { MoonlinkManager, MoonlinkDatabase } from "../../index"; +export declare abstract class Structure { + static manager: MoonlinkManager; + static db: MoonlinkDatabase; + static extend(name: K, extender: (target: Extendable[K]) => T): T; + static init(manager: MoonlinkManager): void; + static get(name: K): Extendable[K]; +} +export declare class Plugin { + load(manager: MoonlinkManager): void; + unload(manager: MoonlinkManager): void; +} diff --git a/node_modules/moonlink.js/dist/src/@Utils/Structure.js b/node_modules/moonlink.js/dist/src/@Utils/Structure.js new file mode 100644 index 0000000..b2d73a9 --- /dev/null +++ b/node_modules/moonlink.js/dist/src/@Utils/Structure.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Plugin = exports.Structure = void 0; +const index_1 = require("../../index"); +const structures = { + MoonlinkManager: index_1.MoonlinkManager, + MoonlinkRestFul: index_1.MoonlinkRestFul, + MoonlinkPlayer: index_1.MoonlinkPlayer, + MoonlinkFilters: index_1.MoonlinkFilters, + MoonlinkDatabase: index_1.MoonlinkDatabase, + MoonlinkQueue: index_1.MoonlinkQueue, + MoonlinkNode: index_1.MoonlinkNode, + MoonlinkTrack: index_1.MoonlinkTrack, + PlayerManager: index_1.PlayerManager, + NodeManager: index_1.NodeManager +}; +class Structure { + static manager; + static db; + static extend(name, extender) { + if (!(name in structures)) { + throw new TypeError(`"${name}" is not a valid structure`); + } + const extended = extender(structures[name]); + structures[name] = extended; + return extended; + } + static init(manager) { + this.manager = manager; + this.db = new (Structure.get("MoonlinkDatabase"))(manager.clientId); + this.manager.emit("debug", `@Moonlink(Structure) - The main class and database are assigned to structure :)`); + } + static get(name) { + const structure = structures[name]; + if (!structure) { + throw new TypeError(`"${name}" structure must be provided.`); + } + return structure; + } +} +exports.Structure = Structure; +class Plugin { + load(manager) { } + unload(manager) { } +} +exports.Plugin = Plugin; diff --git a/node_modules/moonlink.js/package.json b/node_modules/moonlink.js/package.json new file mode 100644 index 0000000..b644762 --- /dev/null +++ b/node_modules/moonlink.js/package.json @@ -0,0 +1,55 @@ +{ + "name": "moonlink.js", + "version": "3.6.4", + "description": "Imagine a Music... 🌙✨ Welcome to Moonlink.js! We invite you to create your own music bot on Discord using Lavalink, in a simple and easy way! 🎶🤖", + "keywords": [ + "bot", + "discord.js", + "moonlink", + "discord", + "easy", + "lavalink", + "music" + ], + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.js" + } + }, + "scripts": { + "start": "rm -r dist && tsc && mv ./dist/index.js ./" + }, + "homepage": "https://moonlink.js.org", + "bugs": { + "url": "https://github.com/Ecliptia/moonlink.js/issues", + "email": "1Lucas1apk@gmail.com" + }, + "license": { + "type": "Apache-2.0", + "url": "https://opensource.org/licenses/apache2.0.php" + }, + "contributors": [ + "1Lucas1.apk" + ], + "repository": { + "type": "git", + "url": "https://github.com/Ecliptia/moonlink.js" + }, + "engines": { + "node": ">=16.6.0" + }, + "devDependencies": { + "@types/node": "^18.15.11", + "discord.js": "^14.14.1", + "get-image-colors": "^4.0.1", + "mongoose": "^8.1.1", + "typecript": "^0.0.1-security", + "typedoc": "^0.25.4", + "typedoc-plugin-markdown": "^3.17.1" + } +} diff --git a/src/modules/discord-bot.js b/src/modules/discord-bot.js index f420eed..d63d07a 100644 --- a/src/modules/discord-bot.js +++ b/src/modules/discord-bot.js @@ -220,8 +220,9 @@ function startErelaManager(dlog, config) { }) + client.manager.on("trackStart", async (player) => { - + console.log("NEW INVOCATION") // Create a metric to count the number of songs played const songPlayed = new metric.Metric("songPlayed", "Nombre de musiques jouées") songPlayed.setValue(songPlayed.getValue() + 1) @@ -246,9 +247,10 @@ function startErelaManager(dlog, config) { client.manager.on("queueEnd", async () => { let player = await client.manager.players.get("137291455336022018") console.log("END OF QUEUE") + if(player) { - await list.addCurrentToPrevious() + await list.addCurrentToPrevious(player.previous) if(await list.haveSongs()) { await player.play(list.next()) diff --git a/src/modules/sub-list.js b/src/modules/sub-list.js index 44698d9..4d9d94d 100644 --- a/src/modules/sub-list.js +++ b/src/modules/sub-list.js @@ -121,16 +121,23 @@ module.exports.List = class { current = song.current + console.log("CURRENT SONG : " + current.title) } - addCurrentToPrevious() { - - if(current) { + addCurrentToPrevious(song) { + if(song) { var previousList = getPreviousFile() + previousList.unshift(song) + savePreviousFile(previousList) + } else if(current) { + var previousList = getPreviousFile() + //Check if the first song is the same as the current song previousList.unshift(current) savePreviousFile(previousList) } + + } diff --git a/src/web/public/javascript/player.js b/src/web/public/javascript/player.js index a1efd12..00a2036 100644 --- a/src/web/public/javascript/player.js +++ b/src/web/public/javascript/player.js @@ -17,7 +17,7 @@ const volume = getID("volume") const volIcon = getID("volIcon") const volTxt = getID("volTxt") -const lyrics = getID("lyrics") +// const lyrics = getID("lyrics") const disconnect = getID("disconnect") const moveout = getID("moveout") @@ -55,7 +55,7 @@ AlwaysRequest("MUSIC_STATE", async (data) => { volume.classList.remove("invisible") volTxt.classList.remove("invisible") volIcon.classList.remove("invisible") - lyrics.classList.remove("invisible") + // lyrics.classList.remove("invisible") } else { @@ -72,7 +72,7 @@ AlwaysRequest("MUSIC_STATE", async (data) => { time_act.innerHTML = " " time_total.innerHTML = " " durationBar.classList.add("invisible") - lyrics.classList.add("invisible") + // lyrics.classList.add("invisible") } @@ -279,93 +279,93 @@ moveout.addEventListener('click', () => { get("MOVEOUT") }) -lyrics.addEventListener('click', (e) => { +// lyrics.addEventListener('click', (e) => { - currentTitle = currentTitle.replace(/\(.*?\)/g, "").replace(/\[.*?\]/g, "").trim() +// currentTitle = currentTitle.replace(/\(.*?\)/g, "").replace(/\[.*?\]/g, "").trim() - if(e.ctrlKey) { - const modal = new ModalComponent({"title": "Rechercher des paroles" , "width": "25%", "closable": true}) +// if(e.ctrlKey) { +// const modal = new ModalComponent({"title": "Rechercher des paroles" , "width": "25%", "closable": true}) - modal.setContent(` -
- - -
- `) +// modal.setContent(` +//
+// +// +//
+// `) - modal.show() +// modal.show() - const lyricsSearch = getID("lyrics_search") - const lyricsSearchBtn = getID("lyrics_search_btn") +// const lyricsSearch = getID("lyrics_search") +// const lyricsSearchBtn = getID("lyrics_search_btn") - lyricsSearchBtn.addEventListener('click', () => { - showLyrics(lyricsSearch.value) - modal.hide() - }) +// lyricsSearchBtn.addEventListener('click', () => { +// showLyrics(lyricsSearch.value) +// modal.hide() +// }) - } else { +// } else { - if(currentTitle) { - showLyrics(currentTitle) +// if(currentTitle) { +// showLyrics(currentTitle) - } else { - const modal = new ModalComponent({"title": "Paroles" , "width": "20%", "closable": true}) - modal.setContent(` +// } else { +// const modal = new ModalComponent({"title": "Paroles" , "width": "20%", "closable": true}) +// modal.setContent(` -

Lancez une musique pour rechercher les paroles ou faites Ctrl + Click !

- `) +//

Lancez une musique pour rechercher les paroles ou faites Ctrl + Click !

+// `) - modal.show() - } - } +// modal.show() +// } +// } -}) +// }) -function showLyrics(title) { - title = title.replace(/\(.*?\)/g, "").replace(/\[.*?\]/g, "").trim() - post("LYRICS", title).then((res) => { +// function showLyrics(title) { +// title = title.replace(/\(.*?\)/g, "").replace(/\[.*?\]/g, "").trim() +// post("LYRICS", title).then((res) => { - if(res.startsWith("
")) { - const modal = new ModalComponent({"title": "Paroles" , "width": "50%", "closable": true}) - modal.setContent(` -

Aucune paroles trouvées pour cette musique !

- `) +// if(res.startsWith("
")) { +// const modal = new ModalComponent({"title": "Paroles" , "width": "50%", "closable": true}) +// modal.setContent(` +//

Aucune paroles trouvées pour cette musique !

+// `) - modal.show() - } else { +// modal.show() +// } else { - const lyricsArray = new Array() +// const lyricsArray = new Array() - // Split res by line when a new [ appears +// // Split res by line when a new [ appears - res.split("[").forEach((line) => { - if(line.includes("]")) { - const time = line.split("]")[0].trim() - const lyrics = line.split("]")[1].trim() - lyricsArray.push(`

${lyrics}

`) - } - }) +// res.split("[").forEach((line) => { +// if(line.includes("]")) { +// const time = line.split("]")[0].trim() +// const lyrics = line.split("]")[1].trim() +// lyricsArray.push(`

${lyrics}

`) +// } +// }) - setTileActive(null) +// setTileActive(null) - loadView(` -

Paroles de "${title}"

-
-
- ${lyricsArray.join("")} -
-
- `) +// loadView(` +//

Paroles de "${title}"

+//
+//
+// ${lyricsArray.join("")} +//
+//
+// `) - } - }) +// } +// }) -} +// } volIcon.addEventListener('click', () => { diff --git a/src/web/public/javascript/queue.js b/src/web/public/javascript/queue.js index d25749f..2de0813 100644 --- a/src/web/public/javascript/queue.js +++ b/src/web/public/javascript/queue.js @@ -154,7 +154,7 @@ class VideoQueue { this.title = data.title this.author = data.author this.thumbnail = data.artworkUrl - this.url = data.uri + this.url = data.url this.duration = data.duration this.identifier = data.numList + "_" + data.identifier this.type = data.type diff --git a/src/web/templates/index.ejs b/src/web/templates/index.ejs index a28d62c..5b9c766 100644 --- a/src/web/templates/index.ejs +++ b/src/web/templates/index.ejs @@ -122,7 +122,7 @@
- +