|
@@ -5,21 +5,165 @@ var kinds = {
|
|
|
"color": ""
|
|
|
}
|
|
|
|
|
|
+var downloads = {}
|
|
|
+var downloading = false
|
|
|
+
|
|
|
+signal file_downloaded
|
|
|
+signal downloads_finished
|
|
|
+signal stats_updated
|
|
|
+signal downloads_started
|
|
|
+
|
|
|
+export(bool) var blind_mode : bool = false
|
|
|
+
|
|
|
+var _headers : Array = []
|
|
|
+
|
|
|
+var _last_method : int
|
|
|
+var _ssl : bool = false
|
|
|
+
|
|
|
+var _file := File.new()
|
|
|
+
|
|
|
+var _timer : float = 0.0
|
|
|
+
|
|
|
+var currentDownload : Download
|
|
|
+class Download:
|
|
|
+ var _file_name : String
|
|
|
+ var _file_size : float
|
|
|
+ var _current_url : String
|
|
|
+ var _kind : String
|
|
|
+ var _downloaded_percent : float = 0
|
|
|
+ var _downloaded_size : float = 0
|
|
|
+
|
|
|
+func _init() -> void:
|
|
|
+ set_process(false)
|
|
|
+ connect("request_completed", self, "_on_request_completed")
|
|
|
+
|
|
|
+func get_stats() -> Download:
|
|
|
+ return currentDownload
|
|
|
+
|
|
|
+func _reset() -> void:
|
|
|
+ currentDownload = Download.new()
|
|
|
+
|
|
|
+func _downloads_done() -> void:
|
|
|
+ set_process(false)
|
|
|
+ _update_stats()
|
|
|
+ _file.close()
|
|
|
+ emit_signal("downloads_finished", currentDownload)
|
|
|
+ _reset()
|
|
|
+ downloading = false
|
|
|
+
|
|
|
+func _update_stats() -> void:
|
|
|
+ if blind_mode == false:
|
|
|
+ _calculate_percentage()
|
|
|
+ emit_signal("stats_updated",currentDownload)
|
|
|
+
|
|
|
+func _process(delta):
|
|
|
+ if not downloading:
|
|
|
+ if len(downloads) == 0:
|
|
|
+ set_process(false)
|
|
|
+ return
|
|
|
+ for kind in downloads:
|
|
|
+ for file in downloads[kind]:
|
|
|
+ var dl = downloads[kind][file]
|
|
|
+ currentDownload = dl
|
|
|
+ _download()
|
|
|
+ _timer += delta
|
|
|
+ if _timer > 1:
|
|
|
+ _update_stats()
|
|
|
+ _timer = 0.0
|
|
|
+
|
|
|
+func _download():
|
|
|
+ ensureFolder(currentDownload._kind)
|
|
|
+ download_file = currentDownload._file_name
|
|
|
+ .connect("stats_updated", Messenger, "_on_statusUpdate")
|
|
|
+ _send_head_request()
|
|
|
+ print("downloading %s" %currentDownload._file_name)
|
|
|
+ downloading = true
|
|
|
+
|
|
|
func ensureFolder(kind):
|
|
|
var dir = Directory.new()
|
|
|
dir.open("user://")
|
|
|
if not dir.dir_exists(kind):
|
|
|
dir.make_dir(kind)
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
func download(file, kind):
|
|
|
+ set_process(true)
|
|
|
if not kinds.has(kind):
|
|
|
print("don't know kind %s"%kind)
|
|
|
return
|
|
|
+ if not downloads.has(kind):
|
|
|
+ downloads[kind] = {}
|
|
|
+ if downloads[kind].has(file):
|
|
|
+ return
|
|
|
+ var download = Download.new()
|
|
|
+ download._file_name = "user://%s/%s"%[kind, file]
|
|
|
+ download._current_url = make_filename(kind, file)
|
|
|
+ download._kind = kind
|
|
|
+ downloads[kind][file] = download
|
|
|
+
|
|
|
+func make_filename(kind, file):
|
|
|
+ return kinds[kind]%file
|
|
|
+
|
|
|
+func _send_head_request() -> void:
|
|
|
+ # The HEAD method only gets the head and not the body. Therefore, doesn't
|
|
|
+ # download the file.
|
|
|
+ request(currentDownload._current_url, _headers, _ssl, HTTPClient.METHOD_HEAD)
|
|
|
+ _last_method = HTTPClient.METHOD_HEAD
|
|
|
+
|
|
|
+
|
|
|
+func _send_get_request() -> void:
|
|
|
+ var error = request(currentDownload._current_url, _headers, _ssl, HTTPClient.METHOD_GET)
|
|
|
+ if error == OK:
|
|
|
+ emit_signal("downloads_started")
|
|
|
+ _last_method = HTTPClient.METHOD_GET
|
|
|
+ set_process(true)
|
|
|
+
|
|
|
+ elif error == ERR_INVALID_PARAMETER:
|
|
|
+ print("Given string isn't a valid url ")
|
|
|
+ elif error == ERR_CANT_CONNECT:
|
|
|
+ print("Can't connect to host")
|
|
|
+
|
|
|
+func _on_request_completed(p_result,
|
|
|
+ _p_response_code,
|
|
|
+ p_headers,
|
|
|
+ _p_body) -> void:
|
|
|
+ if p_result == RESULT_SUCCESS:
|
|
|
+ if _last_method == HTTPClient.METHOD_HEAD and blind_mode == false:
|
|
|
+ var regex = "(?i)content-length: [0-9]*"
|
|
|
+ var size = _extract_regex_from_header(regex, p_headers.join(' '))
|
|
|
+ size = size.replace("Content-Length: ", "")
|
|
|
+ currentDownload._file_size = size.to_float()
|
|
|
+ _send_get_request()
|
|
|
+
|
|
|
+ elif _last_method == HTTPClient.METHOD_HEAD and blind_mode == true:
|
|
|
+ _send_get_request()
|
|
|
+
|
|
|
+ elif _last_method == HTTPClient.METHOD_GET:
|
|
|
+ emit_signal("file_downloaded", currentDownload)
|
|
|
+ Messenger._on_file_downloaded(currentDownload)
|
|
|
+ downloads[currentDownload._kind].erase(currentDownload._file_name)
|
|
|
+ if len(downloads[currentDownload._kind]) == 0:
|
|
|
+ downloads.erase(currentDownload._kind)
|
|
|
+ if len(downloads) == 0:
|
|
|
+ _downloads_done()
|
|
|
+
|
|
|
+ elif p_result == RESULT_DOWNLOAD_FILE_CANT_OPEN:
|
|
|
+ push_error("Download cannot open file %s" %currentDownload._file_name)
|
|
|
+ else:
|
|
|
+ print("HTTP Request error: ", p_result)
|
|
|
+
|
|
|
+func _calculate_percentage() -> void:
|
|
|
+ var error : int
|
|
|
+ error = _file.open(download_file, File.READ)
|
|
|
+
|
|
|
+ if error == OK:
|
|
|
+ currentDownload._downloaded_size = _file.get_len()
|
|
|
+ currentDownload._downloaded_percent = (currentDownload._downloaded_size / currentDownload._file_size) *100
|
|
|
+
|
|
|
+func _extract_regex_from_header(p_regex : String,
|
|
|
+ p_header : String) -> String:
|
|
|
+ var regex = RegEx.new()
|
|
|
+ regex.compile(p_regex)
|
|
|
|
|
|
- ensureFolder(kind)
|
|
|
- var url = kinds[kind]%file
|
|
|
- download_file = "user://%s/%s".format([kind, file])
|
|
|
- # Perform a GET request.
|
|
|
- var error = request(url)
|
|
|
- if error != OK:
|
|
|
- push_error("An error occurred in the HTTP request.")
|
|
|
+ var result = regex.search(p_header)
|
|
|
+ return result.get_string()
|