From 30569f4472117c37b6343f80c3196a5af141406a Mon Sep 17 00:00:00 2001 From: HappyTanuki Date: Sat, 19 Oct 2024 05:06:21 +0900 Subject: [PATCH] =?UTF-8?q?=EB=B9=84=EB=8F=99=EA=B8=B0=20=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=EB=A1=9C=EB=93=9C=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- .vscode/c_cpp_properties.json | 3 +- .vscode/launch.json | 2 +- .vscode/settings.json | 125 +++++++++++++++---------------- .vscode/tasks.json | 4 +- CMakeLists.txt | 4 +- include/AsyncDownloadManager.hpp | 37 ++++++--- include/BumbleBee.hpp | 19 ++--- src/AsyncDownloadManager.cpp | 60 +++++++++++++-- src/BumbleBee.cpp | 17 ++--- src/main.cpp | 10 ++- 11 files changed, 170 insertions(+), 116 deletions(-) diff --git a/.gitignore b/.gitignore index b185639..0add645 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ build/* -out/ -.vs/ -.idea/ -tmp/ +Temp/ config.json Music *.info.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index b4a26e9..5963335 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,8 +3,7 @@ { "name": "Linux", "includePath": [ - "${workspaceFolder}/**", - "${workspaceFolder}/include" + "${workspaceFolder}/**" ], "defines": [ "DDPP_CORO=on" diff --git a/.vscode/launch.json b/.vscode/launch.json index 16c0542..a238240 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "name": "Debug", "type": "cppdbg", "request": "launch", - "program": "/home/happytanuki/BumbleCee/build/BumbleCee", + "program": "${workspaceFolder}/build/BumbleCee", "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], diff --git a/.vscode/settings.json b/.vscode/settings.json index 0a4f658..9ae7d58 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,84 +1,81 @@ { "files.associations": { - "iostream": "cpp", - "any": "cpp", - "chrono": "cpp", - "codecvt": "cpp", - "compare": "cpp", - "condition_variable": "cpp", - "deque": "cpp", - "forward_list": "cpp", - "list": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "optional": "cpp", - "string_view": "cpp", - "random": "cpp", - "*.tcc": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "istream": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "ranges": "cpp", - "semaphore": "cpp", - "shared_mutex": "cpp", + "iosfwd": "cpp", "sstream": "cpp", - "stdexcept": "cpp", - "stop_token": "cpp", - "streambuf": "cpp", - "system_error": "cpp", - "thread": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "typeinfo": "cpp", - "valarray": "cpp", - "variant": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", "cctype": "cpp", - "charconv": "cpp", "clocale": "cpp", "cmath": "cpp", - "concepts": "cpp", - "coroutine": "cpp", "csignal": "cpp", "cstdarg": "cpp", "cstddef": "cpp", - "cstdint": "cpp", "cstdio": "cpp", "cstdlib": "cpp", "cstring": "cpp", "ctime": "cpp", "cwchar": "cpp", "cwctype": "cpp", - "map": "cpp", - "algorithm": "cpp", - "numeric": "cpp", - "ratio": "cpp", - "utility": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "limits": "cpp", - "numbers": "cpp", - "cinttypes": "cpp", - "bitset": "cpp", - "set": "cpp", - "regex": "cpp", - "format": "cpp", - "span": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", "strstream": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "compare": "cpp", "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "coroutine": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", "source_location": "cpp", - "typeindex": "cpp" + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "ranges": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "valarray": "cpp", + "variant": "cpp" } } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 650c89f..f790c8a 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -8,7 +8,7 @@ "command": "make", "args": [], "options": { - "cwd": "/home/happytanuki/BumbleCee/build/" + "cwd": "${workspaceFolder}/build/" }, "group": { "kind": "build", @@ -24,7 +24,7 @@ ".." ], "options": { - "cwd": "/home/happytanuki/BumbleCee/build/" + "cwd": "${workspaceFolder}/build/" }, "group": { "kind": "build", diff --git a/CMakeLists.txt b/CMakeLists.txt index f1b4551..1667003 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,4 +78,6 @@ else() endif() target_link_libraries(${BOT_NAME} dpp) -endif() \ No newline at end of file +endif() + +set(CMAKE_CXX_FLAGS "-g") \ No newline at end of file diff --git a/include/AsyncDownloadManager.hpp b/include/AsyncDownloadManager.hpp index f8f6a89..094031d 100644 --- a/include/AsyncDownloadManager.hpp +++ b/include/AsyncDownloadManager.hpp @@ -6,27 +6,40 @@ #include #include #include +#include +#include #define WORKER_COUNT 5 namespace bumbleBee { class AsyncDownloadManager { public: - static void enqueue(std::string query) { - static AsyncDownloadManager dl; - std::thread th(&bumbleBee::AsyncDownloadManager::enqueueAsyncDL, &dl, query); + static AsyncDownloadManager& getInstance(int worker_count, std::weak_ptr bot, std::weak_ptr musicQueue) { + static AsyncDownloadManager dl(worker_count); + dl.bot = bot; + dl.musicQueue = musicQueue; + return dl; + } + void enqueue(std::string query) { + std::thread th(&bumbleBee::AsyncDownloadManager::enqueueAsyncDL, this, query); th.detach(); } private: - AsyncDownloadManager(){ - for (int i=0; idownloadWorker();}); + } + } + ~AsyncDownloadManager(){ + terminate = true; + dlQueueCondition.notify_all(); + + for (auto& t : worker_thread) { + t.join(); } } - ~AsyncDownloadManager(){} - AsyncDownloadManager(const AsyncDownloadManager& ref) = delete; - AsyncDownloadManager& operator=(const AsyncDownloadManager& ref) = delete; void enqueueAsyncDL(std::string query); void downloadWorker(); @@ -34,6 +47,10 @@ private: std::queue downloadQueue; std::condition_variable dlQueueCondition; std::mutex dlQueueMutex; + std::weak_ptr bot; + std::weak_ptr musicQueue; + std::vector worker_thread; + bool terminate; }; } diff --git a/include/BumbleBee.hpp b/include/BumbleBee.hpp index 03a8aed..a587390 100644 --- a/include/BumbleBee.hpp +++ b/include/BumbleBee.hpp @@ -27,19 +27,13 @@ public: * @brief 파괴자 * @details BumbleBee의 모든 Property를 책임지고 파괴합니다 **/ - ~BumbleBee(); + ~BumbleBee() {} /** * @fn void start() * @brief 봇 시작 **/ void start(); - /** - * @fn bool addCommand(commands::ICommand cmd) - * @brief ICommand 인터페이스에 맞는 커맨드를 추가 - * @warning 이 메소드는 start()메소드가 호출되기 전에 호출되어야 함 - **/ - bool addCommand(commands::ICommand cmd); /** * @fn void on_slashcommand(const dpp::slashcommand_t& event) @@ -53,9 +47,12 @@ public: * @param event **/ void on_ready(const dpp::ready_t &event); -private: + /// @brief DPP 기본 클러스터 객체 - std::unique_ptr cluster; + std::shared_ptr cluster; + /// @brief 음악 큐 + std::shared_ptr queue; +private: /// @brief db 드라이버 sql::Driver* dbDriver; /// @brief db 접속 URL @@ -63,9 +60,7 @@ private: /// @brief db 접속 속성 std::shared_ptr dbProperties; /// @brief Command 목록 - std::vector commands; - /// @brief 음악 큐 - std::shared_ptr queue; + std::vector> commands; }; } #endif \ No newline at end of file diff --git a/src/AsyncDownloadManager.cpp b/src/AsyncDownloadManager.cpp index fbf32b8..d79e597 100644 --- a/src/AsyncDownloadManager.cpp +++ b/src/AsyncDownloadManager.cpp @@ -1,25 +1,69 @@ #include +#include namespace bumbleBee { void AsyncDownloadManager::enqueueAsyncDL(std::string query) { - dlQueueMutex.lock(); + std::lock_guard lock(dlQueueMutex); downloadQueue.push(query); - dlQueueMutex.unlock(); dlQueueCondition.notify_one(); } +std::string getResultFromCommand(std::string cmd) { + std::string result; + FILE* stream; + const int maxBuffer = 12; // 버퍼의 크기는 적당하게 + char buffer[maxBuffer]; + cmd.append(" 2>&1"); // 표준에러를 표준출력으로 redirect + + stream = popen(cmd.c_str(), "r"); // 주어진 command를 shell로 실행하고 파이프 연결 (fd 반환) + if (stream) { + while (fgets(buffer, maxBuffer, stream) != NULL) result.append(buffer); // fgets: fd (stream)를 길이 (maxBuffer)만큼 읽어 버퍼 (buffer)에 저장 + pclose(stream); // 파이프 닫는 것 잊지 마시고요! + } + return result; +} + void AsyncDownloadManager::downloadWorker() { - std::unique_lock dlQueueLock(dlQueueMutex); + std::ostringstream tid; + tid << std::this_thread::get_id(); while (true) { //mutex lock - dlQueueLock.lock(); - dlQueueCondition.wait(dlQueueLock, [&]{ return !downloadQueue.empty(); }); - - system(("./yt-dlp --no-clean-info-json --write-info-json --default-search ytsearch \ - --flat-playlist --skip-download --quiet --ignore-errors -f ba* " + downloadQueue.front()).c_str()); + std::unique_lock dlQueueLock(dlQueueMutex); + dlQueueCondition.wait(dlQueueLock, [&]{ return !downloadQueue.empty() || terminate; }); + std::string query = downloadQueue.front(); downloadQueue.pop(); dlQueueLock.unlock(); + auto cluster = bot.lock(); + assert(cluster); + + cluster->log(dpp::ll_info, "Enqueuing " + query + " accepted."); + + std::string idstring = getResultFromCommand("./yt-dlp --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors --print id " + query); + std::queue ids; + std::stringstream ss(idstring); + + std::string _id; + while (std::getline(ss, _id, '\n')) { + ids.push(_id); + } + + if (ids.size() >= 2) { + cluster->log(dpp::ll_info, "Playlist detected."); + while (!ids.empty()) { + cluster->log(dpp::ll_info, "Enqueuing " + ids.front()); + enqueue("https://youtu.be/" + ids.front()); + ids.pop(); + } + break; + } + + cluster->log(dpp::ll_info, "Thread id: " + tid.str() + ": " + ids.front() + " accepted."); + + system(("./yt-dlp -o \"Temp/%(id)s\" --no-clean-info-json --write-info-json --default-search ytsearch \ + --flat-playlist --skip-download --quiet --ignore-errors -f ba* https://youtu.be/" + ids.front()).c_str()); + + cluster->log(dpp::ll_info, "Thread id: " + tid.str() + ": " + ids.front() + " downloaded."); } } } \ No newline at end of file diff --git a/src/BumbleBee.cpp b/src/BumbleBee.cpp index 3943004..33237a3 100644 --- a/src/BumbleBee.cpp +++ b/src/BumbleBee.cpp @@ -2,7 +2,7 @@ namespace bumbleBee{ BumbleBee::BumbleBee(nlohmann::json settings) { - this->cluster = std::make_unique(settings["token"]); + this->cluster = std::make_shared(settings["token"]); dbDriver = sql::mariadb::get_driver_instance(); this->dbURL = std::make_shared(settings["dbURL"]); sql::Properties pro({ @@ -16,21 +16,16 @@ BumbleBee::BumbleBee(nlohmann::json settings) { cluster->on_ready([this](const dpp::ready_t &event){on_ready(event);}); } -BumbleBee::~BumbleBee() { -} - void BumbleBee::start() { this->cluster->start(dpp::st_wait); } -bool BumbleBee::addCommand(commands::ICommand cmd) { - commands.push_back(cmd); - return false; -} - void BumbleBee::on_slashcommand(const dpp::slashcommand_t &event) { - + for (auto command : commands) + for (auto alias : command->nameAndAliases) + if (event.command.get_command_name() == alias.name) + (*command)(event); } + void BumbleBee::on_ready(const dpp::ready_t &event) { cluster->log(dpp::loglevel::ll_info, "Bot ready."); } - } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f7c7e7a..2262a67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include int main() { nlohmann::json configdocument; @@ -8,5 +10,11 @@ int main() { bumbleBee::BumbleBee bot(configdocument); - bot.start(); + bumbleBee::AsyncDownloadManager& manager = bumbleBee::AsyncDownloadManager::getInstance(5, bot.cluster, bot.queue); + manager.enqueue("https://music.youtube.com/playlist?list=PL5NSTAfQ-wQBqZYMTqxADemyUW8mxJq2h&si=S1OwPaaif_litCqN"); + + std::thread th([](){sleep(100);}); + th.join(); + + //bot.start(); } \ No newline at end of file