Add image caching logic for show posters
This commit is contained in:
+51
-11
@@ -1,8 +1,9 @@
|
|||||||
from typing import Type
|
from typing import Type
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from urllib import parse
|
import urllib.parse
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
@@ -14,7 +15,6 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSlot
|
|||||||
|
|
||||||
from PyQt5.QtGui import QImage
|
from PyQt5.QtGui import QImage
|
||||||
|
|
||||||
|
|
||||||
from .qtmpv import MpvObject
|
from .qtmpv import MpvObject
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
@@ -92,13 +92,13 @@ class ProviderImageProvider(QQuickImageProvider):
|
|||||||
|
|
||||||
|
|
||||||
def getUrl(base: str, path: str) -> dict:
|
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)
|
r: requests.Response = requests.get(url)
|
||||||
return r.json()
|
return r.json()
|
||||||
|
|
||||||
|
|
||||||
class Provider(QObject):
|
class Provider(QObject):
|
||||||
def __init__(self, url: str, parent=None):
|
def __init__(self, url: str, data_dir: str, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.url: str = url
|
self.url: str = url
|
||||||
|
|
||||||
@@ -108,17 +108,44 @@ class Provider(QObject):
|
|||||||
describe["icon"]
|
describe["icon"]
|
||||||
)
|
)
|
||||||
|
|
||||||
def default_val():
|
# Create dictionary of show episodes
|
||||||
return []
|
|
||||||
|
|
||||||
episodes: dict = getUrl(self.url, "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"]:
|
for e in episodes["episodes"]:
|
||||||
_episodes[e["ShowTitle"]].append(Episode(e))
|
_episodes[e["ShowTitle"]].append(Episode(e))
|
||||||
|
|
||||||
shows: dict = getUrl(self.url, "shows")
|
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] = {
|
self._shows: dict[int, Show] = {
|
||||||
e["id"]: Show(e, _episodes[e["title"]]) for e in shows["data"]
|
e["id"]: Show(e, _episodes[e["title"]]) for e in shows["data"]
|
||||||
}
|
}
|
||||||
@@ -161,8 +188,8 @@ class Provider(QObject):
|
|||||||
|
|
||||||
|
|
||||||
class DataSource:
|
class DataSource:
|
||||||
def __init__(self, providers=[]):
|
def __init__(self, providers: list[str], data_dir: str):
|
||||||
self.providers: list[Provider] = [Provider(url) for url in providers]
|
self.providers: list[Provider] = [Provider(url, data_dir) for url in providers]
|
||||||
|
|
||||||
|
|
||||||
def DatabaseType(data_source) -> Type:
|
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"]]
|
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():
|
def main():
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
@@ -218,7 +256,9 @@ def main():
|
|||||||
print(f"ERROR: Could not load config file: {repr(e)}")
|
print(f"ERROR: Could not load config file: {repr(e)}")
|
||||||
sys.exit(-1)
|
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")
|
qmlRegisterType(DatabaseType(data_source), "Ikinuki.Client", 1, 0, "Database")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user