from os import path, walk from tkinter import E, NSEW, W, ttk from traceback import print_exc import xmltodict import requests from ttkthemes import ThemedTk from classes.custom.scrollable_frame import ScrollableFrame from classes.custom.themed_frame import ThemedFrame from classes.enums import SaveState, SaveType from classes.frames.save import FrameSave from modules.utils import configGet class FrameSaves(ScrollableFrame): def __init__(self, master: ThemedTk, **kwargs) -> None: super().__init__(master, **kwargs) master.title("Saves - Stardew Sync") self.saves = self.fetch_saves() # self["borderwidth"] = 1 # self["relief"] = "solid" master.columnconfigure(1, weight=1) if len(self.saves) == 0: self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=2) master.columnconfigure(1, weight=1) self.label = ttk.Label(self, text="No saves found") self.label.grid(column=0, row=0, padx=9, pady=9) else: self.render_saves(refetch=False) def fetch_saves_remote(self) -> list: response = 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")) return response.json() if response.status_code == 200 else [] def fetch_saves(self) -> list: self.saves = self.fetch_saves_remote() for index, entry in enumerate(self.saves): self.saves[index]["state"] = SaveState.RECENT self.saves[index]["type"] = SaveType.REMOTE for subdir, dirs, files in walk(configGet("saves_location")): try: for dir in dirs: print("Processing", dir) with open(path.join(configGet("saves_location"), dir, "SaveGameInfo"), "r", encoding="utf-8") as file: save_info_dict = xmltodict.parse(file.read()) with open(path.join(configGet("saves_location"), dir, dir), "r", encoding="utf-8") as file: save_dict = xmltodict.parse(file.read()) save_date = None save_type = SaveType.LOCAL save_state = SaveState.RECENT use_remote = False for index, entry in enumerate(self.saves): if entry["id"] == int(save_dict["SaveGame"]["uniqueIDForThisGame"]): print(f'Remote: {entry["data"]["save_time"]}; Local: {int(save_info_dict["Farmer"]["saveTime"])}') if int(save_info_dict["Farmer"]["saveTime"]) > entry["data"]["save_time"]: self.saves[index]["type"] = SaveType.BOTH save_type = SaveType.BOTH save_state = SaveState.RECENT save_date = entry["date"] elif int(save_info_dict["Farmer"]["saveTime"]) < entry["data"]["save_time"]: self.saves[index]["type"] = SaveType.BOTH use_remote = True else: self.saves[index]["type"] = SaveType.BOTH self.saves[index]["state"] = SaveState.CURRENT use_remote = True if use_remote is True: continue if save_state == SaveState.RECENT: for index, entry in enumerate(self.saves): if entry["id"] == int(save_dict["SaveGame"]["uniqueIDForThisGame"]): del self.saves[index] break self.saves.append( { "id": int(save_dict["SaveGame"]["uniqueIDForThisGame"]), "user": None, "device": configGet("name"), "date": save_date, "type": save_type, "state": SaveState.RECENT, "data": { "farmer": save_info_dict["Farmer"]["name"], "money": int(save_info_dict["Farmer"]["money"]), "played": int(save_info_dict["Farmer"]["millisecondsPlayed"]), "save_time": int(save_info_dict["Farmer"]["saveTime"]), "year": int(save_info_dict["Farmer"]["yearForSaveGame"]), "season": int(save_info_dict["Farmer"]["seasonForSaveGame"]), "day": int(save_info_dict["Farmer"]["dayOfMonthForSaveGame"]), "game_version": save_info_dict["Farmer"]["gameVersion"] }, "file": { "name": None, "uuid": None, "path": None } } ) except: print_exc() return self.saves def render_saves(self, refetch: bool = True): if refetch is True: self.saves = self.fetch_saves() for widget in self.winfo_children(): widget.destroy() i = 0 for save in self.saves: # print(save) save_frame = FrameSave(self, save_dict=save) save_frame.grid(column=0, row=i, pady=9, padx=9, sticky=W+E) i += 1 if i+1 != len(self.saves): divider = ttk.Separator(self, orient="horizontal") divider.grid(column=0, row=i+1, pady=9) i += 1 # class FrameSavesEmpty(ThemedFrame): # def __init__(self, master: ThemedTk, **kwargs) -> None: # super().__init__(master, **kwargs) # master.title("Saves - Stardew Sync") # self.grid_columnconfigure(0, weight=1) # self.grid_rowconfigure(0, weight=2) # master.columnconfigure(1, weight=1) # self.label = ttk.Label(self, text="No saves found") # self.label.grid(column=0, row=0, padx=9, pady=9)