와 이제 진짜 진짜 버그 다 고친 듯?

This commit is contained in:
2025-02-02 23:55:47 +09:00
parent 1af829c711
commit 14db2a31e8
15 changed files with 219 additions and 110 deletions

View File

@@ -1,4 +1,10 @@
#!/bin/bash
if [ "$(id -u)" -ne 0 ]; then
exec sudo "$0" "$@"
fi
cd build
cmake .. && make
cd ..
cat password | docker login -u happytanuki12 --password-stdin
docker build --tag happytanuki12/bumblebee:latest .
docker push happytanuki12/bumblebee:latest

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _MUSICPLAYMANAGER_HPP_
#define _MUSICPLAYMANAGER_HPP_
#include <dpp/dpp.h>
#include <Queue/MusicQueue.hpp>
#include <condition_variable>
@@ -50,7 +48,7 @@ public:
void setRepeat(const dpp::snowflake guildId, const bool value);
bool getRepeat(const dpp::snowflake guildId);
std::list<MusicQueueElement> getQueue(const dpp::snowflake guildId);
std::pair<std::shared_ptr<std::list<std::shared_ptr<MusicQueueElement>>>, std::list<std::shared_ptr<MusicQueueElement>>::iterator> getQueue(const dpp::snowflake guildId);
MusicQueueElement getNowPlaying(const dpp::snowflake guildId);
std::condition_variable queuedCondition;
@@ -63,7 +61,6 @@ private:
std::unordered_map<dpp::snowflake, std::shared_ptr<std::mutex>> queueEmptyMutex;
void send_audio_to_voice(const MusicQueueElement& music, dpp::discord_voice_client* client);
void send_audio_to_voice(std::shared_ptr<bumbleBee::MusicQueueElement> music, dpp::discord_voice_client* client);
};
}
#endif
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _BUMBLEBEECOMMAND_HPP_
#define _BUMBLEBEECOMMAND_HPP_
#include <dpp/dpp.h>
#include <Audio/MusicPlayManager.hpp>
#include <functional>
@@ -65,6 +63,4 @@ _DECLARE_BUMBLEBEE_COMMAND(Play, p, "노래 재생")
_DECLARE_BUMBLEBEE_COMMAND(Queue, q, "노래 예약 큐를 확인합니다")
_DECLARE_BUMBLEBEE_COMMAND(Repeat, r, "반복을 켜거나 끕니다")
_DECLARE_BUMBLEBEE_COMMAND(Skip, s, "현재 재생중인 곡을 스킵합니다")
_DECLARE_BUMBLEBEE_COMMAND(Shuffle, shuffle, "큐를 섞습니다")
#endif
_DECLARE_BUMBLEBEE_COMMAND(Shuffle, shuffle, "큐를 섞습니다")

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _MUSICQUEUE_HPP_
#define _MUSICQUEUE_HPP_
#include <memory>
#include <functional>
#include <condition_variable>
@@ -17,17 +15,18 @@ public:
currentPlayingPosition = queue.begin();
repeat = true;
}
void enqueue(std::shared_ptr<MusicQueueElement> Element);
std::shared_ptr<MusicQueueElement> dequeue();
std::list<std::shared_ptr<MusicQueueElement>>::iterator findById(std::string id);
std::list<std::shared_ptr<MusicQueueElement>>::iterator findByIndex(int index);
std::shared_ptr<MusicQueueElement> nowplaying();
std::list<std::shared_ptr<MusicQueueElement>>::iterator next_music();
std::shared_ptr<MusicQueueElement> jump_to_index(int idx);
void clear();
std::shared_ptr<MusicQueueElement> erase(std::list<std::shared_ptr<MusicQueueElement>>::iterator it);
std::list<std::shared_ptr<MusicQueueElement>> getQueueCopy();
int size();
void enqueue(std::shared_ptr<MusicQueueElement> Element);
std::shared_ptr<MusicQueueElement> dequeue();
std::list<std::shared_ptr<MusicQueueElement>>::iterator findById(std::string id);
std::list<std::shared_ptr<MusicQueueElement>>::iterator findByIndex(int index);
std::shared_ptr<MusicQueueElement> nowplaying();
std::list<std::shared_ptr<MusicQueueElement>>::iterator next_music();
std::shared_ptr<MusicQueueElement> jump_to_index(int idx);
void clear();
std::shared_ptr<MusicQueueElement> erase(std::list<std::shared_ptr<MusicQueueElement>>::iterator it);
std::pair<std::shared_ptr<std::list<std::shared_ptr<MusicQueueElement>>>, std::list<std::shared_ptr<MusicQueueElement>>::iterator> getQueueCopy();
int size();
std::list<std::shared_ptr<MusicQueueElement>>::iterator end();
bool repeat;
@@ -36,6 +35,4 @@ private:
std::list<std::shared_ptr<MusicQueueElement>> queue;
std::mutex queueMutex;
};
}
#endif
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _MUSICQUEUEELEMENT_HPP_
#define _MUSICQUEUEELEMENT_HPP_
#include <dpp/dpp.h>
namespace bumbleBee {
@@ -19,5 +17,4 @@ public:
const dpp::user issuingUser;
const dpp::embed embed;
};
}
#endif
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _SETTINGSMANAGER_HPP_
#define _SETTINGSMANAGER_HPP_
#include <dpp/dpp.h>
#define _DECLARE_DEFAULT_ACCESSER_STATIC_VARIABLE(type, name, Name)\
@@ -33,5 +31,4 @@ public:
/// @return 유효한 토큰이면 true, 아니면 false를 반환합니다.
static bool validateToken();
};
}
#endif
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _ASYNCDOWNLOADMANAGER_HPP_
#define _ASYNCDOWNLOADMANAGER_HPP_
#include <queue>
#include <string>
#include <thread>
@@ -55,6 +53,4 @@ private:
std::vector<std::thread> worker_thread;
bool terminate;
};
}
#endif
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _CONSOLEUTILS_HPP_
#define _CONSOLEUTILS_HPP_
#include <iostream>
#include <sstream>
#include <queue>
@@ -35,6 +33,4 @@ public:
return tokens;
}
};
}
#endif
}

