From 23a0199d5de24e98125292bd13def85a4194b41b Mon Sep 17 00:00:00 2001 From: = Date: Sat, 9 Sep 2023 21:53:34 +0900 Subject: [PATCH] Update 2.0 --- README.md | 7 +++++++ commands/seek.js | 47 ++++++++++++++++++++++++++++++++++++++++++++ commands/skip.js | 43 ++++++++++++++++++++++++++++++++++------ functions/handler.js | 2 +- functions/skiper.js | 45 ++++++++++++++++++++++++++++++++++++------ index.js | 6 +++++- lib/stellar.js | 21 ++++++++++++++------ package-lock.json | 16 +++++++-------- package.json | 2 +- 9 files changed, 160 insertions(+), 29 deletions(-) create mode 100644 commands/seek.js diff --git a/README.md b/README.md index 0c176c7..684c0db 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,13 @@ Daydream, StellarLoom 프로젝트를 체험해보고 싶다면 유피를 서버 --- +## 🎉 2.0 업데이트 +- 대량 스킵 기능이 추가됬어요. ( /스킵 1 10 -> 1번 ~ 10번 트랙 스킵 ) +- 이동 기능이 추가됬어요. ( /이동 1 30 -> 1분 30초 위치로 이동 ) +- 스킵 사용 이후 트랙 자동 스킵이 안되던 문제를 해결했어요. + +--- + ## **목차** ### **설치** diff --git a/commands/seek.js b/commands/seek.js new file mode 100644 index 0000000..4acb75e --- /dev/null +++ b/commands/seek.js @@ -0,0 +1,47 @@ +let { connection, playlist, volume, station } = require("../lib/val.js"); + +const { EmbedBuilder, SlashCommandBuilder } = require("discord.js"); + +const stellar = require("../lib/stellar.js"); + +const embeded = require("../util/embed.js"); + +module.exports = { + data: new SlashCommandBuilder() + .setName("이동") + .setDescription("현재 트랙을 특정 시간부터 재생해요.") + .addStringOption((option) => + option.setName("옵션") + .setDescription("이동 할 시간(위치)를 입력해주세요. 예를 들어 1 30 은 1분 30초 부터 재생합니다.") + .setRequired(true)), + + async execute(interaction) { + + if (!connection[interaction.guild.id]) return embeded.replyEmbed(interaction, ":triangular_flag_on_post: **|** 재생 중인 노래가 없습니다!", "이동 할 노래가 없습니다."); + if (!playlist[interaction.guild.id]) return embeded.replyEmbed(interaction, ":triangular_flag_on_post: **|** 재생 목록을 찾지 못했습니다!", "이것 참 심오하군요..."); + + let target; + + if (interaction.options.data[0].value.search(" ") > -1) { + target = interaction.options.data[0].value.split(" "); + + let temp_target = 0; + for (let o in target) { + temp_target += parseInt(target[o]) * (1000 * (60 ** ((Object.keys(target).length - o) - 1))); + } + + target = temp_target; + } + + else target = parseInt(interaction.options.data[0].value) * 1000; + + await stellar.seekTrack(interaction, target); + + const seekemb = new EmbedBuilder() + .setColor("#28edbc") + .setTitle(":fast_forward: **|** 재생 시간을 옮겼습니다!") + .setThumbnail("https://img.youtube.com/vi/" + playlist[interaction.guild.id][0].id + "/mqdefault.jpg") + return interaction.reply({ embeds: [seekemb] }); + + } +} \ No newline at end of file diff --git a/commands/skip.js b/commands/skip.js index 3395a72..9ce549a 100644 --- a/commands/skip.js +++ b/commands/skip.js @@ -2,8 +2,6 @@ let { connection, playlist, volume, station } = require("../lib/val.js"); const { EmbedBuilder, SlashCommandBuilder } = require("discord.js"); -const stellar = require("../lib/stellar.js"); - const embeded = require("../util/embed.js"); const skiper = require("../functions/skiper.js"); @@ -22,14 +20,23 @@ module.exports = { if (!playlist[interaction.guild.id]) return embeded.replyEmbed(interaction, ":triangular_flag_on_post: **|** 재생 목록을 찾지 못했습니다!", "이것 참 심오하군요..."); let val; - if (interaction.options.data[0]) val = parseInt(interaction.options.data[0].value) - 1; + if (interaction.options.data[0]) { + val = interaction.options.data[0].value; + console.log(val); + console.log(val.search(" ") > -1); + + if (!(val.search(" ") > -1)) val = parseInt(val) - 1; + else val = [parseInt(val.split(" ")[0]) - 1, parseInt(val.split(" ")[1]) - 1]; + } else val = 0; - if (val > -1 && val < Object.keys(playlist[interaction.guild.id]).length) { + console.log(val); + + if (!val[1] && val > -1 && val < Object.keys(playlist[interaction.guild.id]).length) { let temp_track = { title: playlist[interaction.guild.id][val].title, id: playlist[interaction.guild.id][val].id }; - await skiper.skipTrack(interaction, ["FORCE", val]); + await skiper.skipTrack(interaction, val, "FORCE"); const skiemb = new EmbedBuilder() .setColor("#28edbc") @@ -40,7 +47,31 @@ module.exports = { } - else return embeded.replyEmbed(interaction, ":triangular_flag_on_post: **|** " + (val + 1) + "번 트랙을 찾지 못했습니다!", "!재생목록 에서 트랙 번호를 다시 한번 확인 해주세요!"); + else if (String(val[0]) && val[1] && val[0] > -1 && val[1] < Object.keys(playlist[interaction.guild.id]).length && val[0] < val[1]) { + + let temp_track = { title: playlist[interaction.guild.id][val[0]].title, id: playlist[interaction.guild.id][val[0]].id }; + + let tempVal = [val[0], val[1]]; + let res = ""; + + while (tempVal[0] < tempVal[1] + 1) { + res += "**`" + (parseInt(tempVal[0]) + 1) + "`** | " + playlist[interaction.guild.id][tempVal[0]].title + "\n"; + tempVal[0]++; + } + + await skiper.bulkSkipTrack(interaction, val); + + const skiemb = new EmbedBuilder() + .setColor("#28edbc") + .setTitle(":track_next: **|** 전부 스킵되었습니다!") + .setDescription(res) + .setThumbnail("https://img.youtube.com/vi/" + temp_track.id + "/mqdefault.jpg") + return interaction.reply({ embeds: [skiemb] }); + + } + + else if (!val[1]) return embeded.replyEmbed(interaction, ":triangular_flag_on_post: **|** " + (val + 1) + "번 트랙을 찾지 못했습니다!", "!재생목록 에서 트랙 번호를 다시 한번 확인 해주세요!"); + else return embeded.replyEmbed(interaction, ":triangular_flag_on_post: **|** 해당 트랙을 찾지 못했습니다!", "!재생목록 에서 트랙 번호를 다시 한번 확인 해주세요!"); } } \ No newline at end of file diff --git a/functions/handler.js b/functions/handler.js index 88eac0b..a96c971 100644 --- a/functions/handler.js +++ b/functions/handler.js @@ -5,7 +5,7 @@ async function playTrack (interaction) { const stellar = require("../lib/stellar.js"); - stellar.playTrack(interaction, playlist[interaction.guild.id][0].data); + await stellar.playTrack(interaction, playlist[interaction.guild.id][0].data); //Noti off when repeating if (station[interaction.guild.id] === "REPEAT") return; diff --git a/functions/skiper.js b/functions/skiper.js index 8982e2e..0592eeb 100644 --- a/functions/skiper.js +++ b/functions/skiper.js @@ -1,16 +1,15 @@ -async function skipTrack (interaction, trackID) { +async function skipTrack (interaction, trackID, reason) { + let { connection, playlist, volume, station } = require("../lib/val.js"); const cleaner = require("../functions/cleaner.js"); const handler = require("../functions/handler.js"); //Repeat Handler - if (!trackID[0] && station[interaction.guild.id]) { + if (station[interaction.guild.id] === "REPEAT" && reason === "TrackEND") { const last_trackID = Object.keys(playlist[interaction.guild.id]).length; - playlist[interaction.guild.id][last_trackID] = playlist[interaction.guild.id][trackID]; + playlist[interaction.guild.id][last_trackID] = playlist[interaction.guild.id][0]; } - - else if (trackID[0]) trackID = trackID[1]; //Repeat Handler console.log(trackID); @@ -34,6 +33,40 @@ async function skipTrack (interaction, trackID) { } +async function bulkSkipTrack (interaction, trackID) { + + let { connection, playlist, volume, station } = require("../lib/val.js"); + + const cleaner = require("../functions/cleaner.js"); + const handler = require("../functions/handler.js"); + + console.log(trackID); + + const tempTrackID = trackID[0]; + + while (trackID[0] < trackID[1] + 1) { + delete playlist[interaction.guild.id][trackID[0]]; + trackID[0]++; + } + + let temp_list = playlist[interaction.guild.id]; + playlist[interaction.guild.id] = new Map(); + + let unter = 0; + for (let o in temp_list) { + playlist[interaction.guild.id][unter] = temp_list[o]; + unter++; + } + + console.log(playlist[interaction.guild.id]); + + if (!playlist[interaction.guild.id][0]) return cleaner.clearResource(interaction); + + if (tempTrackID == 0) return handler.playTrack(interaction); + +} + module.exports = { - skipTrack: skipTrack + skipTrack: skipTrack, + bulkSkipTrack: bulkSkipTrack } \ No newline at end of file diff --git a/index.js b/index.js index 342a881..52302bf 100644 --- a/index.js +++ b/index.js @@ -20,6 +20,10 @@ bot.on("ready", () => { }); }); +//LavaLinkAlert +console.log("[StellarLoom] 노래 재생에 문제가 있거나 노래를 재생하는 도중 지속적으로 오류가 발생한다면 LavaLink.jar 을 업데이트 해보세요."); +//LavaLinkAlert + process.on("unhandledRejection", (error) => { console.error("Unhandled promise rejection : ", error); }); @@ -34,7 +38,7 @@ bot.on("ready", () => { //Coomand bot.commands = new Collection(); -const config = ["play", "skip", "playlist", "stop", "repeat", "shuffle"]; +const config = ["play", "skip", "playlist", "stop", "repeat", "shuffle", "seek"]; const commands = []; const rest = new REST({ version: "10" }).setToken(process.env.BOT_TOKEN); diff --git a/lib/stellar.js b/lib/stellar.js index 3adc80b..74a411f 100644 --- a/lib/stellar.js +++ b/lib/stellar.js @@ -144,11 +144,19 @@ async function playTrack (interaction, track) { console.log(connection[interaction.guild.id]); - connection[interaction.guild.id].once("end", (data) => { - console.log(data); - if (data.type === "TrackEndEvent" && data.reason === "REPLACED") return; - return skiper.skipTrack(interaction, 0); - }); + setTimeout(() => { + connection[interaction.guild.id].once("end", (data) => { + console.log(data); + if (data.type === "TrackEndEvent" && data.reason === "REPLACED") return; + return skiper.skipTrack(interaction, 0, "TrackEND"); + }); + }, 1000); +} + +async function seekTrack (interaction, position) { + console.log(position); + + await connection[interaction.guild.id].seek(position); } module.exports = { @@ -157,5 +165,6 @@ module.exports = { searchYT: searchYT, joinVoiceChannel: joinVoiceChannel, leaveVoiceChannel: leaveVoiceChannel, - playTrack: playTrack + playTrack: playTrack, + seekTrack: seekTrack } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4e19f88..043f28c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "stellarloom", - "version": "1.1.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "stellarloom", - "version": "1.1.0", + "version": "2.0.0", "license": "MIT", "dependencies": { "discord.js": "^14.11.0", @@ -132,9 +132,9 @@ } }, "node_modules/@types/node": { - "version": "20.5.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz", - "integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==" + "version": "20.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.0.tgz", + "integrity": "sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==" }, "node_modules/@types/ws": { "version": "8.5.5", @@ -330,9 +330,9 @@ } }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", + "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 433ddd0..de9642e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "stellarloom", "displayName": "StellarLoom Preview", - "version": "1.1.0", + "version": "2.0.0", "description": "거대한 프로젝트를 위한 안정성 있고 효율적인 한국어 기반 디스코드 뮤직 봇", "main": "index.js", "engines": {