github_down
This commit is contained in:
39
github_down/gen.py
Normal file
39
github_down/gen.py
Normal file
@ -0,0 +1,39 @@
|
||||
from subprocess import run
|
||||
|
||||
proxies = [
|
||||
"https://hk.gh-proxy.org/",
|
||||
"https://cdn.gh-proxy.org/",
|
||||
"https://gh-proxy.org/",
|
||||
"https://edgeone.gh-proxy.org/",
|
||||
"https://gh-proxy.top/",
|
||||
"https://gh-proxy.net/",
|
||||
"https://gh-proxy.com/",
|
||||
"https://ghfast.top/",
|
||||
"https://gh.ddlc.top/",
|
||||
"https://gh.llkk.cc/",
|
||||
"https://ghproxy.homeboyc.cn/",
|
||||
"",
|
||||
]
|
||||
|
||||
cmd = [
|
||||
"aria2c",
|
||||
"--auto-file-renaming=false",
|
||||
"--retry-wait=2",
|
||||
"--max-tries=0",
|
||||
"--timeout=10",
|
||||
"--connect-timeout=5",
|
||||
"--lowest-speed-limit=100K",
|
||||
"-x","4","-s","24","-k","1M",
|
||||
]
|
||||
|
||||
try:
|
||||
run("aria2c --version", check=True, capture_output=True)
|
||||
except Exception:
|
||||
print("请先安装aria2")
|
||||
exit(1)
|
||||
|
||||
input_url = input("请输入GitHub文件链接: ").strip()
|
||||
cmd.extend(
|
||||
[f"{proxy}{input_url}" for proxy in proxies]
|
||||
)
|
||||
run(cmd)
|
||||
250
github_down/gen_win.cpp
Normal file
250
github_down/gen_win.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
#include <clocale>
|
||||
|
||||
// ---------------- UTF helpers ----------------
|
||||
static std::wstring utf8_to_wstring(const std::string& s) {
|
||||
if (s.empty()) return L"";
|
||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), nullptr, 0);
|
||||
std::wstring w(wlen, L'\0');
|
||||
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), w.data(), wlen);
|
||||
return w;
|
||||
}
|
||||
|
||||
static std::string trim_copy(std::string s) {
|
||||
auto is_space = [](unsigned char c) { return c==' '||c=='\t'||c=='\n'||c=='\r'; };
|
||||
while (!s.empty() && is_space((unsigned char)s.back())) s.pop_back();
|
||||
size_t i = 0;
|
||||
while (i < s.size() && is_space((unsigned char)s[i])) i++;
|
||||
return s.substr(i);
|
||||
}
|
||||
|
||||
// Quote a single arg for CreateProcess command line.
|
||||
static std::wstring quote_arg_windows(const std::wstring& arg) {
|
||||
bool need_quotes = arg.empty();
|
||||
for (wchar_t c : arg) {
|
||||
if (c == L' ' || c == L'\t' || c == L'\n' || c == L'\v' || c == L'"') {
|
||||
need_quotes = true; break;
|
||||
}
|
||||
}
|
||||
if (!need_quotes) return arg;
|
||||
|
||||
std::wstring out = L"\"";
|
||||
size_t bs_count = 0;
|
||||
for (wchar_t c : arg) {
|
||||
if (c == L'\\') {
|
||||
bs_count++;
|
||||
} else if (c == L'"') {
|
||||
out.append(bs_count * 2 + 1, L'\\');
|
||||
out.push_back(L'"');
|
||||
bs_count = 0;
|
||||
} else {
|
||||
if (bs_count) out.append(bs_count, L'\\');
|
||||
bs_count = 0;
|
||||
out.push_back(c);
|
||||
}
|
||||
}
|
||||
if (bs_count) out.append(bs_count * 2, L'\\');
|
||||
out.push_back(L'"');
|
||||
return out;
|
||||
}
|
||||
|
||||
// ---------------- RAII cleanup guard ----------------
|
||||
struct TempBundleGuard {
|
||||
std::filesystem::path dir;
|
||||
std::filesystem::path aria2_path;
|
||||
|
||||
~TempBundleGuard() {
|
||||
// Best-effort cleanup
|
||||
try {
|
||||
if (!aria2_path.empty() && std::filesystem::exists(aria2_path)) {
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(aria2_path, ec);
|
||||
}
|
||||
if (!dir.empty() && std::filesystem::exists(dir)) {
|
||||
std::error_code ec;
|
||||
std::filesystem::remove_all(dir, ec);
|
||||
}
|
||||
} catch (...) {
|
||||
// swallow
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------- Resource extraction ----------------
|
||||
static bool extract_resource_to_file(
|
||||
const wchar_t* res_name,
|
||||
const std::filesystem::path& out_path
|
||||
) {
|
||||
HRSRC hrsrc = FindResourceW(nullptr, res_name, RT_RCDATA);
|
||||
if (!hrsrc) return false;
|
||||
|
||||
HGLOBAL hglob = LoadResource(nullptr, hrsrc);
|
||||
if (!hglob) return false;
|
||||
|
||||
DWORD size = SizeofResource(nullptr, hrsrc);
|
||||
void* data = LockResource(hglob);
|
||||
if (!data || size == 0) return false;
|
||||
|
||||
std::ofstream ofs(out_path, std::ios::binary);
|
||||
ofs.write(reinterpret_cast<const char*>(data), size);
|
||||
return ofs.good();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------------- Process runner ----------------
|
||||
static int run_process(const std::wstring& exe_path, const std::vector<std::wstring>& args, bool show) {
|
||||
std::wstring cmdline = quote_arg_windows(exe_path);
|
||||
for (const auto& a : args) {
|
||||
cmdline.push_back(L' ');
|
||||
cmdline += quote_arg_windows(a);
|
||||
}
|
||||
|
||||
STARTUPINFOW si{};
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags = STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_SHOW;
|
||||
|
||||
PROCESS_INFORMATION pi{};
|
||||
|
||||
// CreateProcessW may modify buffer
|
||||
std::vector<wchar_t> buf(cmdline.begin(), cmdline.end());
|
||||
buf.push_back(L'\0');
|
||||
|
||||
BOOL ok = CreateProcessW(
|
||||
nullptr,
|
||||
buf.data(),
|
||||
nullptr, nullptr,
|
||||
FALSE,
|
||||
show ? 0 : CREATE_NO_WINDOW,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&si,
|
||||
&pi
|
||||
);
|
||||
|
||||
if (!ok) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
|
||||
DWORD code = 0;
|
||||
GetExitCodeProcess(pi.hProcess, &code);
|
||||
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
return (int)code;
|
||||
}
|
||||
|
||||
// ---------------- Get temp directory ----------------
|
||||
static std::filesystem::path get_temp_dir() {
|
||||
wchar_t buf[MAX_PATH + 1];
|
||||
DWORD n = GetTempPathW(MAX_PATH, buf);
|
||||
if (n == 0 || n > MAX_PATH) throw std::runtime_error("GetTempPathW failed");
|
||||
return std::filesystem::path(buf);
|
||||
}
|
||||
|
||||
static std::filesystem::path make_unique_subdir(const std::filesystem::path& base) {
|
||||
// Use PID + tick count for uniqueness
|
||||
DWORD pid = GetCurrentProcessId();
|
||||
ULONGLONG t = GetTickCount64();
|
||||
|
||||
std::filesystem::path dir = base / L"MyAria2Bundle";
|
||||
std::filesystem::path uniq = dir / (L"run_" + std::to_wstring(pid) + L"_" + std::to_wstring(t));
|
||||
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(uniq, ec);
|
||||
if (ec) throw std::runtime_error("create_directories failed");
|
||||
return uniq;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Windows console UTF-8
|
||||
SetConsoleCP(65001);
|
||||
SetConsoleOutputCP(65001);
|
||||
std::setlocale(LC_ALL, ".UTF-8");
|
||||
|
||||
// Proxies list (same as your python)
|
||||
const std::vector<std::string> proxies = {
|
||||
"https://hk.gh-proxy.org/",
|
||||
"https://cdn.gh-proxy.org/",
|
||||
"https://gh-proxy.org/",
|
||||
"https://edgeone.gh-proxy.org/",
|
||||
"https://gh-proxy.top/",
|
||||
"https://gh-proxy.net/",
|
||||
"https://gh-proxy.com/",
|
||||
"https://ghfast.top/",
|
||||
"https://gh.ddlc.top/",
|
||||
"https://gh.llkk.cc/",
|
||||
"https://ghproxy.homeboyc.cn/",
|
||||
""
|
||||
};
|
||||
|
||||
TempBundleGuard guard;
|
||||
try {
|
||||
// Extract aria2c.exe to %TEMP%\MyAria2Bundle\run_xxx\aria2c.exe
|
||||
auto temp_base = get_temp_dir();
|
||||
guard.dir = make_unique_subdir(temp_base);
|
||||
guard.aria2_path = guard.dir / L"aria2c.exe";
|
||||
|
||||
if (!extract_resource_to_file(L"ARIA2_BIN", guard.aria2_path)) {
|
||||
std::cerr << "释放 aria2c.exe 失败:资源 ARIA2_BIN 不存在或写入失败。\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
int rc = run_process(guard.aria2_path, {L"--version"},false);
|
||||
if (rc != 0) {
|
||||
std::cerr << "aria2c 自检失败(exit=" << rc << ")。\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "请输入GitHub文件链接: ";
|
||||
std::string input_url;
|
||||
std::getline(std::cin, input_url);
|
||||
input_url = trim_copy(input_url);
|
||||
if (input_url.empty()) {
|
||||
std::cerr << "输入为空,退出。\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> args = {
|
||||
L"--auto-file-renaming=false",
|
||||
L"--retry-wait=2",
|
||||
L"--max-tries=0",
|
||||
L"--timeout=10",
|
||||
L"--connect-timeout=5",
|
||||
L"--lowest-speed-limit=100K",
|
||||
L"-x", L"4",
|
||||
L"-s", L"24",
|
||||
L"-k", L"1M"
|
||||
};
|
||||
|
||||
for (const auto& p : proxies) {
|
||||
std::string full = p + input_url;
|
||||
args.push_back(utf8_to_wstring(full));
|
||||
}
|
||||
|
||||
int rc = run_process(guard.aria2_path, args,true);
|
||||
if (rc != 0) {
|
||||
std::cerr << "aria2c 执行失败(exit=" << rc << ")。\n";
|
||||
}
|
||||
return rc;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "异常: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
1
github_down/resource.rc
Normal file
1
github_down/resource.rc
Normal file
@ -0,0 +1 @@
|
||||
ARIA2_BIN RCDATA "aria2c.exe"
|
||||
Reference in New Issue
Block a user