mirror of
https://github.com/HappyTanuki/BumbleCee.git
synced 2025-10-26 09:55:14 +00:00
완성(준)
This commit is contained in:
@@ -1,23 +1,97 @@
|
||||
#include <Audio/MusicPlayManager.hpp>
|
||||
#include <ogg/ogg.h>
|
||||
#include <oggz/oggz.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace bumbleBee {
|
||||
|
||||
void MusicPlayManager::on_voice_ready(const dpp::voice_ready_t& event) {
|
||||
std::unique_lock<std::mutex> queueEmptyLock(queueEmptyMutex);
|
||||
queuedCondition.wait(queueEmptyLock, [&]{
|
||||
return queue->queue.size() != 0;
|
||||
});
|
||||
play(event.voice_client);
|
||||
}
|
||||
|
||||
auto np = queue->nowplaying();
|
||||
auto music = *np;
|
||||
|
||||
void MusicPlayManager::on_voice_track_marker(const dpp::voice_track_marker_t& event) {
|
||||
play(event.voice_client);
|
||||
}
|
||||
|
||||
void MusicPlayManager::on_voice_client_disconnect(const dpp::voice_client_disconnect_t& event) { // 안 불리는 듯?
|
||||
dpp::snowflake gid = dpp::find_channel(event.voice_client->channel_id)->guild_id;
|
||||
event.voice_client->stop_audio();
|
||||
queueMap[gid]->clear();
|
||||
}
|
||||
|
||||
void MusicPlayManager::play(dpp::discord_voice_client* client) {
|
||||
std::thread t([&](dpp::discord_voice_client* client){
|
||||
dpp::snowflake gid = dpp::find_channel(client->channel_id)->guild_id;
|
||||
|
||||
std::unique_lock<std::mutex> queueEmptyLock(*queueEmptyMutex[gid]);
|
||||
queuedCondition.wait(queueEmptyLock, [&]{ return queueMap[gid]->size() != 0; });
|
||||
|
||||
auto np = queueMap[gid]->next_music();
|
||||
auto music = **np;
|
||||
send_audio_to_voice(music, client);
|
||||
}, client);
|
||||
t.detach();
|
||||
}
|
||||
|
||||
void MusicPlayManager::queue_music(const dpp::snowflake guildId, const std::shared_ptr<MusicQueueElement> music) {
|
||||
queueMap[guildId]->enqueue(music);
|
||||
}
|
||||
|
||||
void MusicPlayManager::clear(const dpp::snowflake guildId) {
|
||||
queueMap[guildId]->clear();
|
||||
}
|
||||
std::shared_ptr<MusicQueueElement> MusicPlayManager::remove(const dpp::snowflake guildId, dpp::discord_voice_client* client, int index) {
|
||||
auto queue = queueMap[guildId];
|
||||
auto foundIterator = queue->findByIndex(index);
|
||||
|
||||
if (queue->currentPlayingPosition == foundIterator) {
|
||||
auto removed = queue->erase(queue->findByIndex(0));
|
||||
if (client == nullptr)
|
||||
return removed;
|
||||
client->pause_audio(true);
|
||||
client->stop_audio();
|
||||
client->pause_audio(false);
|
||||
client->insert_marker("end");
|
||||
return removed;
|
||||
}
|
||||
|
||||
return queue->erase(queue->findByIndex(index));
|
||||
}
|
||||
int MusicPlayManager::size(const dpp::snowflake guildId) {
|
||||
return queueMap[guildId]->size();
|
||||
}
|
||||
void MusicPlayManager::setRepeat(const dpp::snowflake guildId, const bool value) {
|
||||
queueMap[guildId]->repeat = value;
|
||||
}
|
||||
|
||||
bool MusicPlayManager::getRepeat(const dpp::snowflake guildId) {
|
||||
return queueMap[guildId]->repeat;
|
||||
}
|
||||
|
||||
std::list<MusicQueueElement> MusicPlayManager::getQueue(const dpp::snowflake guildId){
|
||||
std::list<std::shared_ptr<MusicQueueElement>> queue = queueMap[guildId]->getQueueCopy();
|
||||
std::list<MusicQueueElement> returnValue;
|
||||
|
||||
for (auto iter = queue.begin(); iter != queue.end(); iter++)
|
||||
returnValue.push_back(**iter);
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
MusicQueueElement MusicPlayManager::getNowPlaying(const dpp::snowflake guildId) {
|
||||
std::shared_ptr<MusicQueueElement> nowplaying = queueMap[guildId]->nowplaying();
|
||||
MusicQueueElement returnValue(*nowplaying);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void MusicPlayManager::send_audio_to_voice(const MusicQueueElement& music, dpp::discord_voice_client* client) {
|
||||
std::string command = "./streamOpus.sh ./yt-dlp ffmpeg https://youtu.be/";
|
||||
command += music.id;
|
||||
|
||||
OGGZ* og = oggz_open_stdio(popen(command.c_str(), "r"), OGGZ_READ);
|
||||
|
||||
client->stop_audio();
|
||||
|
||||
oggz_set_read_callback(
|
||||
og, -1,
|
||||
[](OGGZ *oggz, oggz_packet *packet, long serialno, void *user_data) {
|
||||
@@ -27,10 +101,10 @@ void MusicPlayManager::on_voice_ready(const dpp::voice_ready_t& event) {
|
||||
|
||||
return 0;
|
||||
},
|
||||
(void *)event.voice_client
|
||||
(void *)client
|
||||
);
|
||||
|
||||
while (event.voice_client && !event.voice_client->terminating) {
|
||||
while (client && !client->terminating) {
|
||||
static const constexpr long CHUNK_READ = BUFSIZ * 2;
|
||||
|
||||
const long read_bytes = oggz_read(og, CHUNK_READ);
|
||||
@@ -41,28 +115,11 @@ void MusicPlayManager::on_voice_ready(const dpp::voice_ready_t& event) {
|
||||
}
|
||||
}
|
||||
|
||||
//event.from->creator->log(dpp::ll_info, std::string("Sending ") + music.id + " complete!");
|
||||
client->creator->log(dpp::ll_info, "Sending " + music.id + " complete!");
|
||||
|
||||
oggz_close(og);
|
||||
|
||||
event.voice_client->insert_marker("end");
|
||||
|
||||
queueEmptyLock.unlock();
|
||||
}
|
||||
|
||||
void MusicPlayManager::on_voice_track_marker(const dpp::voice_track_marker_t& event) {
|
||||
queue->next_music();
|
||||
}
|
||||
|
||||
void MusicPlayManager::on_voice_client_disconnect(const dpp::voice_client_disconnect_t& event) {
|
||||
event.voice_client->stop_audio();
|
||||
}
|
||||
|
||||
void MusicPlayManager::queue_music(const std::shared_ptr<MusicQueueElement> music) {
|
||||
queue->enqueue(music);
|
||||
}
|
||||
|
||||
void MusicPlayManager::send_audio_to_voice(const MusicQueueElement& music, const dpp::voice_ready_t &event) {
|
||||
|
||||
client->insert_marker();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
|
||||
namespace bumbleBee{
|
||||
BumbleBee::BumbleBee() {
|
||||
if (!settingsManager::load()) {
|
||||
if (!SettingsManager::load()) {
|
||||
std::cout << "Please configure confing.json" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cluster = std::make_shared<dpp::cluster>(settingsManager::getTOKEN());
|
||||
cluster = std::make_shared<dpp::cluster>(SettingsManager::getTOKEN());
|
||||
|
||||
cluster->on_log([](const dpp::log_t& event) {
|
||||
if (event.severity >= settingsManager::getLOGLEVEL()) {
|
||||
if (event.severity >= SettingsManager::getLOGLEVEL()) {
|
||||
std::cout << "[" << dpp::utility::current_date_time() << "] " << dpp::utility::loglevel(event.severity) << ": " << event.message << "\n";
|
||||
}
|
||||
});
|
||||
@@ -24,22 +24,6 @@ BumbleBee::BumbleBee() {
|
||||
|
||||
VersionsCheckUtils::validateYTDLPFFMPEGBinary(cluster);
|
||||
VersionsCheckUtils::updateytdlp(cluster);
|
||||
|
||||
musicManager = std::make_shared<MusicPlayManager>(cluster);
|
||||
|
||||
commands["d"] = std::make_shared<commands::Delete> (cluster->cluster_id, musicManager);
|
||||
commands["l"] = std::make_shared<commands::Leave> (cluster->cluster_id, musicManager);
|
||||
commands["p"] = std::make_shared<commands::Play> (cluster->cluster_id, musicManager);
|
||||
commands["q"] = std::make_shared<commands::Queue> (cluster->cluster_id, musicManager);
|
||||
commands["r"] = std::make_shared<commands::Repeat> (cluster->cluster_id, musicManager);
|
||||
commands["s"] = std::make_shared<commands::Skip> (cluster->cluster_id, musicManager);
|
||||
|
||||
for (auto command : commands) {
|
||||
for (auto aliase : command.second->aliases) {
|
||||
commands[aliase] = std::shared_ptr<commands::ICommand>(command.second);
|
||||
commands[aliase]->set_name(aliase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BumbleBee::start() { this->cluster->start(dpp::st_wait); }
|
||||
@@ -56,7 +40,16 @@ void BumbleBee::on_slashcommand(const dpp::slashcommand_t &event) {
|
||||
}
|
||||
|
||||
void BumbleBee::on_ready(const dpp::ready_t &event) {
|
||||
cluster->log(dpp::loglevel::ll_info, "Bot ready.");
|
||||
GIDs = event.guilds;
|
||||
musicManager = std::make_shared<MusicPlayManager>(cluster, GIDs);
|
||||
|
||||
commands["d"] = std::make_shared<commands::Delete> (cluster->cluster_id, musicManager);
|
||||
commands["l"] = std::make_shared<commands::Leave> (cluster->cluster_id, musicManager);
|
||||
commands["p"] = std::make_shared<commands::Play> (cluster->cluster_id, musicManager);
|
||||
commands["q"] = std::make_shared<commands::Queue> (cluster->cluster_id, musicManager);
|
||||
commands["r"] = std::make_shared<commands::Repeat> (cluster->cluster_id, musicManager);
|
||||
commands["s"] = std::make_shared<commands::Skip> (cluster->cluster_id, musicManager);
|
||||
commands["shuffle"] = std::make_shared<commands::Shuffle> (cluster->cluster_id, musicManager);
|
||||
|
||||
if (event.guilds.size() == 0) {
|
||||
cluster->log(dpp::loglevel::ll_info, "Bot is not on any server! Please invite this bot to any server.");
|
||||
@@ -64,18 +57,24 @@ void BumbleBee::on_ready(const dpp::ready_t &event) {
|
||||
}
|
||||
|
||||
if (dpp::run_once<struct register_bot_commands>()) {
|
||||
if (settingsManager::getCLCOMMAND()) {
|
||||
if (SettingsManager::getREGISTER_COMMAND()) {
|
||||
cluster->log(dpp::loglevel::ll_info, "Clear Pre-installed commands");
|
||||
cluster->global_bulk_command_delete([](const dpp::confirmation_callback_t &t){
|
||||
std::cout << "cleared Pre-installed commands. Please restart Bot" << std::endl;
|
||||
settingsManager::setCLCOMMAND(false);
|
||||
exit(0);
|
||||
|
||||
cluster->global_bulk_command_create({
|
||||
*commands["d"],
|
||||
*commands["l"],
|
||||
*commands["p"],
|
||||
*commands["q"],
|
||||
*commands["r"],
|
||||
*commands["s"],
|
||||
*commands["shuffle"]
|
||||
}, [&](const dpp::confirmation_callback_t &t){
|
||||
cluster->log(dpp::loglevel::ll_info, "Command created.");
|
||||
SettingsManager::setREGISTER_COMMAND(false);
|
||||
});
|
||||
return;
|
||||
}
|
||||
for (auto command : commands)
|
||||
cluster->global_command_create(*command.second);
|
||||
}
|
||||
cluster->log(dpp::loglevel::ll_info, "Command created.");
|
||||
|
||||
cluster->log(dpp::loglevel::ll_info, "Bot ready.");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,39 @@
|
||||
#include <Commands/BumbleBeeCommand.hpp>
|
||||
#include <format>
|
||||
|
||||
namespace bumbleBee::commands {
|
||||
void Delete::execute(const dpp::slashcommand_t &event) {
|
||||
event.edit_original_response(dpp::message("delete"));
|
||||
if (std::holds_alternative<std::monostate>(event.get_parameter("pos"))) // 여기 들어올 일 있나?
|
||||
{
|
||||
event.edit_original_response(dpp::message("위치를 제공하여 주십시오"));
|
||||
event.reply("");
|
||||
return;
|
||||
}
|
||||
int pos = std::get<std::int64_t>(event.get_parameter("pos"));
|
||||
|
||||
if (pos < 0 || pos > musicManager->size(event.command.guild_id))
|
||||
{
|
||||
|
||||
event.edit_original_response(dpp::message(std::string("이상한 인덱스 위치. Pos :") + std::to_string(pos)));
|
||||
return;
|
||||
}
|
||||
|
||||
dpp::voiceconn* v = event.from->get_voice(event.command.guild_id);
|
||||
|
||||
std::shared_ptr<MusicQueueElement> removed;
|
||||
|
||||
if (!v) // v-> 로 nullptr을 참조하면 안 되므로.
|
||||
removed = musicManager->remove(event.command.guild_id, nullptr, pos);
|
||||
else
|
||||
removed = musicManager->remove(event.command.guild_id, v->voiceclient, pos);
|
||||
|
||||
dpp::message msg("다음 항목을 큐에서 삭제했습니다!:");
|
||||
msg.add_embed(removed->embed);
|
||||
|
||||
event.edit_original_response(msg);
|
||||
}
|
||||
|
||||
void Delete::init() {
|
||||
aliases.push_back("delete");
|
||||
add_option(dpp::command_option(dpp::co_integer, "pos", "지울 위치(위치는 1부터 시작, 현재 재생곡은 0)", true));
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
#include <Commands/BumbleBeeCommand.hpp>
|
||||
|
||||
namespace bumbleBee::commands {
|
||||
void Leave::execute(const dpp::slashcommand_t &event) {
|
||||
event.edit_original_response(dpp::message("leave"));
|
||||
void Leave::execute(const dpp::slashcommand_t &event) { // 왜 read loop ended가 뜨는가...
|
||||
dpp::voiceconn* v = event.from->get_voice(event.command.guild_id);
|
||||
|
||||
if (!v || !v->voiceclient || !v->voiceclient->is_ready()) {
|
||||
return;
|
||||
}
|
||||
musicManager->clear(event.command.guild_id);
|
||||
|
||||
event.from->disconnect_voice(event.command.guild_id);
|
||||
|
||||
event.edit_original_response(dpp::message("음성 채팅방을 떠납니다!"));
|
||||
}
|
||||
|
||||
void Leave::init() {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <Commands/BumbleBeeCommand.hpp>
|
||||
#include <Utils/ConsoleUtils.hpp>
|
||||
#include <Settings/SettingsManager.hpp>
|
||||
#include <dpp/nlohmann/json.hpp>
|
||||
#include <variant>
|
||||
|
||||
namespace bumbleBee::commands {
|
||||
@@ -10,7 +12,7 @@ namespace bumbleBee::commands {
|
||||
event.edit_original_response(dpp::message("GUILD NOT FOUND!! WHAT IS THIS SORCERY??"));
|
||||
return;
|
||||
}
|
||||
if (std::holds_alternative<std::monostate>(event.get_parameter("query")))
|
||||
if (std::holds_alternative<std::monostate>(event.get_parameter("query"))) // 이거 필요한가???
|
||||
{
|
||||
event.reply("노래를 재생하려면 검색어 또는 링크를 입력해 주십시오.");
|
||||
return;
|
||||
@@ -21,11 +23,18 @@ namespace bumbleBee::commands {
|
||||
}
|
||||
std::string query = std::get<std::string>(event.get_parameter("query"));
|
||||
|
||||
std::queue<std::string> ids = ConsoleUtils::getResultFromCommand("./yt-dlp --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors --print id " + query);
|
||||
std::queue<std::string> ids = ConsoleUtils::getResultFromCommand(SettingsManager::getYTDLP_CMD() + " --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors --print id " + query);
|
||||
|
||||
std::queue<MusicQueueElement> musics;
|
||||
std::queue<std::shared_ptr<MusicQueueElement>> musics;
|
||||
|
||||
dpp::message origMsg;
|
||||
int initialQueuedCount = musicManager->size(event.command.guild_id);
|
||||
|
||||
dpp::message msg;
|
||||
|
||||
if (musicManager->size(event.command.guild_id) == 0)
|
||||
msg.content = "다음 곡을 재생합니다:";
|
||||
else
|
||||
msg.content = "큐에 다음 곡을 추가했습니다:";
|
||||
|
||||
if (ids.size() >= 2) {
|
||||
event.from->creator->log(dpp::ll_info, "Playlist detected.");
|
||||
@@ -34,34 +43,122 @@ namespace bumbleBee::commands {
|
||||
ids.pop();
|
||||
continue;
|
||||
}
|
||||
event.from->creator->log(dpp::ll_info, "Enqueuing " + ids.front());
|
||||
|
||||
MusicQueueElement music(
|
||||
ids.front(),
|
||||
query,
|
||||
event.command.usr
|
||||
);
|
||||
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);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
musics.push(music);
|
||||
std::istringstream iss(oss.str());
|
||||
nlohmann::json videoDataJson;
|
||||
iss >> videoDataJson;
|
||||
|
||||
// std::string dump = videoDataJson.dump(4);
|
||||
|
||||
time_t SongLength = int(videoDataJson["duration"]);
|
||||
char SongLengthStr[10];
|
||||
tm t;
|
||||
t.tm_mday = SongLength / 86400;
|
||||
t.tm_hour = (SongLength % 86400)/3600;
|
||||
t.tm_min = (SongLength % 3600)/60;
|
||||
t.tm_sec = SongLength%60;
|
||||
strftime(SongLengthStr, sizeof(SongLengthStr), "%X", &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
|
||||
);
|
||||
|
||||
musics.push(std::make_shared<MusicQueueElement>(ids.front(), query, event.command.usr, embed));
|
||||
ids.pop();
|
||||
}
|
||||
}
|
||||
|
||||
MusicQueueElement music(
|
||||
ids.front(),
|
||||
query,
|
||||
event.command.usr
|
||||
);
|
||||
musics.push(music);
|
||||
if (!ids.empty()) {
|
||||
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);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
while (!musics.empty()) {
|
||||
auto element = musics.front();
|
||||
musicManager->queue_music(std::make_shared<MusicQueueElement>(element));
|
||||
musics.pop();
|
||||
std::istringstream iss(oss.str());
|
||||
nlohmann::json videoDataJson;
|
||||
iss >> videoDataJson;
|
||||
|
||||
time_t SongLength = int(videoDataJson["duration"]);
|
||||
char SongLengthStr[10];
|
||||
tm t;
|
||||
t.tm_mday = SongLength / 86400;
|
||||
t.tm_hour = (SongLength % 86400)/3600;
|
||||
t.tm_min = (SongLength % 3600)/60;
|
||||
t.tm_sec = SongLength%60;
|
||||
strftime(SongLengthStr, sizeof(SongLengthStr), "%X", &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
|
||||
);
|
||||
|
||||
musics.push(std::make_shared<MusicQueueElement>(ids.front(), query, event.command.usr, embed));
|
||||
}
|
||||
|
||||
event.edit_original_response(dpp::message("play"));
|
||||
musicManager->queuedCondition.notify_one();
|
||||
if (musics.size() == 1) {
|
||||
event.from->creator->log(dpp::ll_info, "Enqueuing " + musics.front()->id);
|
||||
musicManager->queue_music(event.command.guild_id, musics.front());
|
||||
msg.add_embed(musics.front()->embed);
|
||||
musics.pop();
|
||||
|
||||
event.edit_original_response(msg);
|
||||
musicManager->queuedCondition.notify_all();
|
||||
}
|
||||
else if (musics.size() > 1) {
|
||||
event.from->creator->log(dpp::ll_info, "Enqueuing " + musics.front()->id);
|
||||
musicManager->queue_music(event.command.guild_id, musics.front());
|
||||
msg.add_embed(musics.front()->embed);
|
||||
musics.pop();
|
||||
|
||||
event.edit_original_response(msg);
|
||||
musicManager->queuedCondition.notify_all();
|
||||
|
||||
while (!musics.empty()) {
|
||||
event.from->creator->log(dpp::ll_info, "Enqueuing " + 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 { // ??
|
||||
event.from->creator->log(dpp::ll_error, "??? not queueed any music");
|
||||
}
|
||||
}
|
||||
|
||||
void Play::init() {
|
||||
|
||||
@@ -2,7 +2,31 @@
|
||||
|
||||
namespace bumbleBee::commands {
|
||||
void Queue::execute(const dpp::slashcommand_t &event) {
|
||||
event.edit_original_response(dpp::message("queue"));
|
||||
auto queue = musicManager->getQueue(event.command.guild_id);
|
||||
auto nowplaying = musicManager->getNowPlaying(event.command.guild_id);
|
||||
|
||||
dpp::message msg;
|
||||
dpp::embed embed;
|
||||
|
||||
if (queue.size() == 0) {
|
||||
embed
|
||||
.set_title("큐가 비었습니다!")
|
||||
.set_timestamp(time(0));
|
||||
msg.add_embed(embed);
|
||||
event.edit_original_response(msg);
|
||||
return;
|
||||
}
|
||||
msg.content = "지금 재생 중:";
|
||||
msg.add_embed(nowplaying.embed);
|
||||
|
||||
for (auto iter = queue.begin(); iter != queue.end(); iter++) {
|
||||
dpp::message followMsg(event.command.channel_id, "");
|
||||
|
||||
followMsg.add_embed(iter->embed);
|
||||
event.from->creator->message_create(followMsg); // 어차피 원래 메시지를 지정해서 수정할 것이기 때문에 먼저 팔로잉 메시지를 작성해도 상관없음.
|
||||
}
|
||||
|
||||
event.edit_original_response(msg);
|
||||
}
|
||||
|
||||
void Queue::init() {
|
||||
|
||||
@@ -2,9 +2,15 @@
|
||||
|
||||
namespace bumbleBee::commands {
|
||||
void Repeat::execute(const dpp::slashcommand_t &event) {
|
||||
event.edit_original_response(dpp::message("repeat"));
|
||||
if (musicManager->getRepeat(event.command.guild_id)) {
|
||||
event.edit_original_response(dpp::message("반복을 껐습니다."));
|
||||
musicManager->setRepeat(event.command.guild_id, false);
|
||||
}
|
||||
else {
|
||||
event.edit_original_response(dpp::message("반복을 켰습니다."));
|
||||
musicManager->setRepeat(event.command.guild_id, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Repeat::init() {
|
||||
}
|
||||
void Repeat::init() {}
|
||||
}
|
||||
@@ -2,7 +2,17 @@
|
||||
|
||||
namespace bumbleBee::commands {
|
||||
void Skip::execute(const dpp::slashcommand_t &event) {
|
||||
event.edit_original_response(dpp::message("skip"));
|
||||
dpp::voiceconn* v = event.from->get_voice(event.command.guild_id);
|
||||
|
||||
if (!v || !v->voiceclient || !v->voiceclient->is_ready()) {
|
||||
return;
|
||||
}
|
||||
v->voiceclient->pause_audio(true);
|
||||
v->voiceclient->stop_audio();
|
||||
v->voiceclient->pause_audio(false);
|
||||
v->voiceclient->insert_marker("end");
|
||||
|
||||
event.edit_original_response(dpp::message("스킵했습니다!"));
|
||||
}
|
||||
|
||||
void Skip::init() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <Queue/MusicQueue.hpp>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace bumbleBee {
|
||||
|
||||
@@ -25,14 +26,23 @@ std::list<std::shared_ptr<MusicQueueElement>>::iterator MusicQueue::findById(std
|
||||
}
|
||||
return queue.end();
|
||||
}
|
||||
std::list<std::shared_ptr<MusicQueueElement>>::iterator MusicQueue::findByIndex(int index) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
if (index < 0)
|
||||
return queue.end();
|
||||
if (index == 0)
|
||||
return currentPlayingPosition;
|
||||
return std::next(queue.begin(), index - 1);
|
||||
}
|
||||
std::shared_ptr<MusicQueueElement> MusicQueue::nowplaying() {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
return *currentPlayingPosition;
|
||||
}
|
||||
std::list<std::shared_ptr<MusicQueueElement>>::iterator MusicQueue::next_music() {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
if (currentPlayingPosition == std::prev(queue.end()) || !repeat)
|
||||
if (currentPlayingPosition == --queue.end() && !repeat)
|
||||
return queue.end();
|
||||
if (currentPlayingPosition == std::prev(queue.end()) || repeat)
|
||||
if (currentPlayingPosition == --queue.end() && repeat)
|
||||
currentPlayingPosition = queue.begin();
|
||||
else
|
||||
++currentPlayingPosition;
|
||||
@@ -49,4 +59,39 @@ std::shared_ptr<MusicQueueElement> MusicQueue::jump_to_index(int idx) {
|
||||
}
|
||||
return std::shared_ptr<MusicQueueElement>();
|
||||
}
|
||||
void MusicQueue::clear() {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
queue.clear();
|
||||
currentPlayingPosition = queue.begin();
|
||||
}
|
||||
std::shared_ptr<MusicQueueElement> MusicQueue::erase(std::list<std::shared_ptr<MusicQueueElement>>::iterator it) {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
if (it == queue.end())
|
||||
return nullptr;
|
||||
|
||||
if (currentPlayingPosition == it) {
|
||||
auto removedValue = *it;
|
||||
auto after = queue.erase(currentPlayingPosition++);
|
||||
if (after == queue.end())
|
||||
currentPlayingPosition = --queue.end();
|
||||
return removedValue;
|
||||
}
|
||||
else {
|
||||
auto removedValue = *it;
|
||||
queue.erase(it);
|
||||
return removedValue;
|
||||
}
|
||||
}
|
||||
std::list<std::shared_ptr<MusicQueueElement>> MusicQueue::getQueueCopy(){
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
std::list<std::shared_ptr<MusicQueueElement>> returnValue;
|
||||
|
||||
std::copy(queue.begin(), queue.end(), std::back_inserter(returnValue));
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
int MusicQueue::size() {
|
||||
std::lock_guard<std::mutex> lock(queueMutex);
|
||||
return queue.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
namespace bumbleBee {
|
||||
|
||||
std::string settingsManager::TOKEN = "";
|
||||
std::string settingsManager::YTDLP_CMD = "./yt-dlp";
|
||||
std::string settingsManager::FFMPEG_CMD = "./ffmpeg/bin/ffmpeg";
|
||||
dpp::loglevel settingsManager::LOGLEVEL = dpp::ll_debug;
|
||||
bool settingsManager::CLCOMMAND = false;
|
||||
std::string SettingsManager::TOKEN = "";
|
||||
std::string SettingsManager::YTDLP_CMD = "./yt-dlp";
|
||||
std::string SettingsManager::FFMPEG_CMD = "./ffmpeg/bin/ffmpeg";
|
||||
dpp::loglevel SettingsManager::LOGLEVEL = dpp::ll_debug;
|
||||
bool SettingsManager::REGISTER_COMMAND = false;
|
||||
|
||||
bool settingsManager::validateToken() {
|
||||
bool SettingsManager::validateToken() {
|
||||
nlohmann::json response;
|
||||
if (ConsoleUtils::getResultFromCommand("which curl").size() == 0) {
|
||||
std::cout << "curl is unavaliable. unresolable error please install curl." << std::endl;
|
||||
@@ -32,7 +32,7 @@ bool settingsManager::validateToken() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool settingsManager::load() {
|
||||
bool SettingsManager::load() {
|
||||
nlohmann::json configdocument;
|
||||
try {
|
||||
std::ifstream configfile("config.json");
|
||||
@@ -66,7 +66,7 @@ bool settingsManager::load() {
|
||||
else // 값이 병신같을때 기본값으로 ll_info 부여
|
||||
LOGLEVEL = dpp::ll_info;
|
||||
|
||||
CLCOMMAND = configdocument["CLEAR_PREVIOUS_COMMAND"];
|
||||
REGISTER_COMMAND = configdocument["CLEAR_PREVIOUS_COMMAND"];
|
||||
}
|
||||
catch (const nlohmann::json::type_error& e) {
|
||||
saveToFile();
|
||||
@@ -79,7 +79,7 @@ bool settingsManager::load() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void settingsManager::saveToFile() {
|
||||
void SettingsManager::saveToFile() {
|
||||
nlohmann::json configdocument;
|
||||
|
||||
configdocument["TOKEN"] = TOKEN;
|
||||
@@ -107,7 +107,7 @@ void settingsManager::saveToFile() {
|
||||
break;
|
||||
}
|
||||
|
||||
configdocument["CLEAR_PREVIOUS_COMMAND"] = CLCOMMAND;
|
||||
configdocument["CLEAR_PREVIOUS_COMMAND"] = REGISTER_COMMAND;
|
||||
|
||||
std::ofstream configFile("config.json");
|
||||
if (configFile.is_open()) {
|
||||
|
||||
@@ -38,7 +38,7 @@ void AsyncDownloadManager::downloadWorker() {
|
||||
cluster->log(dpp::ll_info, "AsyncDownloadManager: " + query + " accepted.");
|
||||
|
||||
std::queue<std::string> ids =
|
||||
ConsoleUtils::getResultFromCommand(settingsManager::getYTDLP_CMD() +
|
||||
ConsoleUtils::getResultFromCommand(SettingsManager::getYTDLP_CMD() +
|
||||
" --default-search ytsearch --flat-playlist --skip-download --quiet --ignore-errors --print id " + query);
|
||||
|
||||
if (ids.size() >= 2) {
|
||||
@@ -56,7 +56,7 @@ void AsyncDownloadManager::downloadWorker() {
|
||||
}
|
||||
|
||||
std::queue<std::string> urls =
|
||||
ConsoleUtils::getResultFromCommand(settingsManager::getYTDLP_CMD() +
|
||||
ConsoleUtils::getResultFromCommand(SettingsManager::getYTDLP_CMD() +
|
||||
" -f ba* --print urls https://youtu.be/" + ids.front());
|
||||
|
||||
cluster->log(dpp::ll_debug, "url: " + urls.front());
|
||||
@@ -75,7 +75,7 @@ void AsyncDownloadManager::downloadWorker() {
|
||||
|
||||
cluster->log(dpp::ll_info, "Thread id: " + tid.str() + ": " + downloadID + " accepted.");
|
||||
|
||||
std::string command = std::string("./streamOpus.sh " + settingsManager::getYTDLP_CMD() + " " + downloadID + " " + settingsManager::getFFMPEG_CMD());
|
||||
std::string command = std::string("./streamOpus.sh " + SettingsManager::getYTDLP_CMD() + " " + downloadID + " " + SettingsManager::getFFMPEG_CMD());
|
||||
stream = popen(command.c_str(), "r");
|
||||
|
||||
cluster->log(dpp::ll_info, "Thread id: " + tid.str() + " Opened stream: " + downloadID);
|
||||
|
||||
Reference in New Issue
Block a user