import os import sys import hashlib import requests import urllib.parse from urllib.request import urlretrieve def get_file_list(url): url = "https://apidgp-gameplayer.games.dmm.com" + url print("Retrieving file list from " + url) result = requests.get(url) result.raise_for_status() data = result.json()["data"] return data["domain"], data["file_list"] def get_file_hash(file_path): if not os.path.exists(file_path): return None with open(file_path, "rb") as f: file_hash = hashlib.md5() while chunk := f.read(8192): file_hash.update(chunk) return file_hash.hexdigest() def update_game(game_path, files_url, files_param): print("Updating game") server_url, server_files = get_file_list(files_url) server_file_dict = {file["local_path"]: file for file in server_files} local_files = [os.path.join(dp, f).replace("\\", "/") for dp, dn, filenames in os.walk(game_path) for f in filenames] local_file_dict = {"/" + os.path.relpath(r, game_path).replace("\\", "/"): {"abs_path":r, "hash":""} for r in local_files} files_to_download = [] files_to_delete = [] for server_file_key in server_file_dict.keys(): server_file = server_file_dict[server_file_key] if server_file_key in local_file_dict: local_file = local_file_dict[server_file_key] if server_file["force_delete_flg"]: files_to_delete.append(local_file["abs_path"]) else: local_file["hash"] = get_file_hash(local_file["abs_path"]) if server_file["check_hash_flg"] and local_file["hash"] == server_file["hash"]: continue download_url = urllib.parse.urljoin(server_url, server_file["path"]) + files_param download_path = game_path.replace("\\", "/") + server_file_key files_to_download.append({"url":download_url, "path":download_path}) else: download_url = urllib.parse.urljoin(server_url, server_file["path"]) + files_param download_path = game_path.replace("\\", "/") + server_file_key files_to_download.append({"url":download_url, "path":download_path}) print("Files to download:", len(files_to_download)) count = len(files_to_download) if count > 0: index = 0 max_len = 0 def show(j, downloaded, total_size): nonlocal max_len x = int(40*j/count) string = "Downloading: [{}{}] {}/{} ({}/{})".format("#"*x, "."*(40-x), j, count, min(downloaded,total_size), total_size) max_len = max(len(string), max_len) print(string.ljust(max_len, ' '), end='\r', file=sys.stdout, flush=True) def show_progress(block_num, block_size, total_size): downloaded = block_num * block_size show(index + 1, downloaded, total_size) retries = 3 show(0, 0, 0) while index < len(files_to_download): try: file = files_to_download[index] url, path = file["url"], file["path"] os.makedirs(os.path.dirname(path), exist_ok=True) urlretrieve(url, path, reporthook=show_progress) index += 1 retries = 3 except: retries -= 1 if retries == 0: print(f'Retry for file {file["url"]} failed 3 times') return False print("\n", flush=True, file=sys.stdout) # #files_to_delete is unused until fully tested # for file in files_to_delete: # os.remove(file) return True