88#include < filesystem>
99#include < iostream>
1010#include < shellapi.h>
11+ #include < wininet.h>
12+ #pragma comment(lib, "wininet.lib")
1113
1214#define MAX_LOADSTRING 100
1315#define WM_SENDKEYS (WM_USER + 1 )
1416#define WM_TRAYICON (WM_USER + 2 )
1517
16- std::wstring VERSION_STRING = L" 0.1.7 " ;
18+ std::wstring VERSION_STRING = L" 0.2.0 " ;
1719
1820NOTIFYICONDATA nid = {};
1921HMENU hTrayMenu = nullptr ;
@@ -63,7 +65,7 @@ std::string get_datetime_string() {
6365
6466// Add a line to the open log file
6567size_t log_line (std::string line) {
66- if (!LOG ) {
68+ if (!LOG || !enableLogging ) {
6769 std::cerr << " Log file not ready #52195.\n " ;
6870 return 0 ;
6971 }
@@ -105,31 +107,77 @@ void UpdateDisplayedTextFromShortcuts() {
105107 }
106108 }
107109}
108- bool LoadDataFromJson (const std::wstring& filename) {
109- shortcuts = {};
110+ std::string FetchURL (const std::string& url) {
111+ HINTERNET hInternet = InternetOpen (L" MyApp" , INTERNET_OPEN_TYPE_DIRECT , NULL , NULL , 0 );
112+ if (!hInternet) {
113+ return " " ;
114+ }
115+
116+ HINTERNET hFile = InternetOpenUrlA (hInternet, url.c_str (), NULL , 0 , INTERNET_FLAG_RELOAD , 0 );
117+ if (!hFile) {
118+ InternetCloseHandle (hInternet);
119+ return " " ;
120+ }
121+
122+ std::string result;
123+ char buffer[4096 ];
124+ DWORD bytesRead;
125+
126+ do {
127+ if (InternetReadFile (hFile, buffer, sizeof (buffer), &bytesRead) && bytesRead > 0 ) {
128+ result.append (buffer, bytesRead);
129+ }
130+ else {
131+ break ;
132+ }
133+ } while (bytesRead > 0 );
134+
135+ InternetCloseHandle (hFile);
136+ InternetCloseHandle (hInternet);
137+
138+ return result;
139+ }
140+ bool isSet (nlohmann::json jsonData, std::string key) {
141+ return jsonData.find (key) != jsonData.end ();
142+ }
143+ nlohmann::json GetJsonFromFile (const std::wstring& filename) {
110144 std::ifstream file (filename);
111145 if (!file.is_open ()) {
112146 displayedText = L" Failed to open " + filename;
113147 return false ; // Couldn't find file
114148 }
115-
149+ nlohmann::json jsonData;
150+ file >> jsonData;
151+ return jsonData;
152+ }
153+ nlohmann::json GetJsonFromURL (const std::string& url) {
154+ std::string f = FetchURL (url);
155+ nlohmann::json jsonData = nlohmann::json::parse (f);
156+ return jsonData;
157+ }
158+ bool LoadDataFromJson (nlohmann::json jsonData, bool justShortcuts = false ) {
116159 // Count how many entries we load from the JSON
117160 unsigned int count = 0 ;
118161
119162 try {
120- nlohmann::json jsonData;
121- file >> jsonData;
122163 prefix = Utf8ToWstring (jsonData[" prefix" ]);
123164 version = Utf8ToWstring (jsonData[" version" ]);
124- shortcuts.clear (); // Make sure you're clearing old shortcuts
125165
126166 // If the JSON contains goto_character we pull it out
127- if (jsonData.find (" goto_character" ) != jsonData.end ()) {
128- gotochar = Utf8ToWstring (jsonData[" goto_character" ]);
129- }
167+ if (!justShortcuts) { // this if statement is for when we are using a json from the web, because then we just want the shortcuts
168+ if (isSet (jsonData, " goto_character" )) {
169+ gotochar = Utf8ToWstring (jsonData[" goto_character" ]);
170+ }
130171
131- if (jsonData.find (" start_minimized" ) != jsonData.end ()) {
132- START_MINIMIZED = jsonData[" start_minimized" ];
172+ if (isSet (jsonData, " start_minimized" )) {
173+ START_MINIMIZED = jsonData[" start_minimized" ];
174+ }
175+ if (isSet (jsonData, " enable_logging" )) {
176+ enableLogging = jsonData[" enable_logging" ];
177+ }
178+ if (isSet (jsonData, " ternary" )) {
179+ easterEgg = true ;
180+ }
133181 }
134182 for (auto & el : jsonData[" shortcuts" ].items ()) {
135183 std::wstring key = Utf8ToWstring (el.key ());
@@ -138,34 +186,49 @@ bool LoadDataFromJson(const std::wstring& filename) {
138186
139187 count++;
140188 }
141- if (jsonData.find (" enable_logging" ) != jsonData.end ()) {
142- enableLogging = jsonData[" enable_logging" ];
143- }
144- if (jsonData.find (" ternary" ) != jsonData.end ()) {
145- easterEgg = true ;
146- }
147189 UpdateDisplayedTextFromShortcuts ();
148190 }
149191 catch (const std::exception& ex) {
150192 std::string err = " JSON Parse Error: " ;
151193 err += ex.what ();
152194 displayedText = std::wstring (err.begin (), err.end ());
195+ return false ;
153196 }
154197
155198 if (g_hWnd) {
156199 InvalidateRect (g_hWnd, NULL , TRUE );
157200 UpdateWindow (g_hWnd);
158201 }
159202
160- // Log how many shortcuts we found
161- if (enableLogging) {
162- char buffer[100 ];
163- snprintf (buffer, sizeof (buffer), " Loaded %u shortcuts from configuration" , count);
164- log_line (buffer);
165- }
166-
167203 return true ; // Sucessfully found file, may or may not have been loaded. Maybe make this function return errors instead of just a bool
168204}
205+ void LoadShortcuts () {
206+ shortcuts.clear ();
207+ nlohmann::json jsonData = GetJsonFromFile (json_path);
208+ bool good = LoadDataFromJson (jsonData);
209+ if (!good) {
210+ log_line (" Json file not found, creating one..." );
211+ std::ofstream templateJSON (" shortcuts.json" );
212+ templateJSON << json_default_data;
213+ templateJSON.close ();
214+ jsonData = GetJsonFromFile (json_path);
215+ LoadDataFromJson (jsonData);
216+ }
217+ else {
218+ log_line (" Json file found!" );
219+ }
220+ if (isSet (jsonData, " external_url" )) {
221+ log_line (" External url detected, attempting to load" );
222+ nlohmann::json webJson = GetJsonFromURL (jsonData[" external_url" ]);
223+ if (webJson.empty ()) {
224+ log_line (" Error loading Json from the web, check if the website is typed properly" );
225+ }
226+ else {
227+ LoadDataFromJson (webJson, true );
228+ log_line (" Json loaded successfully!" );
229+ }
230+ }
231+ }
169232std::string wstringToString (const std::wstring& wstr) {
170233 // Create a string with enough space to hold the converted characters
171234 std::string str (wstr.begin (), wstr.end ());
@@ -188,6 +251,8 @@ std::wstring GetExecutableDirectory() {
188251 return fullPath; // fallback to full path if no slash found
189252}
190253
254+
255+
191256// This is where the keypress is captured and compared against the list of shortcuts
192257static LRESULT CALLBACK LowLevelKeyboardProc (int nCode, WPARAM wParam, LPARAM lParam) {
193258 if (nCode == HC_ACTION ) {
@@ -301,7 +366,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
301366 log_line (" OpenKeys started (You can disable logging by setting enable_logging to false in your json)" );
302367 }
303368 log_line (" OpenKeys started" );
304-
305369 }
306370
307371 // Initialize global strings
@@ -433,14 +497,7 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
433497 hFont = CreateFontIndirect (&lf);
434498
435499 // Load Shortcuts
436- bool good = LoadDataFromJson (json_path);
437- if (!good) { // If a shortcuts file is not found, create one
438- std::ofstream templateJSON (" shortcuts.json" );
439- templateJSON << json_default_data;
440- templateJSON.close ();
441- LoadDataFromJson (json_path);
442- }
443-
500+ LoadShortcuts ();
444501
445502 if (!START_MINIMIZED ) {
446503 ShowWindow (hWnd, nCmdShow);
@@ -476,7 +533,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
476533 break ;
477534 case IDM_REFRESH_BUTTON :
478535 log_line (" Reloaded JSON file" );
479- LoadDataFromJson (json_path );
536+ LoadShortcuts ( );
480537 break ;
481538 case IDM_EXIT :
482539 DestroyWindow (hWnd);
0 commit comments