95 lines
3.2 KiB
GDScript
95 lines
3.2 KiB
GDScript
class_name UpdateManager
|
|
extends Node
|
|
|
|
signal update_available(info: Dictionary)
|
|
|
|
const RELEASES_API := "https://git.dominicspringer.de/api/v1/repos/Emporex/Void-Bastion-Releases/releases"
|
|
const PUBLIC_RELEASE_BASE := "https://git.dominicspringer.de/Emporex/Void-Bastion-Releases/releases/tag/"
|
|
|
|
var _request: HTTPRequest
|
|
|
|
|
|
func _ready() -> void:
|
|
if DisplayServer.get_name() == "headless" or Engine.is_editor_hint():
|
|
return
|
|
_request = HTTPRequest.new()
|
|
add_child(_request)
|
|
_request.request_completed.connect(_on_request_completed)
|
|
call_deferred("check_for_update")
|
|
|
|
|
|
func check_for_update() -> void:
|
|
if _request == null or _request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
|
return
|
|
_request.request(RELEASES_API, ["Accept: application/json", "User-Agent: Void-Bastion/%s" % _current_version()])
|
|
|
|
|
|
func _on_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
|
if result != HTTPRequest.RESULT_SUCCESS or response_code < 200 or response_code >= 300:
|
|
return
|
|
var releases = JSON.parse_string(body.get_string_from_utf8())
|
|
if not releases is Array:
|
|
return
|
|
for release in releases:
|
|
if not release is Dictionary or bool(release.get("draft", false)):
|
|
continue
|
|
var version := str(release.get("tag_name", "")).trim_prefix("v")
|
|
if version.is_empty() or not _is_newer_version(version, _current_version()):
|
|
return
|
|
var download_url := PUBLIC_RELEASE_BASE + "v" + version
|
|
var wanted_extension := ".apk" if OS.get_name() == "Android" else ".exe"
|
|
for asset in release.get("assets", []):
|
|
if asset is Dictionary and str(asset.get("name", "")).to_lower().ends_with(wanted_extension):
|
|
download_url = str(asset.get("browser_download_url", download_url))
|
|
break
|
|
update_available.emit({
|
|
"version": version,
|
|
"name": str(release.get("name", version)),
|
|
"url": download_url
|
|
})
|
|
return
|
|
|
|
|
|
func _current_version() -> String:
|
|
return str(ProjectSettings.get_setting("application/config/version", "0.0.0"))
|
|
|
|
|
|
func _is_newer_version(remote: String, local: String) -> bool:
|
|
var remote_parts := _version_parts(remote)
|
|
var local_parts := _version_parts(local)
|
|
for index in 3:
|
|
if remote_parts[index] != local_parts[index]:
|
|
return remote_parts[index] > local_parts[index]
|
|
var remote_suffix: String = remote_parts[3]
|
|
var local_suffix: String = local_parts[3]
|
|
if remote_suffix.is_empty():
|
|
return not local_suffix.is_empty()
|
|
if local_suffix.is_empty():
|
|
return false
|
|
return _prerelease_weight(remote_suffix) > _prerelease_weight(local_suffix)
|
|
|
|
|
|
func _version_parts(value: String) -> Array:
|
|
var normalized := value.trim_prefix("v").strip_edges().to_lower()
|
|
var sections := normalized.split("-", true, 1)
|
|
var numbers := sections[0].split(".")
|
|
return [
|
|
int(numbers[0]) if numbers.size() > 0 else 0,
|
|
int(numbers[1]) if numbers.size() > 1 else 0,
|
|
int(numbers[2]) if numbers.size() > 2 else 0,
|
|
sections[1] if sections.size() > 1 else ""
|
|
]
|
|
|
|
|
|
func _prerelease_weight(value: String) -> int:
|
|
var stage := 0
|
|
if value.begins_with("beta"):
|
|
stage = 100000
|
|
elif value.begins_with("rc"):
|
|
stage = 200000
|
|
var sequence := 0
|
|
for part in value.split("."):
|
|
if part.is_valid_int():
|
|
sequence = int(part)
|
|
return stage + sequence
|