3232
3333#include " engine_update_label.h"
3434
35+ #include " core/io/dir_access.h"
3536#include " core/io/json.h"
3637#include " core/os/time.h"
3738#include " editor/editor_settings.h"
@@ -47,12 +48,56 @@ bool EngineUpdateLabel::_can_check_updates() const {
4748}
4849
4950void EngineUpdateLabel::_check_update () {
51+ if (!_can_check_updates ()) {
52+ _set_status (UpdateStatus::OFFLINE);
53+ return ;
54+ }
55+
5056 checked_update = true ;
57+
58+ if (ratelimit_remaining == UINT64_MAX && ratelimit_reset == UINT64_MAX) {
59+ Ref<FileAccess> gh_ratelimit_file = FileAccess::open (OS::get_singleton ()->get_data_path ().path_join (" gh_ratelimit" ), FileAccess::READ);
60+ if (gh_ratelimit_file.is_valid () && gh_ratelimit_file->is_open ()) {
61+ ratelimit_remaining = gh_ratelimit_file->get_64 ();
62+ ratelimit_reset = gh_ratelimit_file->get_64 ();
63+ } else {
64+ ratelimit_remaining = UINT64_MAX;
65+ ratelimit_reset = 0 ;
66+ }
67+ }
68+
69+ uint64_t current_epoch = Time::get_singleton ()->get_unix_time_from_system ();
70+ if (ratelimit_remaining <= 0 && ratelimit_reset >= current_epoch) {
71+ _set_status (UpdateStatus::UP_TO_DATE);
72+ get_tree ()->create_timer (current_epoch - ratelimit_reset + 1 , false , true )->connect (" timeout" , callable_mp (this , &EngineUpdateLabel::_check_update));
73+ return ;
74+ }
75+
5176 _set_status (UpdateStatus::BUSY);
52- http->request (" https://redotengine.org/versions. json" );
77+ http->request (" https://api.github.com/repos/Redot-Engine/redot-engine/releases " , { " Accept: application/vnd.github+ json" , " X-GitHub-Api-Version:2022-11-28 " } );
5378}
5479
5580void EngineUpdateLabel::_http_request_completed (int p_result, int p_response_code, const PackedStringArray &p_headers, const PackedByteArray &p_body) {
81+ for (const String &header_text : p_headers) {
82+ const String header = header_text.to_lower ();
83+ if (header.begins_with (" x-ratelimit-remaining" )) {
84+ ratelimit_remaining = header.get_slice (" :" , 1 ).to_int ();
85+ } else if (header.begins_with (" x-ratelimit-reset" ) || header.begins_with (" retry-after" )) {
86+ ratelimit_reset = header.get_slice (" :" , 1 ).to_int ();
87+ }
88+ }
89+
90+ const String gh_ratelimit_path = OS::get_singleton ()->get_data_path ().path_join (" gh_ratelimit" );
91+ if (ratelimit_remaining == 0 ) {
92+ Ref<FileAccess> gh_ratelimit_file = FileAccess::open (gh_ratelimit_path, FileAccess::WRITE);
93+ if (gh_ratelimit_file.is_valid () && gh_ratelimit_file->is_open ()) {
94+ gh_ratelimit_file->store_64 (ratelimit_remaining);
95+ gh_ratelimit_file->store_64 (ratelimit_reset);
96+ }
97+ } else if (FileAccess::exists (gh_ratelimit_path)) {
98+ DirAccess::remove_absolute (gh_ratelimit_path);
99+ }
100+
56101 if (p_result != OK) {
57102 _set_status (UpdateStatus::ERROR);
58103 _set_message (vformat (TTR (" Failed to check for updates. Error: %d." ), p_result), theme_cache.error_color );
@@ -96,7 +141,14 @@ void EngineUpdateLabel::_http_request_completed(int p_result, int p_response_cod
96141 for (const Variant &data_bit : version_array) {
97142 const Dictionary version_info = data_bit;
98143
99- const String base_version_string = version_info.get (" name" , " " );
144+ const String bare_tag_name = (String)version_info.get (" tag_name" , " " );
145+ const PackedStringArray tag_bits = bare_tag_name.split (" -" );
146+
147+ if (tag_bits.size () < 3 ) {
148+ continue ;
149+ }
150+
151+ const String base_version_string = tag_bits[1 ];
100152 const PackedStringArray version_bits = base_version_string.split (" ." );
101153
102154 if (version_bits.size () < 2 ) {
@@ -121,15 +173,9 @@ void EngineUpdateLabel::_http_request_completed(int p_result, int p_response_cod
121173 continue ;
122174 }
123175
124- const Array releases = version_info.get (" releases" , Array ());
125- if (releases.is_empty ()) {
126- continue ;
127- }
128-
129- const Dictionary newest_release = releases[0 ];
130- const String release_string = newest_release.get (" name" , " unknown" );
176+ const String release_string = tag_bits[2 ];
131177
132- int release_index;
178+ int release_index = DEV_VERSION ;
133179 VersionType release_type = _get_version_type (release_string, &release_index);
134180
135181 if (minor > current_minor || patch > current_patch) {
@@ -274,11 +320,7 @@ void EngineUpdateLabel::_notification(int p_what) {
274320 } break ;
275321
276322 case NOTIFICATION_READY: {
277- if (_can_check_updates ()) {
278- _check_update ();
279- } else {
280- _set_status (UpdateStatus::OFFLINE);
281- }
323+ _check_update ();
282324 } break ;
283325 }
284326}
@@ -298,7 +340,7 @@ void EngineUpdateLabel::pressed() {
298340 } break ;
299341
300342 case UpdateStatus::UPDATE_AVAILABLE: {
301- OS::get_singleton ()->shell_open (" https://redotengine.org/download/archive/ " + available_newer_version);
343+ OS::get_singleton ()->shell_open (" https://github.com/Redot-Engine/redot-engine/releases/tag/redot- " + available_newer_version);
302344 } break ;
303345
304346 default : {
0 commit comments