forked from chinosk/gkms-localify-dmm
dmm版添加自动更新功能
This commit is contained in:
parent
8a0e332292
commit
64809af01c
|
|
@ -1956,5 +1956,11 @@ namespace GakumasLocal::Hook {
|
||||||
|
|
||||||
|
|
||||||
Log::Info("Hook installed");
|
Log::Info("Hook installed");
|
||||||
|
|
||||||
|
// 延迟启动自动资源更新检查
|
||||||
|
std::thread([]() {
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
GkmsResourceUpdate::AutoCheckUpdateFromAPI();
|
||||||
|
}).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,18 +47,18 @@ namespace GkmsResourceUpdate {
|
||||||
using namespace concurrency::streams;
|
using namespace concurrency::streams;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 打开输出文件流(同步方式)
|
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD>
|
||||||
auto outTask = fstream::open_ostream(conversions::to_string_t(outputPath));
|
auto outTask = fstream::open_ostream(conversions::to_string_t(outputPath));
|
||||||
outTask.wait();
|
outTask.wait();
|
||||||
auto fileStream = outTask.get();
|
auto fileStream = outTask.get();
|
||||||
|
|
||||||
// 创建 HTTP 客户端,注意:如果 url 包含完整路径,cpprestsdk 会自动解析
|
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP <20>ͻ<EFBFBD><CDBB>ˣ<EFBFBD>ע<EFBFBD>⣺<EFBFBD><E2A3BA><EFBFBD> url <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>cpprestsdk <20><><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>
|
||||||
http_client client(conversions::to_string_t(url));
|
http_client client(conversions::to_string_t(url));
|
||||||
|
|
||||||
downloading = true;
|
downloading = true;
|
||||||
downloadProgress = 0.0f;
|
downloadProgress = 0.0f;
|
||||||
|
|
||||||
// 发起 GET 请求
|
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD> GET <20><><EFBFBD><EFBFBD>
|
||||||
auto responseTask = client.request(methods::GET);
|
auto responseTask = client.request(methods::GET);
|
||||||
responseTask.wait();
|
responseTask.wait();
|
||||||
http_response response = responseTask.get();
|
http_response response = responseTask.get();
|
||||||
|
|
@ -68,12 +68,12 @@ namespace GkmsResourceUpdate {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取响应头中的文件大小(如果存在)
|
// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Ӧͷ<EFBFBD>е<EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڣ<EFBFBD>
|
||||||
uint64_t contentLength = 0;
|
uint64_t contentLength = 0;
|
||||||
if (response.headers().has(L"Content-Length"))
|
if (response.headers().has(L"Content-Length"))
|
||||||
contentLength = std::stoull(conversions::to_utf8string(response.headers().find(L"Content-Length")->second));
|
contentLength = std::stoull(conversions::to_utf8string(response.headers().find(L"Content-Length")->second));
|
||||||
|
|
||||||
// 读取响应体,逐块写入文件,同时更新进度
|
// <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Ӧ<EFBFBD>壬<EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>½<EFBFBD><EFBFBD><EFBFBD>
|
||||||
auto inStream = response.body();
|
auto inStream = response.body();
|
||||||
const size_t bufferSize = 8192;
|
const size_t bufferSize = 8192;
|
||||||
// std::vector<unsigned char> buffer(bufferSize);
|
// std::vector<unsigned char> buffer(bufferSize);
|
||||||
|
|
@ -118,13 +118,13 @@ namespace GkmsResourceUpdate {
|
||||||
buffer << file.rdbuf();
|
buffer << file.rdbuf();
|
||||||
std::string content = buffer.str();
|
std::string content = buffer.str();
|
||||||
|
|
||||||
// 去除首尾空格和换行符
|
// ȥ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD>ո<EFBFBD>ͻ<EFBFBD><EFBFBD>з<EFBFBD>
|
||||||
auto is_not_space = [](unsigned char ch) {
|
auto is_not_space = [](unsigned char ch) {
|
||||||
return !std::isspace(ch);
|
return !std::isspace(ch);
|
||||||
};
|
};
|
||||||
// 去除前导空白
|
// ȥ<EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD>
|
||||||
content.erase(content.begin(), std::find_if(content.begin(), content.end(), is_not_space));
|
content.erase(content.begin(), std::find_if(content.begin(), content.end(), is_not_space));
|
||||||
// 去除尾部空白
|
// ȥ<EFBFBD><EFBFBD>β<EFBFBD><EFBFBD><EFBFBD>հ<EFBFBD>
|
||||||
content.erase(std::find_if(content.rbegin(), content.rend(), is_not_space).base(), content.end());
|
content.erase(std::find_if(content.rbegin(), content.rend(), is_not_space).base(), content.end());
|
||||||
resourceVersionCache = content;
|
resourceVersionCache = content;
|
||||||
return content;
|
return content;
|
||||||
|
|
@ -204,7 +204,7 @@ namespace GkmsResourceUpdate {
|
||||||
g_reload_all_data();
|
g_reload_all_data();
|
||||||
GakumasLocal::Log::Info("Update completed.");
|
GakumasLocal::Log::Info("Update completed.");
|
||||||
}
|
}
|
||||||
// 仅解压一个文件
|
// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѹһ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +217,66 @@ namespace GkmsResourceUpdate {
|
||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoCheckUpdateFromAPI() {
|
||||||
|
std::thread([]() {
|
||||||
|
try {
|
||||||
|
if (!g_useAPIAssets) {
|
||||||
|
GakumasLocal::Log::Info("Auto update check skipped: API assets disabled.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GakumasLocal::Log::Info("Auto checking update from API...");
|
||||||
|
|
||||||
|
auto response = send_get(g_useAPIAssetsURL, 30);
|
||||||
|
if (response.status_code() != 200) {
|
||||||
|
GakumasLocal::Log::ErrorFmt("Auto update check failed: HTTP %d\n", response.status_code());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = nlohmann::json::parse(response.extract_utf8string().get());
|
||||||
|
|
||||||
|
std::string remoteVersion = data["tag_name"];
|
||||||
|
const auto localVersion = GetCurrentResourceVersion(false);
|
||||||
|
|
||||||
|
if (localVersion == remoteVersion) {
|
||||||
|
GakumasLocal::Log::InfoFmt("Local resource is already up to date (v%s).", localVersion.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GakumasLocal::Log::InfoFmt("New resource version found: %s -> %s", localVersion.c_str(), remoteVersion.c_str());
|
||||||
|
GakumasLocal::Log::Info("Starting automatic download...");
|
||||||
|
|
||||||
|
if (!data.contains("assets") || !data["assets"].is_array()) {
|
||||||
|
GakumasLocal::Log::Error("API response doesn't contain assets array.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& asset : data["assets"]) {
|
||||||
|
if (!asset.contains("name") || !asset.contains("browser_download_url"))
|
||||||
|
continue;
|
||||||
|
std::string name = asset["name"];
|
||||||
|
if (name.ends_with(".zip")) {
|
||||||
|
std::string downloadUrl = asset["browser_download_url"];
|
||||||
|
|
||||||
|
if (unzipFileFromURL(downloadUrl, gakumasLocalPath.string())) {
|
||||||
|
g_reload_all_data();
|
||||||
|
GakumasLocal::Log::Info("Auto update completed successfully.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
GakumasLocal::Log::Error("Auto update failed during download or extraction.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GakumasLocal::Log::Error("No .zip file found in assets.");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (std::exception& e) {
|
||||||
|
GakumasLocal::Log::ErrorFmt("Exception occurred in AutoCheckUpdateFromAPI: %s\n", e.what());
|
||||||
|
}
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
void checkUpdateFromURL(const std::string& downloadUrl) {
|
void checkUpdateFromURL(const std::string& downloadUrl) {
|
||||||
std::thread([downloadUrl]() {
|
std::thread([downloadUrl]() {
|
||||||
if (unzipFileFromURL(downloadUrl, gakumasLocalPath.string(), "local-files")) {
|
if (unzipFileFromURL(downloadUrl, gakumasLocalPath.string(), "local-files")) {
|
||||||
|
|
|
||||||
|
|
@ -6,5 +6,6 @@ namespace GkmsResourceUpdate {
|
||||||
void saveProgramConfig();
|
void saveProgramConfig();
|
||||||
std::string GetCurrentResourceVersion(bool useCache);
|
std::string GetCurrentResourceVersion(bool useCache);
|
||||||
void CheckUpdateFromAPI(bool isManual);
|
void CheckUpdateFromAPI(bool isManual);
|
||||||
|
void AutoCheckUpdateFromAPI();
|
||||||
void checkUpdateFromURL(const std::string& downloadUrl);
|
void checkUpdateFromURL(const std::string& downloadUrl);
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue