From 000bd0bb45ecdb7129d21763561961729f06d993 Mon Sep 17 00:00:00 2001 From: Cynthia Date: Sat, 10 Dec 2022 14:49:25 -0700 Subject: [PATCH] music: attempt 1 at porting to djs voice and such --- package.json | 4 +- pnpm-lock.yaml | 39 +++++--------- src/modules/music.js | 120 +++++++++++++++++++------------------------ 3 files changed, 67 insertions(+), 96 deletions(-) diff --git a/package.json b/package.json index 2011dbf..1205e81 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,9 @@ "murmurhash": "^2.0.0", "node-ffprobe": "^3.0.0", "oceanic.js": "^1.1.2", + "play-dl": "^1.9.6", "sharp": "^0.28.3", - "sqlite3": "^5.0.2", - "ytdl-core": "github:GreepTheSheep/node-ytdl-core" + "sqlite3": "^5.0.2" }, "devDependencies": { "eslint": "^7.26.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d7c5f14..14568f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,10 +9,10 @@ specifiers: murmurhash: ^2.0.0 node-ffprobe: ^3.0.0 oceanic.js: ^1.1.2 + play-dl: ^1.9.6 prettier: ^2.3.0 sharp: ^0.28.3 sqlite3: ^5.0.2 - ytdl-core: github:GreepTheSheep/node-ytdl-core dependencies: '@ctrl/tinycolor': 3.4.1 @@ -22,9 +22,9 @@ dependencies: murmurhash: 2.0.0 node-ffprobe: 3.0.0 oceanic.js: 1.1.2 + play-dl: 1.9.6 sharp: 0.28.3 sqlite3: 5.0.2 - ytdl-core: github.com/GreepTheSheep/node-ytdl-core/17a77cbe7f3a9670d6536fba7cb3f574c6da596a devDependencies: eslint: 7.26.0 @@ -1479,14 +1479,6 @@ packages: dependencies: yallist: 4.0.0 - /m3u8stream/0.8.6: - resolution: {integrity: sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==} - engines: {node: '>=12'} - dependencies: - miniget: 4.2.2 - sax: 1.2.4 - dev: false - /mime-db/1.48.0: resolution: {integrity: sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==} engines: {node: '>= 0.6'} @@ -1518,11 +1510,6 @@ packages: dom-walk: 0.1.2 dev: false - /miniget/4.2.2: - resolution: {integrity: sha512-a7voNL1N5lDMxvTMExOkg+Fq89jM2vY8pAi9ZEWzZtfNmdfP6RXkvUtFnCAXoCv2T9k1v/fUJVaAEuepGcvLYA==} - engines: {node: '>=12'} - dev: false - /minimatch/3.0.4: resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} dependencies: @@ -1816,6 +1803,17 @@ packages: pngjs: 3.4.0 dev: false + /play-audio/0.5.2: + resolution: {integrity: sha512-ZAqHUKkQLix2Iga7pPbsf1LpUoBjcpwU93F1l3qBIfxYddQLhxS6GKmS0d3jV8kSVaUbr6NnOEcEMFvuX93SWQ==} + dev: false + + /play-dl/1.9.6: + resolution: {integrity: sha512-JW44bQbME9fNfGhGXQ/rdcsHr4BfgJabVlSgpS9QY/NscfprFH1asv+q9atrZThP3+hHIpgtFNABccg9rFWlwg==} + engines: {node: '>=16.0.0'} + dependencies: + play-audio: 0.5.2 + dev: false + /pngjs/3.4.0: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} @@ -2475,14 +2473,3 @@ packages: jimp: 0.16.1 node-fetch: 2.6.1 dev: false - - github.com/GreepTheSheep/node-ytdl-core/17a77cbe7f3a9670d6536fba7cb3f574c6da596a: - resolution: {tarball: https://codeload.github.com/GreepTheSheep/node-ytdl-core/tar.gz/17a77cbe7f3a9670d6536fba7cb3f574c6da596a} - name: ytdl-core - version: 0.0.0-development - engines: {node: '>=12'} - dependencies: - m3u8stream: 0.8.6 - miniget: 4.2.2 - sax: 1.2.4 - dev: false diff --git a/src/modules/music.js b/src/modules/music.js index c47e022..cef3bd3 100644 --- a/src/modules/music.js +++ b/src/modules/music.js @@ -1,5 +1,11 @@ -const ytdl = require("ytdl-core"); const {Collection} = require("oceanic.js"); +const { + AudioPlayerStatus, + createAudioPlayer, + createAudioResource, +} = require("@discordjs/voice"); + +const playdl = require("play-dl"); const ffprobe = require("node-ffprobe"); const Command = require("../lib/command.js"); @@ -132,13 +138,28 @@ async function processPlaylist( } async function createVoiceConnection(guild_id, voice_id, text_id) { - const connection = await hf.bot.joinVoiceChannel(voice_id); - connection._music_text_id = text_id; - connection._music_queue = []; + const state = {}; - connection._music_eventEnd = async function () { - if (connection._music_queue.length > 0) { - const next = connection._music_queue.splice(0, 1)[0]; + const guild = hf.bot.guilds.get(guild_id); + state.connection = hf.bot.joinVoiceChannel({ + channelID: voice_id, + guildID: guild_id, + selfDeaf: true, + selfMute: false, + voiceAdapterCreator: guild.voiceAdapterCreator, + }); + state.text_id = text_id; + state.queue = []; + state.player = createAudioPlayer(); + state.connection.subscribe(state.player); + + state.player.on("stateChange", (oldState, newState) => { + state.status = newState.status; + }); + + state.onEnd = async function () { + if (state.queue.length > 0) { + const next = state.queue.splice(0, 1)[0]; await enqueue({ guild_id, voice_id, @@ -146,11 +167,11 @@ async function createVoiceConnection(guild_id, voice_id, text_id) { url: next.url, type: next.type, addedBy: next.addedBy, - speex: next.speex, }); } else { - await connection.disconnect(); - if (!connection._music_leave) { + await state.player.stop(); + await state.connection.disconnect(); + if (!state.__leave) { await hf.bot.guilds .get(guild_id) .channels.get(text_id) @@ -158,15 +179,14 @@ async function createVoiceConnection(guild_id, voice_id, text_id) { ":musical_note: Queue is empty, leaving voice channel." ); } - connection.off("end", connection._music_eventEnd); + state.player.off(AudioPlayerStatus.Idle, state.onEnd); voiceStorage.delete(guild_id); } }; - connection.on("end", connection._music_eventEnd); + state.player.on(AudioPlayerStatus.Idle, state.End); + voiceStorage.set(guild_id, state); - voiceStorage.set(guild_id, connection); - - return connection; + return state; } async function enqueue({ @@ -178,7 +198,6 @@ async function enqueue({ addedBy, suppress = false, queueNext = false, - speex = false, }) { if (!url) return; @@ -210,7 +229,7 @@ async function enqueue({ ].url .replace("vi_webp", "vi") .replace(".webp", ".jpg"); - media = ytdl(url, { + media = await playdl.stream(url, { quality: "highestaudio", filter: "audioonly", highWaterMark: 1 << 25, @@ -234,7 +253,7 @@ async function enqueue({ title = info.title; length = info.duration; thumbnail = info.artwork_url; - media = streamUrl; + media = await playdl.stream(streamUrl); } else if (type == "file") { title = url; let info; @@ -260,10 +279,10 @@ async function enqueue({ } length = info.duration ? Math.floor(info.duration) * 1000 : 0; - media = url; + media = await playdl.stream(url); } - if (connection.playing) { + if (connection.status != AudioPlayerStatus.Idle) { const queueItem = { url, type, @@ -271,14 +290,13 @@ async function enqueue({ length, addedBy, stream, - speex, id: Math.random().toString(16).substring(2), }; if (queueNext === true) { - connection._music_queue.splice(0, 0, queueItem); + connection.queue.splice(0, 0, queueItem); } else { - connection._music_queue.push(queueItem); + connection.queue.push(queueItem); } if (suppress === false) { @@ -325,12 +343,8 @@ async function enqueue({ return; } - await connection.play(media, { - inlineVolume: true, - voiceDataTimeout: -1, - samplingRate: speex ? 8000 : 48000, - encoderArgs: speex ? ["-acodec", "speex", "-b:a", "8000"] : null, - }); + const resource = createAudioResource(media.stream, {inputType: media.type}); + connection.player.play(resource); textChannel.createMessage({ embeds: [ @@ -409,10 +423,14 @@ command.addAlias("m"); command.category = "misc"; command.helpText = "Music"; command.usage = "help"; -command.callback = async function (msg, line) { +command.callback = async function ( + msg, + line, + [subcommand, ...args], + {shuffle = false, limit = -1, offset = 0, next = false} +) { if (!msg.guildID) return "This command can only be used in guilds."; - const [subcommand, ...args] = line.split(" "); let argStr = args.join(" "); switch (subcommand) { @@ -426,36 +444,6 @@ command.callback = async function (msg, line) { } } - let shuffle = false; - if (argStr.includes("--shuffle")) { - shuffle = true; - argStr = argStr.replace("--shuffle", "").trim(); - } - - let limit = -1; - if (argStr.match(/--limit=(\d+)/)) { - limit = argStr.match(/--limit=(\d+)/)[1]; - argStr = argStr.replace(/--limit=(\d+)/, "").trim(); - } - - let offset = 0; - if (argStr.match(/--offset=(\d+)/)) { - offset = argStr.match(/--offset=(\d+)/)[1]; - argStr = argStr.replace(/--offset=(\d+)/, "").trim(); - } - - let queueNext = false; - if (argStr.match(/--next/)) { - queueNext = true; - argStr = argStr.replace(/--next/, "").trim(); - } - - let speex = false; - if (argStr.match(/--speex/)) { - speex = true; - argStr = argStr.replace(/--speex/, "").trim(); - } - let type; let playlist = false; @@ -531,7 +519,6 @@ command.callback = async function (msg, line) { type, addedBy: msg.author.id, supress: true, - speex, }); } await statusMessage.edit({ @@ -551,8 +538,7 @@ command.callback = async function (msg, line) { url: argStr, type, addedBy: msg.author.id, - queueNext, - speex, + queueNext: next, }); } } else { @@ -571,8 +557,7 @@ command.callback = async function (msg, line) { url: argStr, type: "file", addedBy: msg.author.id, - queueNext, - speex, + queueNext: next, }); } else { return "Unsupported content type."; @@ -587,8 +572,7 @@ command.callback = async function (msg, line) { url, type: "yt", addedBy: msg.author.id, - queueNext, - speex, + queueNext: next, }); } else { return url;