View File

@@ -0,0 +1,84 @@
#pragma once
#include <dpp/dpp.h>
#include <Queue/MusicQueueElement.hpp>
#include <cmath>
namespace bumbleBee {
class QueuedMusicListEmbedProvider {
public:
static std::queue<dpp::embed> makeEmbed(std::list<std::shared_ptr<MusicQueueElement>> queue, std::list<std::shared_ptr<MusicQueueElement>>::iterator np, bool repeat) {
std::queue<dpp::embed> returnValue;
std::list<std::shared_ptr<MusicQueueElement>>::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++) {
dpp::embed embed = makeEmbedPart(queue, np, repeat, it);
returnValue.push(embed);
}
return returnValue;
}
static int distance(const std::list<std::shared_ptr<MusicQueueElement>>::iterator a, const std::list<std::shared_ptr<MusicQueueElement>>::iterator b) {
int i = 0;
std::list<std::shared_ptr<MusicQueueElement>>::iterator mutatea = a;
while (mutatea++ == b)
i++;
return i;
}
private:
static dpp::embed makeEmbedPart(
std::list<std::shared_ptr<MusicQueueElement>> queue,
std::list<std::shared_ptr<MusicQueueElement>>::iterator np,
bool repeat,
std::list<std::shared_ptr<MusicQueueElement>>::iterator startIter) {
dpp::embed embed = dpp::embed()
.set_color(dpp::colors::sti_blue);
if (queue.begin() == queue.end()) {
embed
.set_title("큐가 비었습니다!")
.set_timestamp(time(0));
if (repeat)
embed.add_field(":repeat:","");
return embed;
}
int startIndex = distance(queue.begin(), startIter) + 1;
int index = startIndex;
for (; (index < startIndex + 5) && startIter != queue.end() && index < queue.size()+1; startIter++, index++) { //iter로 순회하면 왠지 모르게 이상한 값을 읽을 때가 있음 이유는 나도 몰?루
if (*startIter == *np)
embed.add_field (
"np",
"",
true
);
else
embed.add_field (
std::to_string(index),
"",
true
);
embed.add_field (
(*startIter)->embed.title,
(*startIter)->embed.description,
true
)
.add_field("","");
}
if (startIter == queue.end() || index >= queue.size()+1) {
embed.set_timestamp(time(0));
if (repeat)
embed.add_field(":repeat:","");
}
return embed;
}
};
}

View File

@@ -1,6 +1,4 @@
#pragma once
#ifndef _VERSIONCHECKUTILS_HPP_
#define _VERSIONCHECKUTILS_HPP_
#include <dpp/dpp.h>
#include "ConsoleUtils.hpp"
#include "../Settings/SettingsManager.hpp"
@@ -73,5 +71,4 @@ public:
}
}
};
}
#endif
}

View File

@@ -11,6 +11,8 @@ void MusicPlayManager::on_voice_ready(const dpp::voice_ready_t& event) {
}
void MusicPlayManager::on_voice_track_marker(const dpp::voice_track_marker_t& event) {
dpp::snowflake gid = dpp::find_channel(event.voice_client->channel_id)->guild_id;
queueMap[gid]->next_music();
play(event.voice_client);
}
@@ -23,13 +25,14 @@ void MusicPlayManager::on_voice_client_disconnect(const dpp::voice_client_discon
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);
queuedCondition.wait(queueEmptyLock, [&]{
return queueMap[gid]->size() != 0 && queueMap[gid]->currentPlayingPosition != queueMap[gid]->end();
});
auto next = queueMap[gid]->currentPlayingPosition;
send_audio_to_voice(*next, client);
}, client);
t.detach();
}
@@ -69,13 +72,9 @@ 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);
std::pair<std::shared_ptr<std::list<std::shared_ptr<MusicQueueElement>>>, std::list<std::shared_ptr<MusicQueueElement>>::iterator>
MusicPlayManager::getQueue(const dpp::snowflake guildId){
auto returnValue = queueMap[guildId]->getQueueCopy();
return returnValue;
}
@@ -87,12 +86,12 @@ MusicQueueElement MusicPlayManager::getNowPlaying(const dpp::snowflake guildId)
return returnValue;
}
void MusicPlayManager::send_audio_to_voice(const MusicQueueElement& music, dpp::discord_voice_client* client) {
void MusicPlayManager::send_audio_to_voice(std::shared_ptr<bumbleBee::MusicQueueElement> music, dpp::discord_voice_client* client) {
std::string command = "./streamOpus.sh ";
command += SettingsManager::getYTDLP_CMD() + " ";
command += SettingsManager::getFFMPEG_CMD() + " ";
command += "https://youtu.be/";
command += music.id;
command += music->id;
OGGZ* og = oggz_open_stdio(popen(command.c_str(), "r"), OGGZ_READ);
@@ -110,7 +109,7 @@ void MusicPlayManager::send_audio_to_voice(const MusicQueueElement& music, dpp::
(void *)client
);
while (client && !client->terminating) {
while (client && !client->terminating && music != nullptr) {
static const constexpr long CHUNK_READ = BUFSIZ * 2;
const long read_bytes = oggz_read(og, CHUNK_READ);
@@ -121,7 +120,8 @@ void MusicPlayManager::send_audio_to_voice(const MusicQueueElement& music, dpp::
}
}
client->creator->log(dpp::ll_info, "Sending " + music.embed.title + " - " + music.id + " complete!");
if (music != nullptr)
client->creator->log(dpp::ll_info, "Sending " + music->embed.title + " - " + music->id + " complete!");
oggz_close(og);

View File

@@ -22,6 +22,7 @@ namespace bumbleBee::commands {
return;
}
std::string query = std::get<std::string>(event.get_parameter("query"));
query = "\"" + query + "\"";
std::queue<std::string> ids =
ConsoleUtils::getResultFromCommand(
@@ -55,20 +56,25 @@ namespace bumbleBee::commands {
while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) {
oss.write(buffer, bytesRead);
}
fclose(file);
pclose(file);
std::istringstream iss(oss.str());
nlohmann::json videoDataJson;
iss >> videoDataJson;
time_t SongLength = int(videoDataJson["duration"]);
char SongLengthStr[10];
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;
strftime(SongLengthStr, sizeof(SongLengthStr), "%X", &t);
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)
@@ -86,23 +92,40 @@ namespace bumbleBee::commands {
ids.pop();
}
event.from->creator->log(dpp::ll_info, "Enqueuing " + musics.front()->embed.title + " - " + 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()) {
if (!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());
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()->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 = "검색 결과가 없습니다";
event.edit_original_response(msg);
}
if (musicManager->getNowPlaying(event.command.guild_id).id == "") {
dpp::voiceconn* v = event.from->get_voice(event.command.guild_id);
if (!v || !v->voiceclient || !v->voiceclient->is_ready()) {
event.edit_original_response(dpp::message("현재 음성 채팅방에 있는 상태가 아닙니다!"));
return;
}
musicManager->play(v->voiceclient);
}
}

View File

@@ -1,32 +1,45 @@
#include <Commands/BumbleBeeCommand.hpp>
#include <Utils/QueuedMusicListEmbedProvider.hpp>
namespace bumbleBee::commands {
void Queue::execute(const dpp::slashcommand_t &event) {
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);
auto queued = QueuedMusicListEmbedProvider::makeEmbed(*queue.first, queue.second, musicManager->getRepeat(event.command.guild_id));
// if (queue.first.size() == 0) {
// msg.add_embed(queued.front());
// event.edit_original_response(msg);
// return;
// }
// &&
// queue.first.size() != 0 &&
// *queue.second != nullptr &&
// (*queue.second)->id != ""
if (queue.first->size() != 0 && queue.first->end() != queue.second && (*queue.second)->id != "") {
msg.content = "지금 재생 중:";
msg.add_embed((*queue.second)->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); // 어차피 원래 메시지를 지정해서 수정할 것이기 때문에 먼저 팔로잉 메시지를 작성해도 상관없음.
else {
msg.content = "재생 중인 노래가 없습니다";
event.edit_original_response(msg);
}
event.edit_original_response(msg);
std::thread t([](std::queue<dpp::embed> queued, dpp::snowflake channel_id, dpp::cluster* cluster) {
for (; !queued.empty(); queued.pop()) {
dpp::message followMsg(channel_id, "현재 큐에 있는 항목:");
followMsg.add_embed(queued.front());
cluster->message_create(followMsg);
}
}, queued, event.command.channel_id, event.from->creator);
t.detach();
}
void Queue::init() {

View File

@@ -5,13 +5,10 @@ namespace bumbleBee::commands {
dpp::voiceconn* v = event.from->get_voice(event.command.guild_id);
if (!v || !v->voiceclient || !v->voiceclient->is_ready()) {
event.edit_original_response(dpp::message("스킵하려면 음악을 재생중이어야 합니다!"));
return;
}
// v->voiceclient->pause_audio(true);
// v->voiceclient->stop_audio();
// v->voiceclient->pause_audio(false);
// v->voiceclient->insert_marker("end");
v->voiceclient->skip_to_next_marker();
v->voiceclient->stop_audio();
v->voiceclient->insert_marker();
event.edit_original_response(dpp::message("스킵했습니다!"));

View File

@@ -1,6 +1,7 @@
#include <Queue/MusicQueue.hpp>
#include <iostream>
#include <algorithm>
#include <Utils/QueuedMusicListEmbedProvider.hpp>
namespace bumbleBee {
@@ -43,10 +44,10 @@ std::shared_ptr<MusicQueueElement> MusicQueue::nowplaying() {
}
std::list<std::shared_ptr<MusicQueueElement>>::iterator MusicQueue::next_music() {
std::lock_guard<std::mutex> lock(queueMutex);
if (currentPlayingPosition == --queue.end() && !repeat)
return queue.end();
if (currentPlayingPosition == --queue.end() && repeat)
currentPlayingPosition = queue.begin();
else if (currentPlayingPosition == --queue.end() && !repeat)
currentPlayingPosition = queue.end();
else
++currentPlayingPosition;
return currentPlayingPosition;
@@ -85,16 +86,28 @@ std::shared_ptr<MusicQueueElement> MusicQueue::erase(std::list<std::shared_ptr<M
return removedValue;
}
}
std::list<std::shared_ptr<MusicQueueElement>> MusicQueue::getQueueCopy(){
std::pair<std::shared_ptr<std::list<std::shared_ptr<MusicQueueElement>>>, std::list<std::shared_ptr<MusicQueueElement>>::iterator>
MusicQueue::getQueueCopy() {
std::lock_guard<std::mutex> lock(queueMutex);
std::list<std::shared_ptr<MusicQueueElement>> returnValue;
std::shared_ptr<std::list<std::shared_ptr<MusicQueueElement>>> returnValue = std::make_shared<std::list<std::shared_ptr<MusicQueueElement>>>();
std::copy(queue.begin(), queue.end(), std::back_inserter(returnValue));
for (auto i = queue.begin(); i != queue.end(); i++)
returnValue->push_back(*i);
return returnValue;
if (returnValue->begin() == returnValue->end() || currentPlayingPosition == queue.end())
return std::make_pair(returnValue, returnValue->end());
std::list<std::shared_ptr<MusicQueueElement>>::iterator iter = returnValue->begin();
std::advance(iter, std::distance(queue.begin(), currentPlayingPosition));
return std::make_pair(returnValue, iter);
}
int MusicQueue::size() {
std::lock_guard<std::mutex> lock(queueMutex);
return queue.size();
}
std::list<std::shared_ptr<MusicQueueElement>>::iterator MusicQueue::end() {
std::lock_guard<std::mutex> lock(queueMutex);
return queue.end();
}
}