from os import path from tkinter import NSEW, NW, E, N, S, W, PhotoImage, messagebox, ttk from traceback import format_exc import requests import sv_ttk from ttkthemes import ThemedTk from classes.custom.scrollable_frame import FIT_HEIGHT, FIT_WIDTH from classes.custom.themed_frame import ThemedFrame from classes.enums import ConnectionState, Theme from classes.frames.devices import FrameDevices, FrameDevicesEmpty from classes.frames.errors import FrameErrorConnection, FrameErrorFirstStart, FrameErrorSavesFolder, FrameErrorUnconfigured from classes.frames.saves import FrameSaves, FrameSavesEmpty from classes.frames.settings import FrameSettings from classes.toplevel.welcome import ToplevelWelcome from modules.theme_titlebar import theme_title_bar from modules.utils import configGet, get_string_mode, resize_window, set_icon, use_dark_mode from modules.logger import logger class App(ThemedTk): def __init__(self): super().__init__() self.__version__ = "0.1.0" resize_window(self, 610, 400) self.resizable(True, True) self.minsize(610, 200) self.title("Stardew Sync") sv_ttk.init_theme(self) if use_dark_mode(): theme_title_bar(self, mode=Theme.DARK) self.update() set_icon(self) self.focus_set() self.draw_main() def verify_authorization(self) -> ConnectionState: try: return ConnectionState.UNAUTHORIZED if requests.get(configGet("address")+"/apikey", headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")).status_code == 403 else ConnectionState.OK except: return ConnectionState.BAD def verify_saves_dir(self): if configGet("saves_location") is None or path.exists(configGet("saves_location")) is False: return False else: return True def frame_saves(self): self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) try: self.frame_saves_saves = requests.get(f'{configGet("address")}/saves?only_ids=True&sort={(configGet("prefer_saves").split())[1]}', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")) except Exception as exp: messagebox.showerror(title="Connection error", message=f"We could not reach the server to check for save entries\n\n{exp}") logger.error(format_exc()) self.frame_saves_object = FrameErrorConnection(self) self.frame_saves_object.grid(column=1, row=0, sticky=NSEW) return if self.frame_saves_saves.status_code == 200 and isinstance(self.frame_saves_saves.json(), list) is True and len(self.frame_saves_saves.json()) > 0: self.frame_saves_object = FrameSaves(self, self.frame_saves_saves.json(), vscroll=True) else: self.frame_saves_object = FrameSavesEmpty(self) self.frame_saves_object.grid(column=1, row=0, sticky=NSEW) return def frame_devices(self): self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) try: self.frame_devices_devices = requests.get(f'{configGet("address")}/devices', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")) except Exception as exp: messagebox.showerror(title="Connection error", message=f"We could not reach the server to check the devices list\n\n{exp}") logger.error(format_exc()) self.frame_devices_object = FrameErrorConnection(self) self.frame_devices_object.grid(column=1, row=0, sticky=NSEW) return if self.frame_devices_devices.status_code == 200 and isinstance(self.frame_devices_devices.json(), list) is True and len(self.frame_devices_devices.json()) > 0: self.frame_devices_object = FrameDevices(self, self.frame_devices_devices.json(), vscroll=True) else: self.frame_devices_object = FrameDevicesEmpty(self) self.frame_devices_object.grid(column=1, row=0, sticky=NSEW) return def frame_settings(self): self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.frame_settings_object = FrameSettings(self) self.frame_settings_object.grid(column=1, row=0, sticky=N+S+W+E) return def draw_main(self): sv_ttk.set_theme(get_string_mode()) # self.grid_rowconfigure(1, weight=2) # self.grid_rowconfigure(0, weight=2) # self.grid_columnconfigure(1, weight=1) # self.setup_label = ttk.Label(self, text="Your client seems to be unconfigured") # self.setup_label.grid(column=1, row=0, padx=9, pady=9, sticky=S) # self.setup_button = ttk.Button(self, text="Set up", style="Accent.TButton", width=10, command=self.open_window_config) # self.setup_button.grid(column=1, row=1, padx=9, pady=9, sticky=N) # return if configGet("first_run") is True: self.welcome_window = ToplevelWelcome(self) self.welcome_window.grab_set() self.frame_sidebar = ThemedFrame(self) self.frame_sidebar.grid(column=0, row=0, columnspan=1, sticky=N+S+W+E) self.item_saves = ttk.Button(self.frame_sidebar, text="Saves", width=10, command=self.frame_saves) self.item_saves.grid(column=0, row=0, sticky=W, padx=9, pady=9) self.item_devices = ttk.Button(self.frame_sidebar, text="Devices", width=10, command=self.frame_devices) self.item_devices.grid(column=0, row=1, sticky=W, padx=9, pady=3) self.item_settings = ttk.Button(self.frame_sidebar, text="Settings", width=10, command=self.frame_settings) self.item_settings.grid(column=0, row=2, sticky=W+S, padx=9, pady=9) if configGet("first_run") is True: self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.connection_error = FrameErrorFirstStart(self) self.connection_error.grid(column=1, row=0, rowspan=2, sticky=N+S+W+E) return if configGet("address") in ["", None] or configGet("apikey") in ["", None]: self.item_saves.state(["disabled"]) self.item_devices.state(["disabled"]) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.connection_error = FrameErrorUnconfigured(self) self.connection_error.grid(column=1, row=0, rowspan=2, sticky=N+S+W+E) # messagebox.showerror(title="Configuration error", message="Your client is not properly configured.") return self.verified = self.verify_authorization() if self.verified in [ConnectionState.BAD, ConnectionState.UNAUTHORIZED]: self.item_saves.state(["disabled"]) self.item_devices.state(["disabled"]) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.connection_error = FrameErrorConnection(self) self.connection_error.grid(column=1, row=0, rowspan=2, sticky=N+S+W+E) if self.verified == ConnectionState.UNAUTHORIZED: messagebox.showerror(title="Authentication error", message="Your API key seems to be invalid.") else: messagebox.showerror(title="Connection error", message="Server is not reachable or your client configuration is incorrect. Please check your network connection and client configuration.") return if self.verify_saves_dir() is False: self.item_saves.state(["disabled"]) self.grid_rowconfigure(0, weight=1) self.grid_columnconfigure(1, weight=1) self.connection_error = FrameErrorSavesFolder(self) self.connection_error.grid(column=1, row=0, rowspan=2, sticky=N+S+W+E) messagebox.showerror(title="Configuration error", message="Saves folder seems to be invalid.") return self.frame_saves() def destroy_everything(self, draw=True): for widget in self.winfo_children(): widget.destroy() if draw is True: self.draw_main() # def open_window_config(self): # window = WindowConfig(self) # window.grab_set() # self.setup_button.destroy() # self.setup_label.destroy() # self.grid_rowconfigure(1, weight=2) # self.grid_rowconfigure(0, weight=2) # self.grid_columnconfigure(1, weight=1) # ttk.Label(self, text="Client configured, try to connect").grid(column=1, row=0, padx=9, pady=9, sticky=S) # ttk.Button(self, text="Connect", style="Accent.TButton", width=10, command=self.try_connecting).grid(column=1, row=1, padx=9, pady=9, sticky=N)