from datetime import datetime, timedelta, timezone from functools import partial from os import makedirs, path, remove from tkinter import LEFT, NSEW, Misc, S, W, ttk from urllib.parse import urlencode from zipfile import ZipFile import requests from classes.custom.themed_frame import ThemedFrame from classes.enums import SaveState, SaveType from modules.utils import configGet, osname class FrameSave(ThemedFrame): def __init__(self, master: Misc, save_dict: dict, **kwargs) -> None: super().__init__(master, style="Card.TFrame", **kwargs) self.widget_width = 47 if osname == "nt" else 42 self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=3) self.grid_columnconfigure(2, weight=3) self.save_dict = save_dict self.title = ttk.Label(self, text=f'{save_dict["data"]["farmer"]} ({save_dict["type"].value.upper()}, {save_dict["state"].value.upper()})', font=("SunValleyBodyStrongFont", 12, "bold"), justify=LEFT, width=self.widget_width) self.title.grid(column=0, row=0, padx=9, pady=9, sticky=W) self.description = ttk.Label(self, text=f'{self.convert_date(year=save_dict["data"]["year"], season=save_dict["data"]["season"], day=save_dict["data"]["day"])}\n{save_dict["data"]["money"]} Gold, {int((save_dict["data"]["played"]/(1000*60*60))%24)} hours played\nGame version: {save_dict["data"]["game_version"]}', width=self.widget_width) self.description.grid(column=0, row=1, padx=9, pady=9, sticky=W) self.buttons = ThemedFrame(self) self.buttons.grid(column=0, columnspan=2, row=2, sticky=NSEW, padx=9, pady=9) self.buttons.grid_columnconfigure(0, weight=1) if save_dict["date"] != None: upload_date = datetime.utcfromtimestamp(save_dict["date"]).replace(tzinfo=timezone.utc).astimezone(tz=None) self.last_upload = ttk.Label(self.buttons, text=f'{upload_date.strftime("%A, %d %b %Y")}\nUploaded at {upload_date.strftime("%H:%M")} by {save_dict["device"]}', font=("SunValleyBodyFont", 8), justify=LEFT, width=self.widget_width) else: self.last_upload = ttk.Label(self.buttons, text=f'Exists only locally', font=("SunValleyBodyFont", 8), justify=LEFT, width=self.widget_width) self.last_upload.grid(column=0, row=0, sticky=W+S) # self.button_device_rename_action = partial(self.rename) # self.button_device_rename = ttk.Button(self.buttons, text="Rename", width=11, command=self.button_device_rename_action) # self.button_device_rename.grid(column=0, row=0, padx=9, sticky=E) self.button_synchronize_action = partial(self.nothing) if save_dict["type"] is SaveType.LOCAL: if save_dict["state"] is SaveState.RECENT: self.button_synchronize_action = partial(self.upload, save_dict["id"]) print(f'{save_dict["id"]}, local, recent') elif save_dict["type"] is SaveType.REMOTE: if save_dict["state"] is SaveState.RECENT: self.button_synchronize_action = partial(self.download, save_dict["id"], save_dict["date"]) print(f'{save_dict["id"]}, remote, recent') else: if save_dict["state"] is SaveState.OUTDATED: self.button_synchronize_action = partial(self.download, save_dict["id"], save_dict["date"]) print(f'{save_dict["id"]}, both, outdated') elif save_dict["state"] is SaveState.RECENT: self.button_synchronize_action = partial(self.upload, save_dict["id"]) print(f'{save_dict["id"]}, both, recent') self.button_synchronize = ttk.Button(self.buttons, text="Synchronize", style="Accent.TButton", width=11, command=self.button_synchronize_action) self.button_synchronize.grid(column=1, row=0, sticky=W) if save_dict["state"] is SaveState.CURRENT: self.button_synchronize.state(["disabled"]) def convert_date(self, year: int, season: int, day: int) -> str: if season == 0: season_name = "Spring" elif season == 1: season_name = "Summer" elif season == 2: season_name = "Fall" else: season_name = "Winter" return "Day {0} of {1}, Year {2}".format(day, season_name, year) def convert_playtime(self, seconds: int) -> str: return "" def upload(self, id: int): print(f"Upload pressed for {id}") files = [("files", open(path.join(configGet("saves_location"), f'{self.save_dict["data"]["farmer"]}_{self.save_dict["id"]}', f'{self.save_dict["data"]["farmer"]}_{self.save_dict["id"]}'), "rb")), ("files", open(path.join(configGet("saves_location"), f'{self.save_dict["data"]["farmer"]}_{self.save_dict["id"]}', "SaveGameInfo"), "rb"))] response = requests.post(f'{configGet("address")}/saves?{urlencode({"device": configGet("name")})}', files=files, headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")) print(response.status_code) self.master.render_saves() def download(self, id: int, date: int): print(f"Download pressed for {id}") response = requests.get(f'{configGet("address")}/saves/{id}/{date}/download', headers={"apikey": configGet("apikey")}, verify=not configGet("allow_self_signed")) makedirs("tmp", exist_ok=True) with open(path.join("tmp", f"{id}.svsave"), "wb") as file: file.write(response.content) makedirs(path.join(configGet("saves_location"), f'{self.save_dict["data"]["farmer"]}_{self.save_dict["id"]}'), exist_ok=True) with ZipFile(path.join("tmp", f"{id}.svsave"), "r") as file: file.extractall(path.join(configGet("saves_location"), f'{self.save_dict["data"]["farmer"]}_{self.save_dict["id"]}')) remove(path.join("tmp", f"{id}.svsave")) print(response.status_code) self.master.render_saves() def nothing(self): pass