From 2f5185e0c3fdb86ae37d0dbdc1e01ace2618cd4c Mon Sep 17 00:00:00 2001 From: HappyTanuki Date: Mon, 3 Feb 2025 01:42:02 +0900 Subject: [PATCH] =?UTF-8?q?=ED=81=90=20=EC=B6=9C=EB=A0=A5=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Utils/QueuedMusicListEmbedProvider.hpp | 28 ++-- src/Commands/Play.cpp | 124 ++++++++++++++++-- src/Commands/Queue.cpp | 38 +++++- 3 files changed, 153 insertions(+), 37 deletions(-) diff --git a/include/Utils/QueuedMusicListEmbedProvider.hpp b/include/Utils/QueuedMusicListEmbedProvider.hpp index a38894a..e339681 100644 --- a/include/Utils/QueuedMusicListEmbedProvider.hpp +++ b/include/Utils/QueuedMusicListEmbedProvider.hpp @@ -6,38 +6,30 @@ namespace bumbleBee { class QueuedMusicListEmbedProvider { public: - static std::queue makeEmbed(std::list> queue, std::list>::iterator np, bool repeat) { + static std::queue makeEmbed(std::shared_ptr>> queue, std::list>::iterator np, bool repeat) { std::queue returnValue; - std::list>::iterator it = queue.begin(); - if (queue.size() == 0) { + std::list>::iterator it = queue->begin(); + if (queue->size() == 0) { dpp::embed embed = makeEmbedPart(queue, np, repeat, it); returnValue.push(embed); return returnValue; } - for (int i = 0; i < std::ceil(queue.size() / 5.0); i++) { + for (int i = 0; i < std::ceil(queue->size() / 5.0) && it != queue->end(); i++) { dpp::embed embed = makeEmbedPart(queue, np, repeat, it); returnValue.push(embed); } return returnValue; } - - static int distance(const std::list>::iterator a, const std::list>::iterator b) { - int i = 0; - std::list>::iterator mutatea = a; - while (mutatea++ == b) - i++; - return i; - } private: static dpp::embed makeEmbedPart( - std::list> queue, + std::shared_ptr>> queue, std::list>::iterator np, bool repeat, - std::list>::iterator startIter) { + std::list>::iterator &startIter) { dpp::embed embed = dpp::embed() .set_color(dpp::colors::sti_blue); - if (queue.begin() == queue.end()) { + if (queue->begin() == queue->end()) { embed .set_title("큐가 비었습니다!") .set_timestamp(time(0)); @@ -48,10 +40,10 @@ private: return embed; } - int startIndex = distance(queue.begin(), startIter) + 1; + int startIndex = std::distance(queue->begin(), startIter) + 1; int index = startIndex; - for (; (index < startIndex + 5) && startIter != queue.end() && index < queue.size()+1; startIter++, index++) { //iter로 순회하면 왠지 모르게 이상한 값을 읽을 때가 있음 이유는 나도 몰?루 + for (; (index < startIndex + 5) && startIter != queue->end() && index < queue->size()+1; startIter++, index++) { //iter로 순회하면 왠지 모르게 이상한 값을 읽을 때가 있음 이유는 나도 몰?루 if (*startIter == *np) embed.add_field ( "np", @@ -72,7 +64,7 @@ private: .add_field("",""); } - if (startIter == queue.end() || index >= queue.size()+1) { + if (startIter == queue->end() || index >= queue->size()+1) { embed.set_timestamp(time(0)); if (repeat) embed.add_field(":repeat:",""); diff --git a/src/Commands/Play.cpp b/src/Commands/Play.cpp index fdb2853..93685de 100644 --- a/src/Commands/Play.cpp +++ b/src/Commands/Play.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include namespace bumbleBee::commands { @@ -40,10 +41,9 @@ namespace bumbleBee::commands { else msg.content = "큐에 다음 곡을 추가했습니다:"; - while (!ids.empty()) { + if (!ids.empty()) { if (ids.front() == "") { ids.pop(); - continue; } FILE* file = popen((SettingsManager::getYTDLP_CMD() + @@ -92,6 +92,115 @@ namespace bumbleBee::commands { ids.pop(); } + if (!ids.empty()) { + std::thread t([]( + std::queue ids, + dpp::snowflake guildId, + dpp::snowflake channelId, + std::string query, + dpp::user user, + dpp::cluster* cluster, + std::shared_ptr manager + ) { + while (!ids.empty()) { + if (ids.front() == "") { + ids.pop(); + continue; + } + + FILE* file = popen((SettingsManager::getYTDLP_CMD() + + " --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors -J http://youtu.be/" + ids.front()).c_str(), "r"); + + std::ostringstream oss; + char buffer[1024]; + size_t bytesRead; + + while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) { + oss.write(buffer, bytesRead); + } + pclose(file); + + std::istringstream iss(oss.str()); + nlohmann::json videoDataJson; + iss >> videoDataJson; + + time_t SongLength = int(videoDataJson["duration"]); + char SongLengthStr[13]; + tm t; + t.tm_mday = SongLength / 86400; + t.tm_hour = (SongLength % 86400)/3600; + t.tm_min = (SongLength % 3600)/60; + t.tm_sec = SongLength%60; + if (t.tm_mday > 0) + strftime(SongLengthStr, sizeof(SongLengthStr), "%d:%H:%M:%S", &t); + else if (t.tm_hour > 0) + strftime(SongLengthStr, sizeof(SongLengthStr), "%H:%M:%S", &t); + else + strftime(SongLengthStr, sizeof(SongLengthStr), "%M:%S", &t); + + dpp::embed embed = dpp::embed() + .set_color(dpp::colors::sti_blue) + .set_title(std::string(videoDataJson["title"])) + .set_description(std::string(videoDataJson["uploader"])) + .set_url(std::string(videoDataJson["webpage_url"])) + .set_image(std::string(videoDataJson["thumbnail"])) + .add_field( + "길이", + SongLengthStr, + true + ); + + auto music = std::make_shared(ids.front(), query, user, embed); + + cluster->log(dpp::ll_info, "Enqueuing " + music->embed.title + " - " + music->id); + manager->queue_music(guildId, music); + ids.pop(); + } + + std::mutex messageorder; + std::unique_lock lock(messageorder); + std::condition_variable messageSentCondition; // 개씨발 코드 개더러워 ;; + bool messagesent = false; + auto queue = manager->getQueue(guildId); + auto queued = QueuedMusicListEmbedProvider::makeEmbed(queue.first, queue.second, manager->getRepeat(guildId)); + if (!queued.empty()) { + dpp::message followMsg(channelId, "현재 큐에 있는 항목:"); + + followMsg.add_embed(queued.front()); + messagesent = false; + cluster->message_create(followMsg, [&](const dpp::confirmation_callback_t &callback){ + messagesent = true; + messageSentCondition.notify_all(); + }); + + messageSentCondition.wait(lock, [&](){ return messagesent; }); + queued.pop(); + } + while (!queued.empty()) { + dpp::message followMsg(channelId, ""); + + followMsg.add_embed(queued.front()); + messagesent = false; + cluster->message_create(followMsg, [&](const dpp::confirmation_callback_t &callback){ + messagesent = true; + messageSentCondition.notify_all(); + }); + + messageSentCondition.wait(lock, [&](){ return messagesent; }); + queued.pop(); + } + }, + ids, + event.command.guild_id, + event.command.channel_id, + query, + event.command.usr, + event.from->creator, + musicManager); + + t.detach(); + } + if (!musics.empty()) { event.from->creator->log(dpp::ll_info, "Enqueuing " + musics.front()->embed.title + " - " + musics.front()->id); musicManager->queue_music(event.command.guild_id, musics.front()); @@ -100,17 +209,6 @@ namespace bumbleBee::commands { event.edit_original_response(msg); musicManager->queuedCondition.notify_all(); - - while (!musics.empty()) { - event.from->creator->log(dpp::ll_info, "Enqueuing " + musics.front()->embed.title + " - " + musics.front()->id); - dpp::message followMsg(event.command.channel_id, ""); - - followMsg.add_embed(musics.front()->embed); - event.from->creator->message_create(followMsg); // 어차피 원래 메시지를 지정해서 수정할 것이기 때문에 먼저 팔로잉 메시지를 작성해도 상관없음. - - musicManager->queue_music(event.command.guild_id, musics.front()); - musics.pop(); - } } else { msg.content = "검색 결과가 없습니다"; diff --git a/src/Commands/Queue.cpp b/src/Commands/Queue.cpp index 51cdccf..5c64f6b 100644 --- a/src/Commands/Queue.cpp +++ b/src/Commands/Queue.cpp @@ -8,7 +8,7 @@ namespace bumbleBee::commands { dpp::message msg; dpp::embed embed; - auto queued = QueuedMusicListEmbedProvider::makeEmbed(*queue.first, queue.second, musicManager->getRepeat(event.command.guild_id)); + auto queued = QueuedMusicListEmbedProvider::makeEmbed(queue.first, queue.second, musicManager->getRepeat(event.command.guild_id)); // if (queue.first.size() == 0) { // msg.add_embed(queued.front()); @@ -32,12 +32,38 @@ namespace bumbleBee::commands { } std::thread t([](std::queue queued, dpp::snowflake channel_id, dpp::cluster* cluster) { - for (; !queued.empty(); queued.pop()) { - dpp::message followMsg(channel_id, "현재 큐에 있는 항목:"); + std::mutex messageorder; + std::unique_lock lock(messageorder); + std::condition_variable messageSentCondition; + bool messagesent = false; + if (!queued.empty()) { + dpp::message followMsg(channel_id, "현재 큐에 있는 항목:"); - followMsg.add_embed(queued.front()); - cluster->message_create(followMsg); - } + followMsg.add_embed(queued.front()); + messagesent = false; + cluster->message_create(followMsg, [&](const dpp::confirmation_callback_t &callback){ + messagesent = true; + messageSentCondition.notify_all(); + }); + + messageSentCondition.wait(lock, [&](){ return messagesent; }); + + queued.pop(); + } + while (!queued.empty()) { + dpp::message followMsg(channel_id, ""); + + followMsg.add_embed(queued.front()); + + messagesent = false; + cluster->message_create(followMsg, [&](const dpp::confirmation_callback_t &callback){ + messagesent = true; + messageSentCondition.notify_all(); + }); + + messageSentCondition.wait(lock, [&](){ return messagesent; }); + queued.pop(); + } }, queued, event.command.channel_id, event.from->creator); t.detach(); }