diff --git a/main.py b/main.py index 41edd68..61af16a 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,6 @@ import os +import sys +import platform import hashlib import json import requests @@ -10,6 +12,8 @@ import subprocess import re # --- КОНФИГУРАЦИЯ --- +APP_VERSION = "v1.1.6" # Укажите здесь вашу текущую версию +UPDATE_API_URL = "https://git.borderban.ru/api/v1/repos/BorderBan/client-py/releases/latest" SERVER_URL = "https://server1.borderban.ru/mods/" CONFIG_FILE = Path.home() / ".factorio_sync_config.json" @@ -29,10 +33,81 @@ def get_file_hash(filepath): sha256_hash.update(byte_block) return sha256_hash.hexdigest() +def check_and_update(root): + # Выполняем автообновление только если программа запущена как скомпилированный бинарник + if not getattr(sys, 'frozen', False): + return + + exe_path = sys.executable + old_exe_path = exe_path + ".old" + + # Очистка мусора: удаляем старый файл, оставшийся от предыдущего обновления + if os.path.exists(old_exe_path): + try: + os.remove(old_exe_path) + except Exception: + pass + + try: + # Получаем данные о последнем релизе + response = requests.get(UPDATE_API_URL, timeout=5) + response.raise_for_status() + release_data = response.json() + latest_version = release_data.get("tag_name") + + # Проверяем, нужна ли загрузка + if not latest_version or latest_version == APP_VERSION: + return + + # Определяем имя нужного ассета в зависимости от ОС + system = platform.system().lower() + asset_name = None + if system == "windows": + asset_name = "factorio-mod-sync-windows.exe" + elif system == "linux": + asset_name = "factorio-mod-sync-linux" + + if not asset_name: + return + + download_url = next((asset.get("browser_download_url") for asset in release_data.get("assets", []) if asset.get("name") == asset_name), None) + + if not download_url: + return + + # Показываем небольшое окно с прогрессом + update_win = tk.Toplevel(root) + update_win.title("Обновление") + update_win.geometry("350x100") + tk.Label(update_win, text=f"Обнаружена новая версия ({latest_version}).\nЗагрузка обновления...\nПожалуйста, подождите.").pack(expand=True) + update_win.update() + + new_exe_path = exe_path + ".new" + with requests.get(download_url, stream=True, timeout=60) as r: + r.raise_for_status() + with open(new_exe_path, 'wb') as f: + for chunk in r.iter_content(chunk_size=8192): + f.write(chunk) + + if system == "linux": + os.chmod(new_exe_path, 0o755) + + # Подменяем исполняемый файл (Windows позволяет переименовать запущенный файл) + os.replace(exe_path, old_exe_path) + os.replace(new_exe_path, exe_path) + + # Перезапускаем новую версию и выходим из текущей + subprocess.Popen([exe_path] + sys.argv[1:]) + sys.exit(0) + + except Exception as e: + print(f"Ошибка проверки или установки обновления: {e}") + # При ошибке просто продолжаем обычный запуск + class SyncApp: def __init__(self, root): self.root = root - self.root.title("Factorio Mod Sync") + self.root.title(f"Factorio Mod Sync {APP_VERSION}") self.root.geometry("500x350") self.config = self.load_config() @@ -240,5 +315,8 @@ class SyncApp: if __name__ == "__main__": root = tk.Tk() + root.withdraw() # Скрываем основное окно на время проверки обновления + check_and_update(root) + root.deiconify() # Показываем основное окно app = SyncApp(root) root.mainloop()