Create more oppurtinities for state saving;
for image cache and settings
This commit is contained in:
1 parent
903b299bfe
commit
f3fd0fa5d9
3 files changed
+20
-3
No files matched your search
@@ -42,6 +42,7 @@ class ImageCache:
|
|||||||
self._images: dict[ImageHash, Image] = {}
|
self._images: dict[ImageHash, Image] = {}
|
||||||
self._photos: dict[tuple[ImageHash, ImageSize], PhotoImage] = {}
|
self._photos: dict[tuple[ImageHash, ImageSize], PhotoImage] = {}
|
||||||
self._lock = asyncio.Lock()
|
self._lock = asyncio.Lock()
|
||||||
|
self._altered: bool = False
|
||||||
# cleanup the URLs
|
# cleanup the URLs
|
||||||
hash_counts: dict[ImageHash, int] = {}
|
hash_counts: dict[ImageHash, int] = {}
|
||||||
now = datetime.now(timezone.utc)
|
now = datetime.now(timezone.utc)
|
||||||
@@ -51,6 +52,7 @@ class ImageCache:
|
|||||||
hash_counts[img_hash] = 0
|
hash_counts[img_hash] = 0
|
||||||
if now >= hash_dict["expires"]:
|
if now >= hash_dict["expires"]:
|
||||||
del self._hashes[url]
|
del self._hashes[url]
|
||||||
|
self._altered = True
|
||||||
else:
|
else:
|
||||||
hash_counts[img_hash] += 1
|
hash_counts[img_hash] += 1
|
||||||
for img_hash, count in hash_counts.items():
|
for img_hash, count in hash_counts.items():
|
||||||
@@ -60,7 +62,8 @@ class ImageCache:
|
|||||||
file.unlink()
|
file.unlink()
|
||||||
|
|
||||||
def save(self) -> None:
|
def save(self) -> None:
|
||||||
json_save(CACHE_DB, self._hashes)
|
if self._altered:
|
||||||
|
json_save(CACHE_DB, self._hashes)
|
||||||
|
|
||||||
def _new_expires(self) -> datetime:
|
def _new_expires(self) -> datetime:
|
||||||
return datetime.now(timezone.utc) + self.LIFETIME
|
return datetime.now(timezone.utc) + self.LIFETIME
|
||||||
@@ -94,6 +97,9 @@ class ImageCache:
|
|||||||
"hash": img_hash,
|
"hash": img_hash,
|
||||||
"expires": self._new_expires()
|
"expires": self._new_expires()
|
||||||
}
|
}
|
||||||
|
# NOTE: If self._hashes ever stops being updated in both above if cases,
|
||||||
|
# this will need to be moved
|
||||||
|
self._altered = True
|
||||||
if size is None:
|
if size is None:
|
||||||
size = image.size
|
size = image.size
|
||||||
photo_key = (img_hash, size)
|
photo_key = (img_hash, size)
|
||||||
|
|||||||
+4
-1
@@ -50,6 +50,7 @@ class Settings:
|
|||||||
def __init__(self, args: ParsedArgs):
|
def __init__(self, args: ParsedArgs):
|
||||||
self._settings: SettingsFile = json_load(SETTINGS_PATH, default_settings)
|
self._settings: SettingsFile = json_load(SETTINGS_PATH, default_settings)
|
||||||
self._args: ParsedArgs = args
|
self._args: ParsedArgs = args
|
||||||
|
self._altered: bool = False
|
||||||
|
|
||||||
# default logic of reading settings is to check args first, then the settings file
|
# default logic of reading settings is to check args first, then the settings file
|
||||||
def __getattr__(self, name: str, /) -> Any:
|
def __getattr__(self, name: str, /) -> Any:
|
||||||
@@ -65,6 +66,7 @@ class Settings:
|
|||||||
return super().__setattr__(name, value)
|
return super().__setattr__(name, value)
|
||||||
elif name in self._settings:
|
elif name in self._settings:
|
||||||
self._settings[name] = value # type: ignore[literal-required]
|
self._settings[name] = value # type: ignore[literal-required]
|
||||||
|
self._altered = True
|
||||||
return
|
return
|
||||||
raise TypeError(f"{name} is missing a custom setter")
|
raise TypeError(f"{name} is missing a custom setter")
|
||||||
|
|
||||||
@@ -72,4 +74,5 @@ class Settings:
|
|||||||
raise RuntimeError("settings can't be deleted")
|
raise RuntimeError("settings can't be deleted")
|
||||||
|
|
||||||
def save(self) -> None:
|
def save(self) -> None:
|
||||||
json_save(SETTINGS_PATH, self._settings)
|
if self._altered:
|
||||||
|
json_save(SETTINGS_PATH, self._settings)
|
||||||
@@ -149,6 +149,13 @@ class Twitch:
|
|||||||
"""
|
"""
|
||||||
self.gui.print(*args, **kwargs)
|
self.gui.print(*args, **kwargs)
|
||||||
|
|
||||||
|
def save(self) -> None:
|
||||||
|
"""
|
||||||
|
Saves the application state.
|
||||||
|
"""
|
||||||
|
self.gui.save()
|
||||||
|
self.settings.save()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _viewers_key(channel: Channel) -> int:
|
def _viewers_key(channel: Channel) -> int:
|
||||||
if (viewers := channel.viewers) is not None:
|
if (viewers := channel.viewers) is not None:
|
||||||
@@ -205,6 +212,8 @@ class Twitch:
|
|||||||
self._mnt_task = asyncio.create_task(self._maintenance_task())
|
self._mnt_task = asyncio.create_task(self._maintenance_task())
|
||||||
await self.fetch_inventory()
|
await self.fetch_inventory()
|
||||||
self.gui.set_games(set(campaign.game for campaign in self.inventory))
|
self.gui.set_games(set(campaign.game for campaign in self.inventory))
|
||||||
|
# Save state on every inventory fetch
|
||||||
|
self.save()
|
||||||
self.change_state(State.GAMES_UPDATE)
|
self.change_state(State.GAMES_UPDATE)
|
||||||
elif self._state is State.GAMES_UPDATE:
|
elif self._state is State.GAMES_UPDATE:
|
||||||
# Figure out which games to watch, and claim the drops we can
|
# Figure out which games to watch, and claim the drops we can
|
||||||
@@ -925,7 +934,6 @@ class Twitch:
|
|||||||
self._drops.update((drop.id, drop) for drop in campaign.drops)
|
self._drops.update((drop.id, drop) for drop in campaign.drops)
|
||||||
await self.gui.inv.add_campaign(campaign)
|
await self.gui.inv.add_campaign(campaign)
|
||||||
self.inventory.append(campaign)
|
self.inventory.append(campaign)
|
||||||
self.gui.save()
|
|
||||||
|
|
||||||
def get_active_drop(self, channel: Channel | None = None) -> TimedDrop | None:
|
def get_active_drop(self, channel: Channel | None = None) -> TimedDrop | None:
|
||||||
if not self.games:
|
if not self.games:
|
||||||
|
|||||||
Reference in new issue
Block a user