mirror of
https://github.com/HappyTanuki/BumbleCee.git
synced 2025-10-26 09:55:14 +00:00
일단은 임시저장, 스트리밍의 실마리를 잡았다
This commit is contained in:
@@ -1,36 +1,20 @@
|
||||
#include <AsyncDownloadManager.hpp>
|
||||
#include <sstream>
|
||||
#include "Utils/ConsoleUtils.hpp"
|
||||
#include "Settings/SettingsManager.hpp"
|
||||
#include <ogg/ogg.h>
|
||||
#include <oggz/oggz.h>
|
||||
#include <opus/opusfile.h>
|
||||
#include <memory>
|
||||
|
||||
namespace bumbleBee {
|
||||
|
||||
void AsyncDownloadManager::enqueueAsyncDL(std::string query) {
|
||||
void AsyncDownloadManager::enqueueAsyncDL(std::pair<std::string, dpp::message> query) {
|
||||
std::lock_guard<std::mutex> lock(dlQueueMutex);
|
||||
downloadQueue.push(query);
|
||||
dlQueueCondition.notify_one();
|
||||
}
|
||||
|
||||
std::queue<std::string> getResultFromCommand(std::string cmd) {
|
||||
std::string result, token;
|
||||
std::queue<std::string> tokens;
|
||||
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);
|
||||
}
|
||||
|
||||
std::stringstream ss(result);
|
||||
while (std::getline(ss, token, '\n')) {
|
||||
tokens.push(token);
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
void AsyncDownloadManager::downloadWorker() {
|
||||
std::ostringstream tid;
|
||||
tid << std::this_thread::get_id();
|
||||
@@ -38,38 +22,49 @@ void AsyncDownloadManager::downloadWorker() {
|
||||
//mutex lock
|
||||
std::unique_lock<std::mutex> dlQueueLock(dlQueueMutex);
|
||||
dlQueueCondition.wait(dlQueueLock, [&]{ return !downloadQueue.empty() || terminate; });
|
||||
auto cluster = bot.lock();
|
||||
assert(cluster);
|
||||
if (terminate) {
|
||||
cluster->log(dpp::ll_info, "Terminating Thread" + tid.str());
|
||||
auto cluster = weak_cluster.lock();
|
||||
if (weak_cluster.expired()) {
|
||||
cluster->log(dpp::ll_error, "Missing cluster, terminating thread " + tid.str());
|
||||
break;
|
||||
}
|
||||
std::string query = downloadQueue.front();
|
||||
if (terminate) {
|
||||
cluster->log(dpp::ll_info, "Terminating thread " + tid.str());
|
||||
break;
|
||||
}
|
||||
std::string query = downloadQueue.front().first;
|
||||
dpp::message oRes = downloadQueue.front().second;
|
||||
downloadQueue.pop();
|
||||
dlQueueLock.unlock();
|
||||
|
||||
cluster->log(dpp::ll_info, "Enqueuing " + query + " accepted.");
|
||||
cluster->log(dpp::ll_info, "AsyncDownloadManager: " + query + " accepted.");
|
||||
|
||||
std::queue<std::string> ids = getResultFromCommand("./yt-dlp --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors --print id " + query);
|
||||
std::queue<std::string> ids =
|
||||
ConsoleUtils::getResultFromCommand(settingsManager::YTDLP_CMD +
|
||||
" --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors --print id " + query);
|
||||
|
||||
if (ids.size() >= 2) {
|
||||
cluster->log(dpp::ll_info, query + " is playlist");
|
||||
while (!ids.empty()) {
|
||||
if (ids.front() == "") {
|
||||
ids.pop();
|
||||
continue;
|
||||
}
|
||||
cluster->log(dpp::ll_info, "Enqueuing " + ids.front());
|
||||
enqueue("https://youtu.be/" + ids.front());
|
||||
cluster->log(dpp::ll_info, "Enqueuing playlist element " + ids.front());
|
||||
enqueue(std::make_pair("https://youtu.be/" + ids.front(), oRes));
|
||||
ids.pop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
std::queue<std::string> urls = getResultFromCommand("./yt-dlp -f ba* --print urls https://youtu.be/" + ids.front());
|
||||
std::queue<std::string> urls =
|
||||
ConsoleUtils::getResultFromCommand(settingsManager::YTDLP_CMD +
|
||||
" -f ba* --print urls https://youtu.be/" + ids.front());
|
||||
|
||||
cluster->log(dpp::ll_info, "url: " + urls.front());
|
||||
cluster->log(dpp::ll_debug, "url: " + urls.front());
|
||||
|
||||
musicQueue->enqueue(std::make_shared<MusicQueueElement>(ids.front(), urls.front()));
|
||||
FILE* stream;
|
||||
|
||||
musicQueue->enqueue(std::make_shared<MusicQueueElement>(oRes, ids.front(), urls.front(), stream));
|
||||
|
||||
std::string downloadID = ids.front();
|
||||
|
||||
@@ -81,13 +76,12 @@ void AsyncDownloadManager::downloadWorker() {
|
||||
|
||||
cluster->log(dpp::ll_info, "Thread id: " + tid.str() + ": " + downloadID + " accepted.");
|
||||
|
||||
system(("./yt-dlp -o \"Temp/%(id)s\" --quiet --ignore-errors -f ba* https://youtu.be/" + downloadID).c_str());
|
||||
std::string command = std::string("./streamAndDownload.sh " + settingsManager::YTDLP_CMD + " " + downloadID + " " + settingsManager::FFMPEG_CMD);
|
||||
stream = popen(command.c_str(), "r");
|
||||
pclose(stream);
|
||||
stream = NULL;
|
||||
|
||||
system((std::string() + "yes n 2>/dev/null | ffmpeg -hide_banner -loglevel error -i \""
|
||||
+ "Temp/" + downloadID + "\" -acodec libopus -vn Music/" + downloadID + ".ogg").c_str());
|
||||
system((std::string() + "rm -f Temp/" + downloadID).c_str());
|
||||
|
||||
cluster->log(dpp::ll_info, "Thread id: " + tid.str() + ": " + downloadID + " downloaded.");
|
||||
cluster->log(dpp::ll_info, "Thread id: " + tid.str() + ": " + downloadID + " download complete.");
|
||||
});
|
||||
th.detach();
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
#include <BumbleBee.hpp>
|
||||
#include <memory>
|
||||
#include <Settings/SettingsManager.hpp>
|
||||
#include <Utils/VersionsCheckUtils.hpp>
|
||||
|
||||
namespace bumbleBee{
|
||||
BumbleBee::BumbleBee(nlohmann::json settings) {
|
||||
this->cluster = std::make_shared<dpp::cluster>(settings["token"]);
|
||||
BumbleBee::BumbleBee() {
|
||||
settingsManager::load();
|
||||
this->cluster = std::make_shared<dpp::cluster>(settingsManager::TOKEN);
|
||||
dbDriver = sql::mariadb::get_driver_instance();
|
||||
this->dbURL = std::make_shared<sql::SQLString>(settings["dbURL"]);
|
||||
this->dbURL = std::make_shared<sql::SQLString>(settingsManager::DBURL);
|
||||
sql::Properties pro({
|
||||
{"user", std::string(settings["user"])},
|
||||
{"password", std::string(settings["password"])}
|
||||
{"user", std::string(settingsManager::DBUSER)},
|
||||
{"password", std::string(settingsManager::DBPASSWORD)}
|
||||
});
|
||||
this->dbProperties = std::make_shared<sql::Properties>(pro);
|
||||
|
||||
@@ -16,6 +20,9 @@ BumbleBee::BumbleBee(nlohmann::json settings) {
|
||||
cluster->on_ready([this](const dpp::ready_t &event){on_ready(event);});
|
||||
|
||||
queue = std::make_shared<MusicQueue>();
|
||||
|
||||
VersionsCheckUtils::validateYTDLPFFMPEGBinary(cluster);
|
||||
VersionsCheckUtils::updateytdlp(cluster);
|
||||
}
|
||||
|
||||
void BumbleBee::start() { this->cluster->start(dpp::st_wait); }
|
||||
|
||||
@@ -14,7 +14,17 @@ std::shared_ptr<MusicQueueElement> MusicQueue::dequeue() {
|
||||
queue.pop_front();
|
||||
return value;
|
||||
}
|
||||
std::weak_ptr<MusicQueueElement> MusicQueue::nowplaying() {
|
||||
std::shared_ptr<MusicQueueElement> MusicQueue::findById(std::string id) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
int index = 0;
|
||||
for (auto iter = queue.begin(); iter != queue.end(); iter++) {
|
||||
if ((*iter).get()->id == id)
|
||||
return *iter;
|
||||
}
|
||||
return std::shared_ptr<MusicQueueElement>();
|
||||
}
|
||||
std::weak_ptr<MusicQueueElement> MusicQueue::nowplaying()
|
||||
{
|
||||
return *currentPlayingPosition;
|
||||
}
|
||||
std::weak_ptr<MusicQueueElement> MusicQueue::next_music() {
|
||||
@@ -38,7 +48,6 @@ std::weak_ptr<MusicQueueElement> MusicQueue::jump_to_index(int idx) {
|
||||
return *iter;
|
||||
}
|
||||
}
|
||||
std::shared_ptr<MusicQueueElement> empty;
|
||||
return empty;
|
||||
return std::shared_ptr<MusicQueueElement>();
|
||||
}
|
||||
}
|
||||
67
src/Settings/SettingsManager.cpp
Normal file
67
src/Settings/SettingsManager.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <Settings/SettingsManager.hpp>
|
||||
|
||||
namespace bumbleBee {
|
||||
|
||||
std::string settingsManager::TOKEN = "";
|
||||
std::string settingsManager::YTDLP_CMD = "./yt-dlp";
|
||||
std::string settingsManager::FFMPEG_CMD = "./ffmpeg/bin/ffmpeg";
|
||||
std::string settingsManager::DBURL = "";
|
||||
std::string settingsManager::DBUSER = "";
|
||||
std::string settingsManager::DBPASSWORD = "";
|
||||
|
||||
void settingsManager::load() {
|
||||
nlohmann::json configdocument;
|
||||
try {
|
||||
std::ifstream configfile("config.json");
|
||||
configfile >> configdocument;
|
||||
|
||||
TOKEN = configdocument["TOKEN"];
|
||||
YTDLP_CMD = configdocument["YTDLP_CMD"];
|
||||
FFMPEG_CMD = configdocument["FFMPEG_CMD"];
|
||||
DBURL = configdocument["DBURL"];
|
||||
DBUSER = configdocument["DBUSER"];
|
||||
DBPASSWORD = configdocument["DBPASSWORD"];
|
||||
}
|
||||
catch (const nlohmann::json::type_error& e) {
|
||||
saveToFile();
|
||||
std::ifstream configfile("config.json");
|
||||
configfile >> configdocument;
|
||||
|
||||
TOKEN = configdocument["TOKEN"];
|
||||
YTDLP_CMD = configdocument["YTDLP_CMD"];
|
||||
FFMPEG_CMD = configdocument["FFMPEG_CMD"];
|
||||
DBURL = configdocument["DBURL"];
|
||||
DBUSER = configdocument["DBUSER"];
|
||||
DBPASSWORD = configdocument["DBPASSWORD"];
|
||||
}
|
||||
catch (const nlohmann::json::parse_error& e) {
|
||||
saveToFile();
|
||||
std::ifstream configfile("config.json");
|
||||
configfile >> configdocument;
|
||||
|
||||
TOKEN = configdocument["TOKEN"];
|
||||
YTDLP_CMD = configdocument["YTDLP_CMD"];
|
||||
FFMPEG_CMD = configdocument["FFMPEG_CMD"];
|
||||
DBURL = configdocument["DBURL"];
|
||||
DBUSER = configdocument["DBUSER"];
|
||||
DBPASSWORD = configdocument["DBPASSWORD"];
|
||||
}
|
||||
}
|
||||
|
||||
void settingsManager::saveToFile() {
|
||||
nlohmann::json configdocument;
|
||||
|
||||
configdocument["TOKEN"] = TOKEN;
|
||||
configdocument["YTDLP_CMD"] = YTDLP_CMD;
|
||||
configdocument["FFMPEG_CMD"] = FFMPEG_CMD;
|
||||
configdocument["DBURL"] = DBURL;
|
||||
configdocument["DBUSER"] = DBUSER;
|
||||
configdocument["DBPASSWORD"] = DBPASSWORD;
|
||||
|
||||
std::ofstream configFile("config.json");
|
||||
if (configFile.is_open()) {
|
||||
configFile << configdocument.dump(4);
|
||||
configFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/main.cpp
11
src/main.cpp
@@ -4,17 +4,14 @@
|
||||
#include <thread>
|
||||
|
||||
int main() {
|
||||
nlohmann::json configdocument;
|
||||
std::ifstream configfile("config.json");
|
||||
configfile >> configdocument;
|
||||
|
||||
bumbleBee::BumbleBee bot(configdocument);
|
||||
bumbleBee::BumbleBee bot;
|
||||
|
||||
bumbleBee::AsyncDownloadManager& manager = bumbleBee::AsyncDownloadManager::getInstance(5, bot.cluster, bot.queue);
|
||||
manager.enqueue("https://music.youtube.com/playlist?list=PL5NSTAfQ-wQBqZYMTqxADemyUW8mxJq2h&si=vFV4jlm70kxGfKNa");
|
||||
manager.enqueue(std::make_pair("https://music.youtube.com/watch?v=4NnqIu_v1QA&si=buZP2UwzQtJLENmb", nullptr));
|
||||
|
||||
std::thread th([](){sleep(11);});
|
||||
std::thread th([](){sleep(60);});
|
||||
th.join();
|
||||
manager.stop();
|
||||
|
||||
std::cout << "\n\n\n\n\nend\n\n\n\n\n\n\n";
|
||||
//bot.start();
|
||||
|
||||
Reference in New Issue
Block a user