Add image caching logic for show posters
This commit is contained in:
+51
-11
@@ -1,8 +1,9 @@
|
||||
from typing import Type
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from urllib import parse
|
||||
import urllib.parse
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
@@ -14,7 +15,6 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSlot
|
||||
|
||||
from PyQt5.QtGui import QImage
|
||||
|
||||
|
||||
from .qtmpv import MpvObject
|
||||
|
||||
import requests
|
||||
@@ -92,13 +92,13 @@ class ProviderImageProvider(QQuickImageProvider):
|
||||
|
||||
|
||||
def getUrl(base: str, path: str) -> dict:
|
||||
url: str = parse.urljoin(base, path)
|
||||
url: str = urllib.parse.urljoin(base, path)
|
||||
r: requests.Response = requests.get(url)
|
||||
return r.json()
|
||||
|
||||
|
||||
class Provider(QObject):
|
||||
def __init__(self, url: str, parent=None):
|
||||
def __init__(self, url: str, data_dir: str, parent=None):
|
||||
super().__init__(parent)
|
||||
self.url: str = url
|
||||
|
||||
@@ -108,17 +108,44 @@ class Provider(QObject):
|
||||
describe["icon"]
|
||||
)
|
||||
|
||||
def default_val():
|
||||
return []
|
||||
|
||||
# Create dictionary of show episodes
|
||||
episodes: dict = getUrl(self.url, "episodes")
|
||||
_episodes: defaultdict[str, list[Episode]] = defaultdict(default_val)
|
||||
_episodes: defaultdict[str, list[Episode]] = defaultdict(lambda: [])
|
||||
|
||||
for e in episodes["episodes"]:
|
||||
_episodes[e["ShowTitle"]].append(Episode(e))
|
||||
|
||||
shows: dict = getUrl(self.url, "shows")
|
||||
|
||||
# Create image_cache directory
|
||||
provider_data_dir: str = os.path.join(
|
||||
data_dir, "image_cache", "providers", self._name
|
||||
)
|
||||
os.makedirs(provider_data_dir, exist_ok=True)
|
||||
|
||||
# Cache show posters
|
||||
for s in shows["data"]:
|
||||
# Get local cache path
|
||||
poster_url: str = s["poster"]
|
||||
poster_path: str = urllib.parse.urlparse(poster_url).path
|
||||
poster_ext: str = os.path.splitext(poster_path)[1]
|
||||
download_path: str = os.path.join(
|
||||
provider_data_dir, str(s["id"]) + poster_ext
|
||||
)
|
||||
|
||||
# Download poster
|
||||
try:
|
||||
with open(download_path, "xb") as f:
|
||||
r = requests.get(poster_url, stream=True)
|
||||
if r.status_code == 200:
|
||||
r.raw.decode_content = True
|
||||
shutil.copyfileobj(r.raw, f)
|
||||
except FileExistsError:
|
||||
pass
|
||||
|
||||
# Overwrite poster URL with local path
|
||||
s["poster"] = download_path
|
||||
|
||||
self._shows: dict[int, Show] = {
|
||||
e["id"]: Show(e, _episodes[e["title"]]) for e in shows["data"]
|
||||
}
|
||||
@@ -161,8 +188,8 @@ class Provider(QObject):
|
||||
|
||||
|
||||
class DataSource:
|
||||
def __init__(self, providers=[]):
|
||||
self.providers: list[Provider] = [Provider(url) for url in providers]
|
||||
def __init__(self, providers: list[str], data_dir: str):
|
||||
self.providers: list[Provider] = [Provider(url, data_dir) for url in providers]
|
||||
|
||||
|
||||
def DatabaseType(data_source) -> Type:
|
||||
@@ -204,6 +231,17 @@ def load_config() -> list[str]:
|
||||
return [f'http://{b["address"]}:{b["port"]}/' for b in config["backends"]]
|
||||
|
||||
|
||||
def get_data_dir() -> str:
|
||||
try:
|
||||
data_dir: str = os.path.join(os.environ["XDG_DATA_HOME"], "ikinuki")
|
||||
except:
|
||||
data_dir: str = os.path.join(os.environ["HOME"], ".local", "share", "ikinuki")
|
||||
|
||||
os.makedirs(data_dir, exist_ok=True)
|
||||
|
||||
return data_dir
|
||||
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
@@ -218,7 +256,9 @@ def main():
|
||||
print(f"ERROR: Could not load config file: {repr(e)}")
|
||||
sys.exit(-1)
|
||||
|
||||
data_source = DataSource(backends)
|
||||
data_dir: str = get_data_dir()
|
||||
|
||||
data_source = DataSource(backends, data_dir)
|
||||
|
||||
qmlRegisterType(DatabaseType(data_source), "Ikinuki.Client", 1, 0, "Database")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user