Work on importer / SGDB integration
This commit is contained in:
@@ -60,7 +60,7 @@ class Game(Gtk.Box):
|
||||
blacklisted = None
|
||||
game_cover = None
|
||||
|
||||
def __init__(self, data, **kwargs):
|
||||
def __init__(self, win, data, allow_side_effects=False, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.win = shared.win
|
||||
@@ -69,6 +69,7 @@ class Game(Gtk.Box):
|
||||
|
||||
self.update_values(data)
|
||||
|
||||
if allow_side_effects:
|
||||
self.win.games[self.game_id] = self
|
||||
|
||||
self.set_play_icon()
|
||||
@@ -77,7 +78,6 @@ class Game(Gtk.Box):
|
||||
self.add_controller(self.event_contoller_motion)
|
||||
self.event_contoller_motion.connect("enter", self.toggle_play, False)
|
||||
self.event_contoller_motion.connect("leave", self.toggle_play, None, None)
|
||||
|
||||
self.cover_button.connect("clicked", self.main_button_clicked, False)
|
||||
self.play_button.connect("clicked", self.main_button_clicked, True)
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from requests import HTTPError
|
||||
from gi.repository import Adw, Gio, Gtk
|
||||
|
||||
from .create_dialog import create_dialog
|
||||
from .save_cover import resize_cover, save_cover
|
||||
from .steamgriddb import SGDBAuthError, SGDBHelper
|
||||
from .steamgriddb import SGDBAuthError, SGDBError, SGDBHelper
|
||||
|
||||
|
||||
class Importer:
|
||||
@@ -25,11 +23,12 @@ class Importer:
|
||||
n_sgdb_tasks_created = 0
|
||||
n_sgdb_tasks_done = 0
|
||||
sgdb_cancellable = None
|
||||
sgdb_error = None
|
||||
errors = None
|
||||
|
||||
def __init__(self, win):
|
||||
self.win = win
|
||||
self.sources = set()
|
||||
self.errors = []
|
||||
|
||||
@property
|
||||
def n_tasks_created(self):
|
||||
@@ -123,10 +122,13 @@ class Importer:
|
||||
)
|
||||
continue
|
||||
|
||||
# TODO make sources return games AND avoid duplicates
|
||||
game_id = game.game_id
|
||||
if game.game_id in self.win.games and not self.win.games[game_id].removed:
|
||||
# Avoid duplicates
|
||||
gid = game.game_id
|
||||
if gid in self.win.games and not self.win.games[gid].removed:
|
||||
continue
|
||||
|
||||
# Register game
|
||||
self.win.games[gid] = game
|
||||
game.save()
|
||||
self.n_games_added += 1
|
||||
|
||||
@@ -148,49 +150,16 @@ class Importer:
|
||||
|
||||
def sgdb_task_thread_func(self, _task, _obj, data, cancellable):
|
||||
"""SGDB query code"""
|
||||
|
||||
game, *_rest = data
|
||||
|
||||
use_sgdb = self.win.schema.get_boolean("sgdb")
|
||||
if not use_sgdb or game.blacklisted:
|
||||
return
|
||||
|
||||
# Check if we should query SGDB
|
||||
prefer_sgdb = self.win.schema.get_boolean("sgdb-prefer")
|
||||
prefer_animated = self.win.schema.get_boolean("sgdb-animated")
|
||||
image_trunk = self.win.covers_dir / game.game_id
|
||||
still = image_trunk.with_suffix(".tiff")
|
||||
animated = image_trunk.with_suffix(".gif")
|
||||
|
||||
# Breaking down the condition
|
||||
is_missing = not still.is_file() and not animated.is_file()
|
||||
is_not_best = not animated.is_file() and prefer_animated
|
||||
if not (is_missing or is_not_best or prefer_sgdb):
|
||||
return
|
||||
|
||||
game.set_loading(1)
|
||||
|
||||
# SGDB request
|
||||
sgdb = SGDBHelper(self.win)
|
||||
try:
|
||||
sgdb_id = sgdb.get_game_id(game)
|
||||
uri = sgdb.get_game_image_uri(sgdb_id, animated=prefer_animated)
|
||||
response = requests.get(uri, timeout=5)
|
||||
sgdb.conditionaly_update_cover(game)
|
||||
except SGDBAuthError as error:
|
||||
# On auth error, cancel all present and future SGDB tasks for this import
|
||||
self.sgdb_error = error
|
||||
logging.error("SGDB Auth error occured", exc_info=error)
|
||||
cancellable.cancel()
|
||||
return
|
||||
except Exception as error: # pylint: disable=broad-exception-caught
|
||||
logging.warning("Non auth error in SGDB query", exc_info=error)
|
||||
return
|
||||
|
||||
# Image saving
|
||||
tmp_file = Gio.File.new_tmp()[0]
|
||||
tmp_file_path = tmp_file.get_path()
|
||||
Path(tmp_file_path).write_bytes(response.content)
|
||||
save_cover(self.win, game.game_id, resize_cover(self.win, tmp_file_path))
|
||||
self.errors.append(error)
|
||||
except (HTTPError, SGDBError) as error:
|
||||
self.errors.append(error)
|
||||
|
||||
def sgdb_task_callback(self, _obj, _result, data):
|
||||
"""SGDB query callback"""
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from pathlib import Path
|
||||
|
||||
import logging
|
||||
import requests
|
||||
from requests import HTTPError
|
||||
from gi.repository import Gio
|
||||
|
||||
from . import shared
|
||||
@@ -24,6 +26,10 @@ class SGDBBadRequestError(SGDBError):
|
||||
pass
|
||||
|
||||
|
||||
class SGDBNoImageFoundError(SGDBError):
|
||||
pass
|
||||
|
||||
|
||||
class SGDBHelper:
|
||||
"""Helper class to make queries to SteamGridDB"""
|
||||
|
||||
@@ -69,6 +75,66 @@ class SGDBHelper:
|
||||
case _:
|
||||
res.raise_for_status()
|
||||
|
||||
def conditionaly_update_cover(self, game):
|
||||
"""Update the game's cover if appropriate"""
|
||||
|
||||
# Obvious skips
|
||||
use_sgdb = self.win.schema.get_boolean("sgdb")
|
||||
if not use_sgdb or game.blacklisted:
|
||||
return
|
||||
|
||||
image_trunk = self.win.covers_dir / game.game_id
|
||||
still = image_trunk.with_suffix(".tiff")
|
||||
uri_kwargs = image_trunk.with_suffix(".gif")
|
||||
prefer_sgdb = self.win.schema.get_boolean("sgdb-prefer")
|
||||
|
||||
# Do nothing if file present and not prefer SGDB
|
||||
if not prefer_sgdb and (still.is_file() or uri_kwargs.is_file()):
|
||||
return
|
||||
|
||||
# Get ID for the game
|
||||
try:
|
||||
sgdb_id = self.get_game_id(game)
|
||||
except (HTTPError, SGDBError) as error:
|
||||
logging.warning(
|
||||
"Error while getting SGDB ID for %s", game.name, exc_info=error
|
||||
)
|
||||
raise error
|
||||
|
||||
# Build different SGDB options to try
|
||||
image_uri_kwargs_sets = [{"animated": False}]
|
||||
if self.win.schema.get_boolean("sgdb-animated"):
|
||||
image_uri_kwargs_sets.insert(0, {"animated": True})
|
||||
|
||||
# Download covers
|
||||
for uri_kwargs in image_uri_kwargs_sets:
|
||||
try:
|
||||
uri = self.get_game_image_uri(sgdb_id, **uri_kwargs)
|
||||
response = requests.get(uri, timeout=5)
|
||||
tmp_file = Gio.File.new_tmp()[0]
|
||||
tmp_file_path = tmp_file.get_path()
|
||||
Path(tmp_file_path).write_bytes(response.content)
|
||||
save_cover(
|
||||
self.win, game.game_id, resize_cover(self.win, tmp_file_path)
|
||||
)
|
||||
except SGDBAuthError as error:
|
||||
# Let caller handle auth errors
|
||||
raise error
|
||||
except (HTTPError, SGDBError) as error:
|
||||
logging.warning("Error while getting image", exc_info=error)
|
||||
continue
|
||||
else:
|
||||
# Stop as soon as one is finished
|
||||
return
|
||||
|
||||
# No image was added
|
||||
logging.warning(
|
||||
'No matching image found for game "%s" (SGDB ID %d)',
|
||||
game.name,
|
||||
sgdb_id,
|
||||
)
|
||||
raise SGDBNoImageFoundError()
|
||||
|
||||
|
||||
# Current steps to save image for N games
|
||||
# Create a task for every game
|
||||
|
||||
Reference in New Issue
Block a user