From ff2984aadefec3d6c1f6395f8ad9f6881fd61a39 Mon Sep 17 00:00:00 2001 From: Mirvis <108653332+Kexi8BiT@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:23:39 +0500 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=B0=D0=BF=D0=B8=20=D0=B8=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BD=D0=B5=D0=BA=D0=BE?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D1=8B=D1=85=20=D0=BD=D0=B0=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B5=D0=BA,=20=D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D1=81=D0=B8=D1=81=D1=82?= =?UTF-8?q?=D0=B5=D0=BC=D0=B0=20=D1=85=D0=B5=D1=88=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/icons/gitdark.png | Bin 0 -> 584 bytes assets/logo_.png | Bin 0 -> 15035 bytes hashsystem.py | 60 +++++++++++++++++++++++++++++++++++++++ internets.py | 35 ++++++++++++++++++++++- main.py | 11 +++++-- navifation.py | 34 +++++++++++++--------- settings_page.py | 40 +++++++++++++++++++++----- ui.py | 26 +++++++++++++---- 8 files changed, 175 insertions(+), 31 deletions(-) diff --git a/assets/icons/gitdark.png b/assets/icons/gitdark.png index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0dafe28ce7ee62c6b5620e8d585396b6a93b11ab 100644 GIT binary patch literal 584 zcmV-O0=NB%P)8-WeN2kf-5E-aXpTub zDTbrn)BYVKf~N}=3u}jP-tieuLc2?99)VHxyJWYS@TojAoIuh_J(va?GU~|I_w?KoAHuyVRaJZ0kl6A{6U)Xx+L9F*rgDxP7u(|?GMbUMC6 zAOVM{BR-RT0})j?*YgP5sLG>&!(Vc30w-LvTj1^EG&X@AZ{Gw4QUL=ixzICnD*grV W$UTzx=t#`~0000ggG()#^gP?SSG{`;Rd!O%n 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 P>JvF>MX53gqi_EMjnfSI literal 0 HcmV?d00001 diff --git a/hashsystem.py b/hashsystem.py index e69de29..0fef90d 100644 --- a/hashsystem.py +++ b/hashsystem.py @@ -0,0 +1,60 @@ +import hashlib +import os +import requests + +def file_hash_(file_path: str) -> str: + """ + Возвращает md5 hash файла по его пути + ```python + path = "/path/to/file.txt" + hash_md5 = file_hash(path) + print(hash_md5) + ``` + :param file_path: + :return: + """ + hash_md5 = hashlib.md5() + try: + with open(file_path, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + hash_md5.update(chunk) + return hash_md5.hexdigest() + except: + return "404" + + +def is_directory(path: str) -> bool: + return os.path.isdir(path) +def files_update(path_to_games_dir: str, game_id: str, files_hashs) -> None: + error_files = [] + file_names = [] + for file in files_hashs: + print(f"- {game_id}/{file['name']}...", end="") + if file['type'] == "dir": + if not os.path.isdir(f"{path_to_games_dir}/{game_id}/{file['name']}"): + os.mkdir(f"{path_to_games_dir}/{game_id}/{file['name']}") + files_update("games", f"{game_id}/{file['name']}", file['files']) + continue + file_names.append(file['name']) + file_hash = file_hash_(f"{path_to_games_dir}/{game_id}/{file['name']}") + if not file_hash == "404": + if file_hash == file["hash"]: + print("OK", file_hash) + else: + print("FAIL") + file['local_hash'] = file_hash + error_files.append(file) + else: + print("404") + error_files.append(file) + + print("---------------------------") + for file in error_files: + print(f"- {file['name']}...", end="") + try: + with open(f"{path_to_games_dir}/{game_id}/{file['name']}", "wb") as f: + f.write(requests.get(file['url']).content) + print("DONE!") + except: + print("FAIL!") + print("=============================") \ No newline at end of file diff --git a/internets.py b/internets.py index f5cba6c..e84e5a9 100644 --- a/internets.py +++ b/internets.py @@ -4,8 +4,41 @@ def get_ip(): return requests.get("https://ipinfo.io/ip").text -def get_updates(only_last:bool = False, game_id = ""): + + +# Эта функция возвращает обнавления указанной игры +def get_updates(only_last:bool = False, game_id = "") -> []: news = requests.get(f"http://127.0.0.1:8000/updates/{game_id}").json() if only_last: return news[0] return news + + +#Функция для проверки работы нового api (пока что только существование потом добавлю проверку всех ендпоинтов) +def check_api(url: str) -> bool: + """ + Функция для проверки работы нового api + ```python + check_api("http://127.0.0.1:8000") -> Fasle/TRue + ``` + :param url: + :return: + """ + try: + req = requests.get(f"{url}/online") + if req.status_code == 200: + req_json = req.json() + print(req_json) + if "status" in req_json: + print("API работает") + return True + + else: + print("в json нет online") + return False + else: + print("не 200") + return False + except Exception as e: + print(e) + return False diff --git a/main.py b/main.py index d18e79a..71e8136 100644 --- a/main.py +++ b/main.py @@ -8,6 +8,7 @@ from settings_page import go_to_settings, get_settings_page from ui import interface_button, interface_switch from game_run_page import GamesPage +from home_page import get_main_page_home sound = True launcher_name = "PixelLauncher" @@ -35,16 +36,20 @@ def main(page: ft.Page): duration=500, reverse_duration=500, ) + def go_to_home(e): + content.content = get_main_page_home(page) + content.update() + + HOME = ft.Container(get_main_page_home(page)) GAMES = ft.Container(get_games_page(page, content)) SETTINGS = ft.Container(get_settings_page(page)) - content.content = GAMES - + content.content = SETTINGS - drag_area, nav_left = get_elements(page, height, lambda e: go_to_main(content, page), lambda _: go_to_settings(content, page)) + drag_area, nav_left = get_elements(page, height, lambda e: go_to_home(page), lambda _: go_to_settings(content, page), lambda e: go_to_main(content, page)) page.add(drag_area) page.add(ft.Row([nav_left, content])) diff --git a/navifation.py b/navifation.py index 30ebb64..66155f6 100644 --- a/navifation.py +++ b/navifation.py @@ -1,31 +1,37 @@ import flet as ft -from sound_effect import BoopSound - +from PIL import Image +import io +import base64 +from ui import navigation_button launcher_name = "PixelLauncher" +def colorize_image(rgb, image_path): + image = Image.open(image_path).convert('RGB') + colored_image = Image.new('RGB', image.size, rgb) + colored_image = Image.blend(colored_image, image, 0.5) + byte_stream = io.BytesIO() + colored_image.save(byte_stream, format='PNG') + byte_stream.seek(0) + base64_image = base64.b64encode(byte_stream.getvalue()).decode('utf-8') + return base64_image -navigation_button = { - "width": 250, - "height": 45, - "bgcolor": ft.colors.TRANSPARENT, - "color": ft.colors.WHITE, - "icon_color": ft.colors.WHITE, - "style": ft.ButtonStyle(shape=ft.RoundedRectangleBorder(radius=0), bgcolor=ft.colors.TRANSPARENT, - surface_tint_color=ft.colors.TRANSPARENT, shadow_color=ft.colors.TRANSPARENT, overlay_color=ft.colors.with_opacity(0.1, ft.colors.WHITE)), -} +logo_path = "assets/logo_.png" +rgb = (100, -5, -2) -def get_elements(page, height, main, settings): +def get_elements(page, height, main, settings, library): def close(e): page.window_minimized = True page.update() + + image_base64 = colorize_image(rgb, logo_path) navigation = ft.Container(ft.Column([ft.Container( - ft.Image("assets/logo.png", width=150), + ft.Image(src_base64=image_base64, width=150, border_radius=30), margin=ft.margin.only(bottom=40, top=20), on_click=lambda _: page.launch_url("https://www.sovagroup.one"), tooltip="site:https://www.sovagroup.one"), ft.ElevatedButton("Главная", **navigation_button, on_click=main), - ft.ElevatedButton("Библиотека", **navigation_button, on_click=lambda _: BoopSound(page).play()), + ft.ElevatedButton("Библиотека", **navigation_button, on_click=library), ft.ElevatedButton("Настройки", **navigation_button, on_click=settings), ft.Divider(), ft.ElevatedButton("Оффициальный лаунчер", **navigation_button, icon=ft.icons.OPEN_IN_NEW, on_click=lambda _: page.launch_url("https://www.sovagroup.one/sovalaucher"), tooltip="sovagroup:official-launcher"), diff --git a/settings_page.py b/settings_page.py index 90eed02..99f0792 100644 --- a/settings_page.py +++ b/settings_page.py @@ -1,30 +1,56 @@ import flet as ft from sound_effect import BoopSound from ui import interface_button, interface_switch, interface_input +from internets import check_api - -def go_to_settings(content, page): +def go_to_settings(content, page: ft.Page): boop = BoopSound(page) boop.play() content.content = get_settings_page(page) content.update() def get_settings_page(page: ft.Page): + cdn = page.client_storage.get("cdn_url") + if cdn == None: + page.client_storage.set("cdn_url", "http://127.0.0.1:8000") + print("CDN - УСТАНОВЛЕННО") def edit_cdn(e): def close(e): dialog.open = False page.update() + + def edit(e): + edited_cdn = dialog.content.content.controls[0].value + e.control.content = ft.ProgressRing(width=20, height=20, color=ft.colors.RED_400, bgcolor=ft.colors.BLACK26) + e.control.update() + if check_api(edited_cdn): + close(e) + page.client_storage.set("cdn_url", "http://127.0.0.1:8000") + else: + e.control.content = ft.Text("Сохранить") + e.control.update() + dialog.content.content.controls[0].error_text = "Некорректная ссылка" + dialog.content.content.controls[0].update() + + def one_change(e): + e.control.error_text = None + dialog.content.content.controls[0].update() + boop.play() + cdn_url = page.client_storage.get("cdn_url") dialog = ft.AlertDialog( modal=True, - shape=ft.ContinuousRectangleBorder(radius=20), + shape=ft.ContinuousRectangleBorder(radius=50), + content_padding=15, + actions_padding=15, content=ft.Container( ft.Column([ - ft.TextField(label="CDN", value="https://cdn.sovagroup.one", on_change=boop.play_e, color="#FFFFFF", cursor_color="#FFFFFF", border_color=ft.colors.WHITE, border_radius=15, focused_border_color=ft.colors.RED_400), + ft.TextField(label="CDN", value=cdn_url, on_change=one_change, **interface_input), ]), - height=50, - width=300 + height=60, + width=300, + ), - actions=[ft.ElevatedButton("Сохранить", on_click=boop.play_e, **interface_button, width=150), ft.ElevatedButton("Отмена", on_click=close, **interface_button, width=150)] + actions=[ft.ElevatedButton("Сохранить", on_click=edit, **interface_button, width=150), ft.ElevatedButton("Отмена", on_click=close, **interface_button, width=150)] ) page.dialog = dialog dialog.open = True diff --git a/ui.py b/ui.py index 1e0b72e..a7a4997 100644 --- a/ui.py +++ b/ui.py @@ -2,19 +2,33 @@ interface_button = { "color": ft.colors.WHITE, - "style": ft.ButtonStyle(shape=ft.RoundedRectangleBorder(radius=10), bgcolor=ft.colors.WHITE24, overlay_color=ft.colors.with_opacity(0.5, ft.colors.RED_500), padding=20), + "style": ft.ButtonStyle(shape=ft.RoundedRectangleBorder(radius=10), bgcolor=ft.colors.WHITE24, overlay_color=ft.colors.with_opacity(0.05, ft.colors.WHITE), padding=20), "icon_color": "white", } interface_switch = { - "active_color" : ft.colors.WHITE, - "active_track_color" : ft.colors.RED_400, - "inactive_track_color" : "#1e1f22", - "thumb_color" : ft.colors.WHITE, + "active_color": ft.colors.WHITE, + "active_track_color": ft.colors.RED_400, + "inactive_track_color": "#1e1f22", + "thumb_color": ft.colors.WHITE, "inactive_thumb_color" : "white", "focus_color" : ft.colors.WHITE } -interface_input = { +navigation_button = { + "width": 250, + "height": 45, + "bgcolor": ft.colors.TRANSPARENT, + "color": ft.colors.WHITE, + "icon_color": ft.colors.WHITE, + "style": ft.ButtonStyle(shape=ft.RoundedRectangleBorder(radius=0), bgcolor=ft.colors.TRANSPARENT, + surface_tint_color=ft.colors.TRANSPARENT, shadow_color=ft.colors.TRANSPARENT, overlay_color=ft.colors.with_opacity(0.1, ft.colors.WHITE)), +} +interface_input = { + "color": "#FFFFFF", + "cursor_color": "#FFFFFF", + "border_color": ft.colors.WHITE, + "border_radius": 15, + "focused_border_color": ft.colors.RED_400 } \ No newline at end of file