mirror of
https://github.com/HappyTanuki/BumbleCee.git
synced 2025-10-25 17:35:58 +00:00
일단은 임시저장, 스트리밍의 실마리를 잡았다
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,5 @@ Temp/
|
||||
config.json
|
||||
Music
|
||||
*.info.json
|
||||
yt-dlp
|
||||
yt-dlp
|
||||
ffmpeg
|
||||
22
.vscode/settings.json
vendored
22
.vscode/settings.json
vendored
@@ -77,6 +77,26 @@
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp",
|
||||
"*.ipp": "cpp"
|
||||
"*.ipp": "cpp",
|
||||
"format": "cpp",
|
||||
"span": "cpp",
|
||||
"__bit_reference": "cpp",
|
||||
"__bits": "cpp",
|
||||
"__config": "cpp",
|
||||
"__debug": "cpp",
|
||||
"__errc": "cpp",
|
||||
"__hash_table": "cpp",
|
||||
"__locale": "cpp",
|
||||
"__mutex_base": "cpp",
|
||||
"__node_handle": "cpp",
|
||||
"__nullptr": "cpp",
|
||||
"__split_buffer": "cpp",
|
||||
"__string": "cpp",
|
||||
"__threading_support": "cpp",
|
||||
"__tree": "cpp",
|
||||
"__tuple": "cpp",
|
||||
"ios": "cpp",
|
||||
"locale": "cpp",
|
||||
"queue": "cpp"
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,8 @@ set(BOT_NAME "BumbleCee")
|
||||
project(${BOT_NAME})
|
||||
aux_source_directory("src" coresrc)
|
||||
aux_source_directory("src/Commands" commands)
|
||||
add_executable(${BOT_NAME} ${coresrc} ${commands})
|
||||
aux_source_directory("src/Settings" settings)
|
||||
add_executable(${BOT_NAME} ${coresrc} ${commands} ${settings})
|
||||
|
||||
string(ASCII 27 Esc)
|
||||
|
||||
|
||||
@@ -5,30 +5,28 @@
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <curl/curl.h>
|
||||
#include <dpp/dpp.h>
|
||||
#include <MusicQueue.hpp>
|
||||
|
||||
#define WORKER_COUNT 5
|
||||
|
||||
namespace bumbleBee {
|
||||
/// @brief 싱글톤 멀티스레딩 다운로드 매니저
|
||||
class AsyncDownloadManager {
|
||||
public:
|
||||
static AsyncDownloadManager& getInstance(int worker_count, std::weak_ptr<dpp::cluster> bot, std::shared_ptr<bumbleBee::MusicQueue> musicQueue) {
|
||||
static AsyncDownloadManager& getInstance(int worker_count, std::weak_ptr<dpp::cluster> weak_cluster, std::shared_ptr<bumbleBee::MusicQueue> musicQueue) {
|
||||
static AsyncDownloadManager dl(worker_count);
|
||||
dl.bot = bot;
|
||||
dl.weak_cluster = weak_cluster;
|
||||
dl.musicQueue = musicQueue;
|
||||
return dl;
|
||||
}
|
||||
void enqueue(std::string query) {
|
||||
void enqueue(std::pair<std::string, dpp::message> query) {
|
||||
std::thread th(&bumbleBee::AsyncDownloadManager::enqueueAsyncDL, this, query);
|
||||
th.detach();
|
||||
}
|
||||
|
||||
~AsyncDownloadManager(){
|
||||
auto cluster = bot.lock();
|
||||
assert(cluster);
|
||||
cluster->log(dpp::ll_info, "AsyncDownloadManager Destructor called.");
|
||||
void stop() {
|
||||
auto cluster = weak_cluster.lock();
|
||||
cluster->log(dpp::ll_info, "AsyncDownloadManager stop/destructor called.");
|
||||
terminate = true;
|
||||
dlQueueCondition.notify_all();
|
||||
|
||||
@@ -37,6 +35,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
~AsyncDownloadManager(){
|
||||
stop();
|
||||
}
|
||||
|
||||
private:
|
||||
AsyncDownloadManager(int worker_count){
|
||||
worker_thread.reserve(worker_count);
|
||||
@@ -46,13 +48,13 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void enqueueAsyncDL(std::string query);
|
||||
void enqueueAsyncDL(std::pair<std::string, dpp::message> query);
|
||||
void downloadWorker();
|
||||
|
||||
std::queue<std::string> downloadQueue;
|
||||
std::queue<std::pair<std::string, dpp::message>> downloadQueue;
|
||||
std::condition_variable dlQueueCondition;
|
||||
std::mutex dlQueueMutex;
|
||||
std::weak_ptr<dpp::cluster> bot;
|
||||
std::weak_ptr<dpp::cluster> weak_cluster;
|
||||
std::shared_ptr<bumbleBee::MusicQueue> musicQueue;
|
||||
std::vector<std::thread> worker_thread;
|
||||
bool terminate;
|
||||
|
||||
@@ -18,9 +18,8 @@ public:
|
||||
/**
|
||||
* @fn BumbleBee(nlohmann::json settings)
|
||||
* @brief 생성자
|
||||
* @param settings 설정 json
|
||||
**/
|
||||
BumbleBee(nlohmann::json settings);
|
||||
BumbleBee();
|
||||
/**
|
||||
* @fn ~BumbleBee()
|
||||
* @brief 파괴자
|
||||
|
||||
@@ -7,15 +7,19 @@
|
||||
namespace bumbleBee::commands {
|
||||
class ICommand {
|
||||
public:
|
||||
/// @brief 기본 생성자
|
||||
/// @param botID 명령어 등록을 위한 봇 아이디
|
||||
/// @param queue 음악이 저장되어 있는 큐
|
||||
/**
|
||||
* @brief 기본 생성자
|
||||
* @param botID 명령어 등록을 위한 봇 아이디
|
||||
* @param queue 음악이 저장되어 있는 큐
|
||||
**/
|
||||
ICommand(dpp::snowflake botID, std::weak_ptr<MusicQueue> queue) {
|
||||
this->botID = botID;
|
||||
this->queue = queue;
|
||||
}
|
||||
/// @brief 명령어 호출 시에 콜백되는 함수
|
||||
/// @param event
|
||||
/**
|
||||
* @brief 명령어 호출 시에 콜백될 메소드
|
||||
* @param event dpp::slashcommand_t
|
||||
**/
|
||||
virtual void operator()(const dpp::slashcommand_t &event){};
|
||||
|
||||
/// @brief 봇 명령어들의 이름과 별명들을 저장하는 벡터
|
||||
@@ -26,11 +30,19 @@ private:
|
||||
dpp::snowflake botID;
|
||||
/// @brief 음악 큐에 대한 약한 포인터
|
||||
std::weak_ptr<MusicQueue> queue;
|
||||
|
||||
/**
|
||||
* @brief 명령어 별명 추가
|
||||
* @param name 명령어 이름
|
||||
* @param description 명령어 설명
|
||||
**/
|
||||
void addCommandAliase(std::string name, std::string description) {
|
||||
nameAndAliases.push_back(dpp::slashcommand(name, description, botID));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn _DECLARE_BUMBLEBEE_COMMAND_one_PARAM_one_ALIAS(name, alias, description, option_name, option_desc)
|
||||
* @brief 명령어 인자가 없는 명령어의 boilerplate 대체 매크로
|
||||
* @param name 명령어 이름 및 클래스명
|
||||
* @param alias 명령어 별명
|
||||
@@ -52,7 +64,6 @@ public: \
|
||||
}
|
||||
|
||||
/**
|
||||
* @fn _DECLARE_BUMBLEBEE_COMMAND_one_PARAM_one_ALIAS(name, alias, description, option_name, option_desc)
|
||||
* @brief 명령어 인자를 하나 갖는 명령어의 boilerplate 대체 매크로
|
||||
* @param name 명령어 이름 및 클래스명
|
||||
* @param alias 명령어 별명
|
||||
|
||||
16
include/MusicPlayManager.hpp
Normal file
16
include/MusicPlayManager.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#ifndef _MUSICPLAYMANAGER_HPP_
|
||||
#define _MUSICPLAYMANAGER_HPP_
|
||||
#include <dpp/dpp.h>
|
||||
|
||||
namespace BumbleBee {
|
||||
class MusicPlayManager {
|
||||
public:
|
||||
MusicPlayManager(std::shared_ptr<dpp::cluster> cluster) {
|
||||
this->cluster = cluster;
|
||||
}
|
||||
private:
|
||||
std::shared_ptr<dpp::cluster> cluster;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -5,14 +5,23 @@
|
||||
#include <functional>
|
||||
#include <condition_variable>
|
||||
#include <list>
|
||||
#include <dpp/dpp.h>
|
||||
|
||||
namespace bumbleBee {
|
||||
|
||||
class MusicQueueElement {
|
||||
public:
|
||||
MusicQueueElement(std::string id, std::string url) : id(id), url(url) {}
|
||||
MusicQueueElement(
|
||||
dpp::message originalResponse,
|
||||
std::string id,
|
||||
std::string url,
|
||||
FILE* stream) :
|
||||
|
||||
originalResponse(originalResponse), id(id), url(url), stream(stream) {}
|
||||
dpp::message originalResponse;
|
||||
std::string id;
|
||||
std::string url;
|
||||
FILE* stream;
|
||||
};
|
||||
|
||||
class MusicQueue {
|
||||
@@ -23,6 +32,7 @@ public:
|
||||
}
|
||||
void enqueue(std::shared_ptr<MusicQueueElement> Element);
|
||||
std::shared_ptr<MusicQueueElement> dequeue();
|
||||
std::shared_ptr<MusicQueueElement> findById(std::string id);
|
||||
std::weak_ptr<MusicQueueElement> nowplaying();
|
||||
std::weak_ptr<MusicQueueElement> next_music();
|
||||
std::weak_ptr<MusicQueueElement> jump_to_index(int idx);
|
||||
|
||||
30
include/Settings/SettingsManager.hpp
Normal file
30
include/Settings/SettingsManager.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#ifndef _SETTINGSMANAGER_HPP_
|
||||
#define _SETTINGSMANAGER_HPP_
|
||||
#include <string>
|
||||
#include <dpp/nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace bumbleBee {
|
||||
class settingsManager {
|
||||
public:
|
||||
/// @brief 봇 토큰
|
||||
static std::string TOKEN;
|
||||
/// @brief yt-dlp 실행 명령어
|
||||
static std::string YTDLP_CMD;
|
||||
/// @brief ffmpeg 실행 명령어
|
||||
static std::string FFMPEG_CMD;
|
||||
/// @brief db접속 url
|
||||
static std::string DBURL;
|
||||
/// @brief db접속 유저
|
||||
static std::string DBUSER;
|
||||
/// @brief db접속 비밀번호
|
||||
static std::string DBPASSWORD;
|
||||
|
||||
|
||||
static void load();
|
||||
|
||||
static void saveToFile();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
40
include/Utils/ConsoleUtils.hpp
Normal file
40
include/Utils/ConsoleUtils.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
#ifndef _CONSOLEUTILS_HPP_
|
||||
#define _CONSOLEUTILS_HPP_
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <queue>
|
||||
|
||||
namespace bumbleBee {
|
||||
class ConsoleUtils {
|
||||
public:
|
||||
/**
|
||||
* @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 \n을 구분자로 토큰화하여 반환합니다
|
||||
* @param cmd 실행할 명령
|
||||
* @return std::queue<std::string> tokens
|
||||
*/
|
||||
static 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
75
include/Utils/VersionsCheckUtils.hpp
Normal file
75
include/Utils/VersionsCheckUtils.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#ifndef _VERSIONCHECKUTILS_HPP_
|
||||
#define _VERSIONCHECKUTILS_HPP_
|
||||
#include <dpp/dpp.h>
|
||||
#include "ConsoleUtils.hpp"
|
||||
#include "../Settings/SettingsManager.hpp"
|
||||
|
||||
namespace bumbleBee {
|
||||
class VersionsCheckUtils {
|
||||
public:
|
||||
static bool isThereCMD(std::shared_ptr<dpp::cluster> cluster, std::string cmd) {
|
||||
if (ConsoleUtils::getResultFromCommand("which " + cmd).size() == 0) {
|
||||
cluster->log(dpp::ll_error, cmd + " is unavaliable. unresolable error please install " + cmd);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
static void validateYTDLPFFMPEGBinary(std::shared_ptr<dpp::cluster> cluster) {
|
||||
cluster->log(dpp::ll_info, "Checking if yt-dlp and ffmpeg is available...");
|
||||
std::queue<std::string> result = ConsoleUtils::getResultFromCommand(settingsManager::FFMPEG_CMD + " -version");
|
||||
std::string front = result.front();
|
||||
if (front[0] != 'f' ||
|
||||
front[1] != 'f' ||
|
||||
front[2] != 'm' ||
|
||||
front[3] != 'p' ||
|
||||
front[4] != 'e' ||
|
||||
front[5] != 'g') {
|
||||
cluster->log(dpp::ll_warning, "ffmpeg is unavailable. downloading ffmpeg...");
|
||||
|
||||
if (!isThereCMD(cluster, "curl")) {
|
||||
exit(1);
|
||||
}
|
||||
if (!isThereCMD(cluster, "tar")) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
system("curl -LO https://github.com/BtbN/FFmpeg-Builds/releases/latest/download/ffmpeg-master-latest-linux64-gpl.tar.xz");
|
||||
system("tar -xf ffmpeg-master-latest-linux64-gpl.tar.xz");
|
||||
system("rm ffmpeg-master-latest-linux64-gpl.tar.xz");
|
||||
system("mv ffmpeg-master-latest-linux64-gpl ffmpeg");
|
||||
}
|
||||
result = ConsoleUtils::getResultFromCommand(settingsManager::YTDLP_CMD + " --version");
|
||||
front = result.front();
|
||||
if ((front[0]-'0' < 0 || front[0]-'0' > 9) ||
|
||||
(front[1]-'0' < 0 || front[1]-'0' > 9) ||
|
||||
(front[2]-'0' < 0 || front[2]-'0' > 9) ||
|
||||
(front[3]-'0' < 0 || front[3]-'0' > 9)) {
|
||||
cluster->log(dpp::ll_warning, "ytdlp is unavailable. downloading ytdlp...");
|
||||
|
||||
if (!isThereCMD(cluster, "curl")) {
|
||||
exit(1);
|
||||
}
|
||||
if (!isThereCMD(cluster, "tar")) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
system("curl -LO https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp");
|
||||
system("chmod +x ./yt-dlp");
|
||||
}
|
||||
}
|
||||
|
||||
static void updateytdlp(std::shared_ptr<dpp::cluster> cluster) {
|
||||
cluster->log(dpp::ll_info, "Checking if yt-dlp update is available...");
|
||||
std::queue<std::string> result = ConsoleUtils::getResultFromCommand("./yt-dlp -U");
|
||||
while(!result.empty()) {
|
||||
std::string front = result.front();
|
||||
result.pop();
|
||||
cluster->log(dpp::ll_info, front);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -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();
|
||||
|
||||
8
streamAndDownload.sh
Executable file
8
streamAndDownload.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
YTDLP_CMD=$1
|
||||
DOWNLOAD_ID=$2
|
||||
FFMPEG_CMD=$3
|
||||
|
||||
$YTDLP_CMD -o - --quiet --ignore-errors -f bestaudio https://youtu.be/$DOWNLOAD_ID | \
|
||||
$FFMPEG_CMD -i - -hide_banner -ar 48000 -ac 2 -c:a libopus -f ogg -
|
||||
Reference in New Issue
Block a user