diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9f15f94 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "ofen"] + path = ofen + url = https://www.sinxmiao.cn/taynpg/ofen +[submodule "zoost"] + path = zoost + url = https://www.sinxmiao.cn/taynpg/zoost diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ab627a..7ed5a62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,3 +10,9 @@ if (MSVC) add_compile_options(/utf-8) add_subdirectory(wt_reg) endif() + +add_definitions(-DFMT_HEADER_ONLY) +include_directories(ofen) +add_subdirectory(zoost) +add_subdirectory(del_file) +add_subdirectory(use_tdl) \ No newline at end of file diff --git a/del_file/CMakeLists.txt b/del_file/CMakeLists.txt new file mode 100644 index 0000000..40ef3e3 --- /dev/null +++ b/del_file/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16) + +project(del_file LANGUAGES CXX) + +add_executable(del_file main.cpp) \ No newline at end of file diff --git a/del_file/main.cpp b/del_file/main.cpp new file mode 100644 index 0000000..e686d0c --- /dev/null +++ b/del_file/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char* argv[]) +{ + + return 0; +} \ No newline at end of file diff --git a/ofen b/ofen new file mode 160000 index 0000000..bc92823 --- /dev/null +++ b/ofen @@ -0,0 +1 @@ +Subproject commit bc928233f0bc8facd6e0ea8e8bead146e5850844 diff --git a/use_tdl/CMakeLists.txt b/use_tdl/CMakeLists.txt new file mode 100644 index 0000000..9b3da3f --- /dev/null +++ b/use_tdl/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.16) + +project(use_tdl LANGUAGES CXX) + +add_executable(use_tdl main.cpp) \ No newline at end of file diff --git a/use_tdl/main.cpp b/use_tdl/main.cpp new file mode 100644 index 0000000..9d9cd3a --- /dev/null +++ b/use_tdl/main.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = std::filesystem; + +struct Args { + std::string downloader; + std::string url; + std::string output; + std::string proxy = "http://127.0.0.1:7897"; + uint32_t retry = 2; + uint64_t retry_interval = 5; +}; + +// 执行命令并返回退出码 +int execute_command(const std::string& program, const std::vector& args) +{ + try { + // 构建命令字符串用于显示 + std::string cmd_str = program; + for (const auto& arg : args) { + cmd_str += " " + arg; + } + fmt::print("执行命令: {}\n", cmd_str); + + // 构建命令行参数数组 + std::vector argv; + argv.push_back(program.c_str()); + + for (const auto& arg : args) { + argv.push_back(arg.c_str()); + } + argv.push_back(nullptr); + + // 执行命令 + int result = std::system(cmd_str.c_str()); + + // Windows 上直接返回,Linux/macOS 需要使用宏提取退出码 +#ifdef _WIN32 + return result; +#else + return WEXITSTATUS(result); +#endif + } catch (const std::exception& e) { + fmt::print(stderr, "执行命令失败: {}\n", e.what()); + return -1; + } +} + +// 调用外部下载器 +int call_downloader(const std::string& downloader_path, const std::string& url, const std::string& output_dir, + const std::string& proxy, bool resume) +{ + + std::vector args = {"dl", "-u", url, "--proxy", proxy, "-d", output_dir, "--skip-same"}; + + if (resume) { + args.push_back("--continue"); + } + + return execute_command(downloader_path, args); +} + +// 带重试的下载函数 +int download_with_retry(const Args& args) +{ + uint32_t max_attempts = args.retry + 1; + uint32_t attempt = 1; + + while (true) { + fmt::print("\n=== 尝试 {}/{} ===\n", attempt, max_attempts); + + int status = call_downloader(args.downloader, args.url, args.output, args.proxy, false); + + if (status == 0) { // 成功 + fmt::print("✅ 第{}次尝试成功\n", attempt); + return status; + } else if (attempt < max_attempts) { // 失败但还可重试 + fmt::print("❌ 第{}次尝试失败,{}秒后重试...\n", attempt, args.retry_interval); + + std::this_thread::sleep_for(std::chrono::seconds(args.retry_interval)); + attempt++; + } else { // 达到最大重试次数 + fmt::print(stderr, "❌ 已达到最大重试次数({}次),下载失败\n", max_attempts); + return status; + } + } +} + +int main(int argc, char** argv) +{ + Args args; + + CLI::App app{"简单的下载器包装工具"}; + + // 添加命令行参数 + app.add_option("-d,--downloader", args.downloader, "外部下载器程序的路径")->required()->check(CLI::ExistingFile); + + app.add_option("-u,--url", args.url, "远程文件的URL")->required(); + + app.add_option("-o,--output", args.output, "本地存储目录")->required()->check(CLI::ExistingDirectory); + + // proxy 参数(有默认值的字符串参数) + app.add_option("-p,--proxy", args.proxy, "代理")->default_val("http://127.0.0.1:7897"); + + // retry 参数(有默认值的数值参数) + app.add_option("-r,--retry", args.retry, "重试次数")->default_val(2)->check(CLI::NonNegativeNumber); + + // retry-interval 参数(有默认值的数值参数) + app.add_option("-i,--retry-interval", args.retry_interval, "重试间隔(秒)")->default_val(5)->check(CLI::NonNegativeNumber); + + try { + app.parse(argc, argv); + } catch (const CLI::ParseError& e) { + return app.exit(e); + } + + // 打印URL(无论成功失败都会在最后打印) + fmt::print("下载URL: {}\n", args.url); + + // CLI11 已经做了基本的验证,但我们可以再次验证 + if (!fs::exists(args.downloader)) { + fmt::print(stderr, "错误: 下载器文件不存在: {}\n", args.downloader); + return 1; + } + + if (!fs::exists(args.output)) { + fmt::print(stderr, "错误: 输出目录不存在: {}\n", args.output); + return 1; + } + + if (!fs::is_directory(args.output)) { + fmt::print(stderr, "错误: 输出路径不是目录: {}\n", args.output); + return 1; + } + + fmt::print("开始下载...\n"); + fmt::print(" 下载器: {}\n", args.downloader); + fmt::print(" 远程URL: {}\n", args.url); + fmt::print(" 输出目录: {}\n", args.output); + fmt::print(" 代理: {}\n", args.proxy); + fmt::print(" 重试次数: {}\n", args.retry); + fmt::print(" 重试间隔: {}秒\n", args.retry_interval); + + // 调用外部下载器,带有重试逻辑 + int status = download_with_retry(args); + + // 无论成功失败,都打印URL + fmt::print("\n下载URL: {}\n", args.url); + + // 判断下载是否成功 + if (status == 0) { + fmt::print("✅ 下载成功!\n"); + return 0; + } else { + fmt::print(stderr, "❌ 下载失败,退出码: {}\n", status); + return 1; + } +} \ No newline at end of file diff --git a/zoost b/zoost new file mode 160000 index 0000000..c2c2a98 --- /dev/null +++ b/zoost @@ -0,0 +1 @@ +Subproject commit c2c2a983f1f7d19934841ee14205e64243a8c435