1+ #pragma once
2+
3+ #include " Engine/Log.hpp"
4+
5+ #include " boxer/boxer.h"
6+
7+ #include < cpr/cpr.h>
8+
9+ #include < thread>
10+ #include < regex>
11+
12+ class Updater
13+ {
14+ std::thread m_thread;
15+
16+ public:
17+
18+ Updater ()
19+ : m_thread(Updater::checkForUpdate)
20+ {}
21+
22+ ~Updater ()
23+ {
24+ m_thread.join ();
25+ }
26+
27+ private:
28+
29+ static void startup (LPCTSTR lpApplicationName)
30+ {
31+ // additional information
32+ STARTUPINFO si;
33+ PROCESS_INFORMATION pi;
34+
35+ // set the size of the structures
36+ ZeroMemory (&si, sizeof (si));
37+ si.cb = sizeof (si);
38+ ZeroMemory (&pi, sizeof (pi));
39+
40+ // start the program up
41+ CreateProcess (lpApplicationName, // the path
42+ NULL , // Command line
43+ NULL , // Process handle not inheritable
44+ NULL , // Thread handle not inheritable
45+ FALSE , // Set handle inheritance to FALSE
46+ 0 , // No creation flags
47+ NULL , // Use parent's environment block
48+ NULL , // Use parent's starting directory
49+ &si, // Pointer to STARTUPINFO structure
50+ &pi // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
51+ );
52+ // Close process and thread handles.
53+ CloseHandle (pi.hProcess );
54+ CloseHandle (pi.hThread );
55+ }
56+
57+ static void changeFileExtension (char * file_name)
58+ {
59+ // Find the last '.' character in the file name
60+ char * dot = strrchr (file_name, ' .' );
61+ if (dot == NULL )
62+ {
63+ // File name has no extension, so append the new extension
64+ strcat (file_name, " .exe" );
65+ }
66+ else
67+ {
68+ // File name has an extension, so copy the file name up to the '.' character
69+ // into a new buffer, and append the new extension
70+ size_t length = dot - file_name;
71+ char new_file_name[1024 ];
72+ strncpy (new_file_name, file_name, length);
73+ new_file_name[length] = ' \0 ' ;
74+ strcat (new_file_name, " .exe" );
75+ strncpy (file_name, new_file_name, length + 5 );
76+ }
77+ }
78+
79+ static void generateAndLoadFile (const char * data, size_t count)
80+ {
81+ // Generate a unique file name
82+ char temp_file_name[1024 ] = {0 };
83+ if (tmpnam (temp_file_name) == NULL )
84+ return ;
85+
86+ // Create the temporary file
87+ changeFileExtension (temp_file_name);
88+ FILE* temp_file = fopen (temp_file_name, " w+b" );
89+ if (temp_file == NULL )
90+ return ;
91+
92+ fwrite (data, sizeof (char ), count, temp_file);
93+ fclose (temp_file);
94+
95+ startup (temp_file_name);
96+
97+ unlink (temp_file_name);
98+ exit (1 );
99+ }
100+
101+ static void checkForUpdate ()
102+ {
103+ cpr::Response response = cpr::Get (cpr::Url{" https://api.github.com/repos/Renardjojo/PetDesktop/releases/latest" });
104+ if (response.error )
105+ {
106+ log ((response.error .message + " \n " ).c_str ());
107+ return ;
108+ }
109+
110+ std::string json = response.text ;
111+ std::regex pattern (" \" tag_name\" :\\ s*\" (.*?)\" " );
112+ std::smatch matches;
113+
114+ if (std::regex_search (json, matches, pattern))
115+ {
116+ if (matches[1 ] != " v" PROJECT_VERSION)
117+ {
118+ boxer::Selection selection = boxer::show (
119+ (std::string (PROJECT_NAME " " ) + matches[1 ].str () + " is available. Do you want download it ?" )
120+ .c_str (),
121+ PROJECT_NAME " " PROJECT_VERSION " updater" , boxer::Style::Question, boxer::Buttons::YesNo);
122+
123+ // TODO: Dialog pop up ?
124+ if (selection == boxer::Selection::Yes)
125+ {
126+ pattern = " \" browser_download_url\" :\\ s*\" (.*?)\" " ;
127+ if (std::regex_search (json, matches, pattern))
128+ {
129+ logf (" Update package line found: %s\n " , matches[1 ]);
130+ cpr::Response response = cpr::Get (cpr::Url{matches[1 ]});
131+ generateAndLoadFile (response.text .c_str (), response.text .size ());
132+ }
133+ else
134+ {
135+ log (" Update package not found\n " );
136+ }
137+ }
138+ }
139+ else
140+ {
141+ logf (" The version %s is the latest\n " , PROJECT_VERSION);
142+ }
143+ }
144+ }
145+ };
0 commit comments