3 Commits

21 changed files with 301 additions and 262 deletions

8
.clang-format Normal file
View File

@@ -0,0 +1,8 @@
# Google C/C++ Code Style Settings
Language: Cpp
BasedOnStyle: Google
Standard: c++20
IndentWidth: 2
UseTab: Never
ColumnLimit: 80

10
.idea/.gitignore generated vendored
View File

@@ -1,10 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Environment-dependent path to Maven home directory
/mavenHomeManager.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

9
.idea/BumbleCee.iml generated
View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="openjdk-23" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/BumbleCee.iml" filepath="$PROJECT_DIR$/.idea/BumbleCee.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,19 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/include"
],
"defines": [
"DDPP_CORO=on"
],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

13
.vscode/launch.json vendored
View File

@@ -1,13 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Debug",
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/BumbleCee",
"program": "${workspaceFolder}/build/Debug Clang 18.1.3 x86_64-pc-linux-gnu/tests/${fileBasenameNoExtension}",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
@@ -22,8 +26,7 @@
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
],
"preLaunchTask": "${defaultBuildTask}"
]
}
]
}

48
.vscode/settings.json vendored
View File

@@ -1,9 +1,16 @@
{
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
"editor.rulers": [
{
"column": 80
}
],
"cmake.generator": "Ninja",
"files.associations": {
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"csetjmp": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
@@ -12,37 +19,53 @@
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"strstream": "cpp",
"barrier": "cpp",
"bit": "cpp",
"bitset": "cpp",
"cfenv": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"cinttypes": "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",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"expected": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"source_location": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"rope": "cpp",
"slist": "cpp",
"format": "cpp",
"fstream": "cpp",
"future": "cpp",
@@ -51,20 +74,39 @@
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"latch": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"scoped_allocator": "cpp",
"semaphore": "cpp",
"shared_mutex": "cpp",
"span": "cpp",
"spanstream": "cpp",
"sstream": "cpp",
"stacktrace": "cpp",
"stdexcept": "cpp",
"stdfloat": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"syncstream": "cpp",
"thread": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"__config": "cpp",
"rope": "cpp"
"__locale": "cpp",
"ios": "cpp",
"locale": "cpp",
"print": "cpp"
},
"files.exclude": {
"**/*.rpyc": true,
"**/*.rpa": true,
"**/*.rpymc": true,
"**/cache/": true
}
}

37
.vscode/tasks.json vendored
View File

@@ -1,37 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "ninja",
"command": "ninja",
"args": [],
"options": {
"cwd": "${workspaceFolder}/build/"
},
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": ["cmake"]
},
{
"type": "shell",
"label": "cmake",
"command": "cmake",
"args": [
"..",
"-G",
"Ninja"
],
"options": {
"cwd": "${workspaceFolder}/build/"
},
"group": {
"kind": "build",
"isDefault": false
}
},
]
}

View File

@@ -2,23 +2,28 @@ cmake_minimum_required (VERSION 3.16)
set(BOT_NAME "BumbleCee")
project(${BOT_NAME} LANGUAGES CXX)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(BOOST_EXCLUDE_LIBRARIES nowide)
set(BUILD_TESTING ON)
set(DPP_BUILD_TEST OFF)
enable_testing()
if(WIN32)
set(OPENSSL_ROOT_DIR "C:/Program Files/OpenSSL-Win64")
set(OPENSSL_INCLUDE_DIR "${OPENSSL_ROOT_DIR}/include")
if(CMAKE_BUILD_TYPE STREQUAL Debug)
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MDd/libcrypto.lib")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MDd/libssl.lib")
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MTd/libcrypto.lib")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MTd/libssl.lib")
else()
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MD/libcrypto.lib")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MD/libssl.lib")
set(OPENSSL_CRYPTO_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MT/libcrypto.lib")
set(OPENSSL_SSL_LIBRARY "${OPENSSL_ROOT_DIR}/lib/VC/x64/MT/libssl.lib")
endif()
endif()
@@ -26,14 +31,15 @@ find_package(OpenSSL REQUIRED)
include(FetchContent)
set(BUILD_SHARED_LIBS_OLD ${BUILD_SHARED_LIBS})
FetchContent_Declare(
Boost
URL "https://github.com/boostorg/boost/releases/download/boost-1.89.0/boost-1.89.0-cmake.7z"
DOWNLOAD_EXTRACT_TIMESTAMP ON
CMAKE_ARGS
-DBOOST_USE_STATIC_LIBS=OFF # DLL 사용
-DBOOST_USE_STATIC_RUNTIME=OFF # /MD, /MDd 사용
EXCLUDE_FROM_ALL
)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Do not build SHARED libraries" FORCE)
message(STATUS "Fetching and making available Boost...")
FetchContent_MakeAvailable(Boost)
@@ -42,23 +48,23 @@ FetchContent_Declare(
GIT_REPOSITORY "https://github.com/brainboxdotcc/DPP.git"
GIT_TAG "v10.1.3"
GIT_SHALLOW ON
CMAKE_ARGS -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} -DCMAKE_CXX_STANDARD_REQUIRED=ON
)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build SHARED libraries" FORCE)
message(STATUS "Fetching and making available dpp...")
FetchContent_MakeAvailable(dpp)
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD} CACHE BOOL "Type of libraries to build" FORCE)
# -------------------------------------------------------------
# 플랫폼별 FFmpeg 바이너리 다운로드 및 링크
# -------------------------------------------------------------
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set(FFMPEG_URL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-lgpl-shared.zip")
set(FFMPEG_SHA256HASH "SHA256=c95a9d4e030f694f33c85a7611204383a0bca906514a08d83d3858496b122f76")
set(FFMPEG_ARCHIVE_NAME "ffmpeg-windows")
set(FFMPEG_LIB_DIR "lib")
set(FFMPEG_INCLUDE_DIR "include")
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
set(FFMPEG_URL "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-lgpl-shared.tar.xz")
set(FFMPEG_SHA256HASH "SHA256=ebf6b197ffe52d798504895b4c2b84114ad5d2b406ac76e18374b44d1184ade3")
set(FFMPEG_ARCHIVE_NAME "ffmpeg-linux")
set(FFMPEG_LIB_DIR "lib")
set(FFMPEG_INCLUDE_DIR "include")
@@ -69,7 +75,6 @@ endif()
FetchContent_Declare(
ffmpeg
URL ${FFMPEG_URL}
URL_HASH ${FFMPEG_SHA256HASH}
DOWNLOAD_EXTRACT_TIMESTAMP ON
SOURCE_DIR ${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}
)
@@ -87,41 +92,42 @@ find_library(AVUTIL_LIBRARY NAMES avutil PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT
message(STATUS "AVUTIL_LIBRARY = ${AVUTIL_LIBRARY}")
find_library(SWSCALE_LIBRARY NAMES swscale PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT_PATH)
message(STATUS "SWSCALE_LIBRARY = ${SWSCALE_LIBRARY}")
find_library(SWRESAMPLE_LIBRARY NAMES swresample PATHS ${FFMPEG_LIBRARY_PATH} NO_DEFAULT_PATH)
message(STATUS "SWRESAMPLE_LIBRARY = ${SWRESAMPLE_LIBRARY}")
if(NOT AVCODEC_LIBRARY OR NOT AVFORMAT_LIBRARY OR NOT AVUTIL_LIBRARY)
if(NOT AVCODEC_LIBRARY OR NOT AVFORMAT_LIBRARY OR NOT AVUTIL_LIBRARY OR NOT SWRESAMPLE_LIBRARY)
message(FATAL_ERROR "FFmpeg 라이브러리를 찾을 수 없습니다. 다운로드 경로를 확인해주세요.")
endif()
file(GLOB_RECURSE CORES "src/*.cpp" "src/*.cxx" "src/*.cc")
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.cxx" "src/*.cc")
set(ALL_SOURCE_FILES
${CORES}
${AUDIO_SOURCES}
${COMMANDS_SOURCES}
${QUEUE_SOURCES}
${SETTINGS_SOURCES}
${UTILS_SOURCES}
)
add_library(${BOT_NAME}_lib ${SOURCES})
add_executable(${BOT_NAME} ${ALL_SOURCE_FILES})
target_include_directories(${BOT_NAME}_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_link_libraries(${BOT_NAME} PRIVATE dpp)
target_link_libraries(${BOT_NAME} PRIVATE Boost::filesystem)
target_link_libraries(${BOT_NAME} PRIVATE Boost::process)
target_link_libraries(${BOT_NAME} PRIVATE Boost::log)
target_link_libraries(${BOT_NAME} PRIVATE Boost::beast)
target_link_libraries(${BOT_NAME} PRIVATE OpenSSL::Crypto)
target_link_libraries(${BOT_NAME} PRIVATE OpenSSL::SSL)
target_link_libraries(${BOT_NAME} PRIVATE ${AVUTIL_LIBRARY})
target_link_libraries(${BOT_NAME} PRIVATE ${AVCODEC_LIBRARY})
target_link_libraries(${BOT_NAME} PRIVATE ${AVFORMAT_LIBRARY})
target_link_libraries(${BOT_NAME} PRIVATE ${SWSCALE_LIBRARY})
target_include_directories(${BOT_NAME}_lib PUBLIC ${OpenSSL_INCLUDE_DIRS})
target_include_directories(${BOT_NAME}_lib PUBLIC ${FFMPEG_INCLUDE_PATH})
target_precompile_headers(${BOT_NAME}_lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/precomp.h")
target_link_libraries(${BOT_NAME}_lib PUBLIC dpp)
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::filesystem)
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::process)
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::log)
target_link_libraries(${BOT_NAME}_lib PUBLIC Boost::beast)
target_link_libraries(${BOT_NAME}_lib PUBLIC OpenSSL::Crypto)
target_link_libraries(${BOT_NAME}_lib PUBLIC OpenSSL::SSL)
target_link_libraries(${BOT_NAME}_lib PUBLIC ${AVUTIL_LIBRARY})
target_link_libraries(${BOT_NAME}_lib PUBLIC ${AVCODEC_LIBRARY})
target_link_libraries(${BOT_NAME}_lib PUBLIC ${AVFORMAT_LIBRARY})
target_link_libraries(${BOT_NAME}_lib PUBLIC ${SWSCALE_LIBRARY})
target_link_libraries(${BOT_NAME}_lib PUBLIC ${SWRESAMPLE_LIBRARY})
if(WIN32)
target_link_libraries(${BOT_NAME} PRIVATE ws2_32)
target_link_libraries(${BOT_NAME}_lib PUBLIC ws2_32)
endif()
if(UNIX AND NOT APPLE AND CMAKE_BUILD_TYPE STREQUAL "Release")
set_target_properties(${PROJECT_NAME} PROPERTIES
if(UNIX AND NOT APPLE)
set_target_properties(${BOT_NAME}_lib PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "$ORIGIN"
SKIP_BUILD_RPATH FALSE
@@ -129,30 +135,29 @@ if(UNIX AND NOT APPLE AND CMAKE_BUILD_TYPE STREQUAL "Release")
)
endif()
target_include_directories(${BOT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
add_executable(${BOT_NAME} ${SOURCES})
target_include_directories(${BOT_NAME} PRIVATE ${OpenSSL_INCLUDE_DIRS})
target_include_directories(${BOT_NAME} PRIVATE ${FFMPEG_INCLUDE_PATH})
target_link_libraries(${BOT_NAME} PUBLIC ${BOT_NAME}_lib)
target_precompile_headers(${BOT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include/precomp.h")
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"$<TARGET_FILE_DIR:Boost::filesystem>"
"$<TARGET_FILE_DIR:${BOT_NAME}>"
COMMENT "Copying Boost.Filesystem DLL/so files to output directory"
file(GLOB FFMPEG_SHARED
"${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}/bin/*.dll" # Windows
"${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}/lib/*.so*" # Linux
)
foreach(ffmpeg_shared ${FFMPEG_SHARED})
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"$<TARGET_FILE_DIR:Boost::process>"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${ffmpeg_shared}"
"$<TARGET_FILE_DIR:${BOT_NAME}>"
COMMENT "Copying Boost.Process DLL/so files to output directory"
COMMENT "Copying ${ffmpeg_shared} to output directory"
)
endforeach()
add_custom_command(TARGET ${BOT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_BINARY_DIR}/${FFMPEG_ARCHIVE_NAME}/bin"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:dpp>"
"$<TARGET_FILE_DIR:${BOT_NAME}>"
COMMENT "Copying FFMpeg_AVCODEC DLL/so files to output directory"
COMMENT "Copying dpp DLL/so files to output directory"
)
add_subdirectory(tests)

View File

@@ -7,32 +7,35 @@ namespace utils {
// @brief 명령어가 실행 가능한지 체크합니다
// @param cmd 실행할 명령
// @return int error_code
int ValidateCommand(std::string cmd);
int ValidateCommand(
boost::asio::io_context& ctx, std::string cmd,
const std::vector<std::string>& args = std::vector<std::string>());
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
// @param cmd 실행할 명령
// @param args 아규먼트
// @return int error_code
int ExecuteCommand(
const std::string& cmd,
boost::asio::io_context& ctx, const std::string& cmd,
const std::vector<std::string>& args = std::vector<std::string>());
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
// @param cmd 실행할 명령
// @param result 실행결과
// @return int error_code
int ExecuteCommand(const std::string& cmd, std::string& result);
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
std::string& result);
// @brief 명령어를 쉘에서 실행하고 결과를 EOF 전까지 읽어 반환합니다
// @param cmd 실행할 명령
// @param args 아규먼트
// @param result 실행결과
// @return int error_code
int ExecuteCommand(const std::string& cmd, const std::vector<std::string>& args,
std::string& result);
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
const std::vector<std::string>& args, std::string& result);
// @brief 명령어를 쉘에서 실행하고 결과를 파이프로 연결하여 반환합니다
// @param cmd 실행할 명령
// @param args 아규먼트
// @return boost::process::popen
boost::process::popen OpenPipe(
const std::string& cmd,
boost::asio::io_context& ctx, const std::string& cmd,
const std::vector<std::string>& args = std::vector<std::string>());
} // namespace utils
#endif

View File

@@ -5,9 +5,9 @@
namespace utils {
int InstallYtdlp();
int InstallYtdlp(boost::asio::io_context& ctx);
int CheckUpdate();
int CheckUpdate(boost::asio::io_context& ctx);
} // namespace utils

View File

@@ -3,33 +3,8 @@
#include "utils/update_checker.h"
int main(int argc, char* argv[]) {
boost::system::error_code ec;
char buf[16384];
std::string output;
utils::CheckUpdate();
// utils::ExecuteCommand("yt-dlp", {"-U"}, output);
// std::cout << output;
// auto ytdlp_pipe = utils::OpenPipe(
// "yt-dlp", {"-o", "-", "--quiet", "--ignore-errors", "-f", "bestaudio",
// "https://youtu.be/9_bTl2vvYQg?si=IVhvpDhnpPvziwQR"});
// while (true) {
// boost::system::error_code read_ec;
// size_t bytes_read =
// boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf, 16384),
// read_ec);
// if (bytes_read > 0) {
// std::cout.write(buf, bytes_read);
// }
// if (read_ec == boost::asio::error::eof || read_ec) {
// break;
// }
// }
boost::asio::io_context ctx;
utils::CheckUpdate(ctx);
return 0;
}

View File

@@ -4,50 +4,50 @@
namespace utils {
int ValidateCommand(std::string cmd) {
int ValidateCommand(boost::asio::io_context& ctx, std::string cmd,
const std::vector<std::string>& args) {
try {
ExecuteCommand(cmd);
ExecuteCommand(ctx, cmd, args);
} catch (const boost::process::system_error& e) {
return -1;
}
return 0;
}
int ExecuteCommand(const std::string& cmd,
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
const std::vector<std::string>& args) {
std::string ignored;
return ExecuteCommand(cmd, args, ignored);
return ExecuteCommand(ctx, cmd, args, ignored);
}
int ExecuteCommand(const std::string& cmd, std::string& result) {
std::vector<std::string> ignored;
return ExecuteCommand(cmd, ignored, result);
}
int ExecuteCommand(const std::string& cmd, const std::vector<std::string>& args,
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
std::string& result) {
std::vector<std::string> ignored;
return ExecuteCommand(ctx, cmd, ignored, result);
}
int ExecuteCommand(boost::asio::io_context& ctx, const std::string& cmd,
const std::vector<std::string>& args, std::string& result) {
try {
boost::system::error_code ec;
boost::asio::io_context ctx;
boost::process::popen proc(
ctx, cmd, args, boost::process::process_stdio{{}, nullptr, nullptr});
boost::asio::read(proc, boost::asio::dynamic_buffer(result), ec);
if (ec != boost::asio::error::eof) {
return -1;
}
proc.wait();
return proc.exit_code();
} catch (const boost::process::system_error& e) {
return -1;
}
}
boost::process::popen OpenPipe(const std::string& cmd,
boost::process::popen OpenPipe(boost::asio::io_context& ctx,
const std::string& cmd,
const std::vector<std::string>& args) {
boost::asio::io_context ctx;
boost::process::popen proc(
ctx, cmd, args, boost::process::process_stdio{{}, nullptr, nullptr});
return proc;
return boost::process::popen(
ctx, cmd, args, boost::process::process_stdio{nullptr, nullptr, nullptr});
};
} // namespace utils

View File

@@ -55,8 +55,18 @@ void DownloadFileFromHTTPS(std::string url, std::string filename) {
boost::beast::http::write(stream, req);
boost::beast::flat_buffer buffer;
boost::beast::http::response<boost::beast::http::dynamic_body> res;
boost::beast::http::read(stream, buffer, res);
// 응답 파서 만들기
boost::beast::http::response_parser<boost::beast::http::dynamic_body>
parser;
// body 제한 해제 (무제한)
parser.body_limit((std::numeric_limits<std::uint64_t>::max)());
// 응답 읽기
boost::beast::http::read(stream, buffer, parser);
auto res = parser.release();
int status = res.result_int();
if (status / 100 == 3) {

View File

@@ -6,7 +6,7 @@
namespace utils {
int InstallYtdlp() {
int InstallYtdlp(boost::asio::io_context& ctx) {
BOOST_LOG_TRIVIAL(warning) << "ytdlp is unavailable. downloading ytdlp...";
#ifdef WIN32
DownloadFileFromHTTPS(
@@ -16,34 +16,54 @@ int InstallYtdlp() {
DownloadFileFromHTTPS(
"https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp",
"yt-dlp");
ExecuteCommand(boost::process::environment::find_executable("chmod").c_str(),
ExecuteCommand(ctx,
boost::process::environment::find_executable("chmod").string(),
{"+x", "yt-dlp"});
#endif
return 0;
}
int CheckUpdate() {
char buf[16384];
if (ValidateCommand("yt-dlp") != 0) {
InstallYtdlp();
return 0;
static int FindNewLinePos(std::string& string, int start_pos) {
int newline_pos = start_pos;
while (newline_pos < string.size()) {
if (string[newline_pos] == '\n') {
return newline_pos;
}
newline_pos++;
}
return newline_pos;
}
auto ytdlp_pipe = utils::OpenPipe("yt-dlp", {"-U"});
int CheckUpdate(boost::asio::io_context& ctx) {
std::string output = "";
int old_newline_pos = 0;
int newline_pos = 0;
while (true) {
boost::system::error_code read_ec;
size_t bytes_read =
boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf, 16384), read_ec);
if (bytes_read > 0) {
BOOST_LOG_TRIVIAL(info) << buf;
#ifdef WIN32
if (ExecuteCommand(ctx, "yt-dlp.exe", {"--version", "--newline"}, output) !=
0) {
InstallYtdlp(ctx);
ExecuteCommand(ctx, "yt-dlp.exe", {"--version", "--newline"}, output);
}
if (read_ec == boost::asio::error::eof || read_ec) {
break;
BOOST_LOG_TRIVIAL(info) << "yt-dlp version: "
<< output.substr(0, output.size() - 1);
output = "";
ExecuteCommand(ctx, "yt-dlp.exe", {"-U", "--newline"}, output);
#else
if (ExecuteCommand(ctx, "yt-dlp", {"--version", "--newline"}, output) != 0) {
InstallYtdlp(ctx);
ExecuteCommand(ctx, "yt-dlp", {"--version", "--newline"}, output);
}
BOOST_LOG_TRIVIAL(info) << "yt-dlp version: "
<< output.substr(0, output.size() - 1);
output = "";
ExecuteCommand(ctx, "yt-dlp", {"-U", "--newline"}, output);
#endif
while (newline_pos < output.size()) {
old_newline_pos = newline_pos;
newline_pos = FindNewLinePos(output, newline_pos);
BOOST_LOG_TRIVIAL(info) << output.substr(old_newline_pos, newline_pos - 1);
newline_pos++;
}
return 0;

8
tests/CMakeLists.txt Normal file
View File

@@ -0,0 +1,8 @@
file(GLOB_RECURSE TEST_SOURCES "*.cpp" "*.cxx" "*.cc")
foreach(test_src ${TEST_SOURCES})
get_filename_component(test_name ${test_src} NAME_WE)
add_executable(${test_name} ${test_src})
target_link_libraries(${test_name} PRIVATE ${BOT_NAME}_lib)
add_test(NAME ${test_name} COMMAND ${test_name})
endforeach()

View File

@@ -0,0 +1,52 @@
#include "precomp.h"
#include "utils/console.h"
#include "utils/update_checker.h"
int main() {
boost::asio::io_context ctx;
boost::system::error_code ec;
utils::CheckUpdate(ctx);
char buf[8192];
#ifdef WIN32
/*try {
auto ytdlp_pipe = utils::OpenPipe(ctx,
"yt-dlp.exe", { "-o", "-", "--quiet", "--ignore-errors", "-f",
"bestaudio", "https://youtu.be/9_bTl2vvYQg?si=IVhvpDhnpPvziwQR" });
while (true) {
boost::system::error_code read_ec;
size_t bytes_read =
boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf,
8192), read_ec); if (bytes_read > 0) { std::cout.write(buf, bytes_read);
}
if (read_ec == boost::asio::error::eof || read_ec) {
break;
}
}
}
catch (const boost::process::system_error& e) {
std::string error = e.what();
return -1;
}*/
#else
auto ytdlp_pipe = utils::OpenPipe(
ctx, "yt-dlp",
{"-o", "-", "--quiet", "--ignore-errors", "-f", "bestaudio",
"https://youtu.be/9_bTl2vvYQg?si=IVhvpDhnpPvziwQR"});
while (true) {
boost::system::error_code read_ec;
size_t bytes_read =
boost::asio::read(ytdlp_pipe, boost::asio::buffer(buf, 8192), read_ec);
if (bytes_read > 0) {
std::cout.write(buf, bytes_read);
}
if (read_ec == boost::asio::error::eof || read_ec) {
break;
}
}
#endif
return 0;
}

8
tests/update.cc Normal file
View File

@@ -0,0 +1,8 @@
#include "precomp.h"
#include "utils/update_checker.h"
int main() {
boost::asio::io_context ctx;
utils::CheckUpdate(ctx);
return 0;
}

BIN
yt-dlp

Binary file not shown.