From 775a131b328c481580ecac951b34eb1e7032bfad Mon Sep 17 00:00:00 2001 From: Six Jonathan Date: Fri, 6 Jan 2023 22:27:12 +0100 Subject: [PATCH] Create updater --- .gitmodules | 3 ++ CMakeLists.txt | 4 ++ deps/cpr | 1 + include/Game/Game.hpp | 123 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 129 insertions(+), 2 deletions(-) create mode 160000 deps/cpr diff --git a/.gitmodules b/.gitmodules index d16bfaf..d66a9be 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "deps/yaml-cpp"] path = deps/yaml-cpp url = https://github.com/jbeder/yaml-cpp.git +[submodule "deps/cpr"] + path = deps/cpr + url = https://github.com/libcpr/cpr.git diff --git a/CMakeLists.txt b/CMakeLists.txt index b1f3283..63f790b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,10 @@ target_link_libraries(${PROJECT_NAME} Boxer) add_subdirectory(${ABS_DEPS_DIR}/yaml-cpp) target_link_libraries(${PROJECT_NAME} yaml-cpp) +# cpr +add_subdirectory(${ABS_DEPS_DIR}/cpr) +target_link_libraries(${PROJECT_NAME} cpr) + ########### Define ############ target_compile_definitions(${PROJECT_NAME} PRIVATE RESOURCE_PATH="${REL_RESOURCES_DIR}/") target_compile_definitions(${PROJECT_NAME} PRIVATE PROJECT_NAME="${PROJECT_NAME}") diff --git a/deps/cpr b/deps/cpr new file mode 160000 index 0000000..b97163a --- /dev/null +++ b/deps/cpr @@ -0,0 +1 @@ +Subproject commit b97163a237ae4554101c2c7c5ab6353945038717 diff --git a/include/Game/Game.hpp b/include/Game/Game.hpp index 2e7a275..7854337 100644 --- a/include/Game/Game.hpp +++ b/include/Game/Game.hpp @@ -16,10 +16,12 @@ #include "Engine/Log.hpp" #include "Engine/Vector2.hpp" -#include - #include #include +#include + +#include +#include class Game { @@ -108,6 +110,7 @@ class Game public: Game() : setting(RESOURCE_PATH "setting/setting.yaml", datas), mainLoop(datas), physicSystem(datas) { + checkForUpdate(); logf("%s %s\n", PROJECT_NAME, PROJECT_VERSION); initWindow(); initOpenGL(); @@ -131,6 +134,122 @@ class Game srand(datas.randomSeed == -1 ? (unsigned)time(nullptr) : datas.randomSeed); } + + void startup(LPCTSTR lpApplicationName) + { + // additional information + STARTUPINFO si; + PROCESS_INFORMATION pi; + + // set the size of the structures + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + // start the program up + CreateProcess(lpApplicationName, // the path + NULL, // Command line + NULL, // Process handle not inheritable + NULL, // Thread handle not inheritable + FALSE, // Set handle inheritance to FALSE + 0, // No creation flags + NULL, // Use parent's environment block + NULL, // Use parent's starting directory + &si, // Pointer to STARTUPINFO structure + &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses) + ); + // Close process and thread handles. + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } + + void changeFileExtension(char* file_name) + { + // Find the last '.' character in the file name + char* dot = strrchr(file_name, '.'); + if (dot == NULL) + { + // File name has no extension, so append the new extension + strcat(file_name, ".exe"); + } + else + { + // File name has an extension, so copy the file name up to the '.' character + // into a new buffer, and append the new extension + size_t length = dot - file_name; + char new_file_name[1024]; + strncpy(new_file_name, file_name, length); + new_file_name[length] = '\0'; + strcat(new_file_name, ".exe"); + strncpy(file_name, new_file_name, length + 5); + } + } + + void generateAndLoadFile(const char* data, size_t count) + { + // Generate a unique file name + char temp_file_name[1024] = {0}; + if (tmpnam(temp_file_name) == NULL) + return; + + // Create the temporary file + changeFileExtension(temp_file_name); + FILE* temp_file = fopen(temp_file_name, "w+b"); + if (temp_file == NULL) + return; + + fwrite(data, sizeof(char), count, temp_file); + fclose(temp_file); + + startup(temp_file_name); + + unlink(temp_file_name); + exit(1); + } + + void checkForUpdate() + { + auto response = cpr::Get(cpr::Url{"https://api.github.com/repos/Renardjojo/PetDesktop/releases/latest"}); + + if (response.error) + { + log(response.error.message.c_str()); + return; + } + + std::string json = response.text; + std::regex pattern("\"tag_name\":\\s*\"(.*?)\""); + std::smatch matches; + + if (std::regex_search(json, matches, pattern)) + { + if (matches[1] != PROJECT_VERSION) + { + boxer::Selection selection = boxer::show("An update is available, do you want download it ?", PROJECT_NAME " update", boxer::Style::Question, boxer::Buttons::YesNo); + + // TODO: Pop up + if (selection == boxer::Selection::Yes) + { + pattern = "\"browser_download_url\":\\s*\"(.*?)\""; + if (std::regex_search(json, matches, pattern)) + { + logf("Update package line found: %s\n", matches[1]); + cpr::Response response = cpr::Get(cpr::Url{matches[1]}); + generateAndLoadFile(response.text.c_str(), response.text.size()); + } + else + { + log("Update package not found"); + } + } + } + else + { + logf("The version %s is the latest", PROJECT_VERSION); + } + } + } + void initDrawContext() { Framebuffer::bindScreen();