🚧 SGDB

This commit is contained in:
GeoffreyCoulaud
2023-05-05 16:02:57 +02:00
parent 5c6bfc8b3e
commit 0abe283619
3 changed files with 88 additions and 32 deletions

View File

@@ -2,7 +2,7 @@ from threading import Thread, Lock
from gi.repository import Adw, Gtk, Gio from gi.repository import Adw, Gtk, Gio
from .game import Game from .game import Game
from .steamgriddb import SGDBSave from .steamgriddb import SGDBHelper
class Importer: class Importer:
@@ -97,47 +97,20 @@ class Importer:
def __import_from_source(self, *args, **kwargs): def __import_from_source(self, *args, **kwargs):
"""Source import thread entry point""" """Source import thread entry point"""
# TODO just get Game objects from the sources
source, *rest = args source, *rest = args
iterator = source.__iter__() iterator = source.__iter__()
for game_values in iterator: for game in iterator:
game = Game(self.win, game_values)
self.games_lock.acquire() self.games_lock.acquire()
self.games.add(game) self.games.add(game)
self.games_lock.release() self.games_lock.release()
# TODO SGDB image
# Who's in charge of image adding ?
self.progress_lock.acquire() self.progress_lock.acquire()
self.counts[source.id]["total"] = len(iterator) self.counts[source.id]["total"] = len(iterator)
if not game.blacklisted: if not game.blacklisted:
self.counts[source.id]["done"] += 1 self.counts[source.id]["done"] += 1
self.update_progressbar() self.update_progressbar()
self.progress_lock.release() self.progress_lock.release()
# TODO remove after not needed
def save_game(self, values=None, cover_path=None):
if values:
game = Game(self.win, values)
if save_cover:
save_cover(self.win, game.game_id, resize_cover(self.win, cover_path))
self.games.add(game)
self.games_no += 1
if game.blacklisted:
self.games_no -= 1
self.queue -= 1
self.update_progressbar()
if self.queue == 0 and not self.blocker:
if self.games:
self.total_queue = len(self.games)
self.queue = len(self.games)
self.import_statuspage.set_title(_("Importing Covers…"))
self.update_progressbar()
SGDBSave(self.win, self.games, self)
else:
self.done()

View File

@@ -1,6 +1,7 @@
from functools import cached_property from functools import cached_property
from sqlite3 import connect from sqlite3 import connect
from src.game import Game
from src.utils.save_cover import resize_cover, save_cover from src.utils.save_cover import resize_cover, save_cover
from src.importer.source import Source, SourceIterator from src.importer.source import Source, SourceIterator
from src.importer.decorators import replaced_by_schema_key, replaced_by_path from src.importer.decorators import replaced_by_schema_key, replaced_by_path
@@ -55,6 +56,7 @@ class LutrisSourceIterator(SourceIterator):
continue continue
# Build basic game # Build basic game
# TODO decouple game creation from the window object (later)
values = { values = {
"hidden": row[4], "hidden": row[4],
"name": row[1], "name": row[1],
@@ -65,6 +67,7 @@ class LutrisSourceIterator(SourceIterator):
"executable": self.source.executable_format.format(game_id=row[2]), "executable": self.source.executable_format.format(game_id=row[2]),
"developer": None, # TODO get developer metadata on Lutris "developer": None, # TODO get developer metadata on Lutris
} }
game = Game(self.source.win, values)
# Save official image # Save official image
image_path = self.source.cache_location / "coverart" / f"{row[2]}.jpg" image_path = self.source.cache_location / "coverart" / f"{row[2]}.jpg"
@@ -73,6 +76,7 @@ class LutrisSourceIterator(SourceIterator):
save_cover(self.source.win, values["game_id"], resized) save_cover(self.source.win, values["game_id"], resized)
# TODO Save SGDB # TODO Save SGDB
SGDBSave(self.win, self.games, self)
return values return values

View File

@@ -8,6 +8,85 @@ from .create_dialog import create_dialog
from .save_cover import save_cover, resize_cover from .save_cover import save_cover, resize_cover
class SGDBError(Exception):
pass
class SGDBHelper:
base_url = "https://www.steamgriddb.com/api/v2/"
win = None
importer = None
exception = None
def __init__(self, win, importer=None) -> None:
self.win = win
self.importer = importer
@property
def auth_header(self):
key = self.win.schema.get_string("sgdb-key")
headers = {"Authorization": f"Bearer {key}"}
return headers
# TODO delegate that to the app
def create_exception_dialog(self, exception):
dialog = create_dialog(
self.win,
_("Couldn't Connect to SteamGridDB"),
exception,
"open_preferences",
_("Preferences"),
)
dialog.connect("response", self.response)
# TODO same as create_exception_dialog
def on_exception_dialog_response(self, _widget, response):
if response == "open_preferences":
self.win.get_application().on_preferences_action(page_name="sgdb")
def get_game_id(self, game):
"""Get grid results for a game. Can raise an exception."""
# Request
res = requests.get(
f"{self.base_url}search/autocomplete/{game.name}",
headers=self.auth_headers,
timeout=5,
)
if res.status_code == 200:
return res.json()["data"][0]["id"]
# HTTP error
res.raise_for_status()
# SGDB API error
res_json = res.json()
if "error" in tuple(res_json):
raise SGDBError(res_json["errors"])
else:
raise SGDBError(res.status_code)
def get_image_uri(self, game, animated=False):
"""Get the image for a game"""
uri = f"{self.base_url}grids/game/{self.get_game_id(game)}?dimensions=600x900"
if animated:
uri += "&types=animated"
grid = requests.get(uri, headers=self.auth_header, timeout=5)
image_uri = grid.json()["data"][0]["url"]
return image_uri
# Current steps to save image for N games
# Create a task for every game
# Call update_cover
# If using sgdb and (prefer or no image) and not blacklisted
# Search for game
# Get image from sgdb (animated if preferred and found, or still)
# Exit task and enter task_done
# If error, create popup
class SGDBSave: class SGDBSave:
def __init__(self, games, importer=None): def __init__(self, games, importer=None):
self.win = shared.win self.win = shared.win