🎨 Various changes
- Changed source additional data to dict - Moved local cover saving into a manager - Added stub for itch cover manager
This commit is contained in:
@@ -120,7 +120,7 @@ class Importer:
|
|||||||
# Handle the result depending on its type
|
# Handle the result depending on its type
|
||||||
if isinstance(iteration_result, Game):
|
if isinstance(iteration_result, Game):
|
||||||
game = iteration_result
|
game = iteration_result
|
||||||
additional_data = tuple()
|
additional_data = {}
|
||||||
elif isinstance(iteration_result, tuple):
|
elif isinstance(iteration_result, tuple):
|
||||||
game, additional_data = iteration_result
|
game, additional_data = iteration_result
|
||||||
elif iteration_result is None:
|
elif iteration_result is None:
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Optional, Generator
|
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from src import shared
|
from src import shared
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
from src.importer.sources.source import LinuxSource, Source, SourceIterator
|
from src.importer.sources.source import (
|
||||||
|
LinuxSource,
|
||||||
|
Source,
|
||||||
|
SourceIterationResult,
|
||||||
|
SourceIterator,
|
||||||
|
)
|
||||||
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
||||||
from src.utils.save_cover import resize_cover, save_cover
|
|
||||||
|
|
||||||
|
|
||||||
class BottlesSourceIterator(SourceIterator):
|
class BottlesSourceIterator(SourceIterator):
|
||||||
source: "BottlesSource"
|
source: "BottlesSource"
|
||||||
|
|
||||||
def generator_builder(self) -> Generator[Optional[Game], None, None]:
|
def generator_builder(self) -> SourceIterationResult:
|
||||||
"""Generator method producing games"""
|
"""Generator method producing games"""
|
||||||
|
|
||||||
data = (self.source.location / "library.yml").read_text("utf-8")
|
data = (self.source.location / "library.yml").read_text("utf-8")
|
||||||
@@ -34,17 +37,16 @@ class BottlesSourceIterator(SourceIterator):
|
|||||||
}
|
}
|
||||||
game = Game(values, allow_side_effects=False)
|
game = Game(values, allow_side_effects=False)
|
||||||
|
|
||||||
# Save official cover
|
# Get official cover path
|
||||||
bottle_path = entry["bottle"]["path"]
|
bottle_path = entry["bottle"]["path"]
|
||||||
image_name = entry["thumbnail"].split(":")[1]
|
image_name = entry["thumbnail"].split(":")[1]
|
||||||
image_path = (
|
image_path = (
|
||||||
self.source.location / "bottles" / bottle_path / "grids" / image_name
|
self.source.location / "bottles" / bottle_path / "grids" / image_name
|
||||||
)
|
)
|
||||||
if image_path.is_file():
|
additional_data = {"local_image_path": image_path}
|
||||||
save_cover(values["game_id"], resize_cover(image_path))
|
|
||||||
|
|
||||||
# Produce game
|
# Produce game
|
||||||
yield game
|
yield (game, additional_data)
|
||||||
|
|
||||||
|
|
||||||
class BottlesSource(Source):
|
class BottlesSource(Source):
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ from hashlib import sha256
|
|||||||
from json import JSONDecodeError
|
from json import JSONDecodeError
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Optional, TypedDict, Generator
|
from typing import Optional, TypedDict
|
||||||
|
|
||||||
from src import shared
|
from src import shared
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
from src.importer.sources.source import (
|
from src.importer.sources.source import (
|
||||||
LinuxSource,
|
LinuxSource,
|
||||||
Source,
|
Source,
|
||||||
|
SourceIterationResult,
|
||||||
SourceIterator,
|
SourceIterator,
|
||||||
WindowsSource,
|
WindowsSource,
|
||||||
)
|
)
|
||||||
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
||||||
from src.utils.save_cover import resize_cover, save_cover
|
|
||||||
|
|
||||||
|
|
||||||
class HeroicLibraryEntry(TypedDict):
|
class HeroicLibraryEntry(TypedDict):
|
||||||
@@ -50,7 +50,9 @@ class HeroicSourceIterator(SourceIterator):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def game_from_library_entry(self, entry: HeroicLibraryEntry) -> Optional[Game]:
|
def game_from_library_entry(
|
||||||
|
self, entry: HeroicLibraryEntry
|
||||||
|
) -> SourceIterationResult:
|
||||||
"""Helper method used to build a Game from a Heroic library entry"""
|
"""Helper method used to build a Game from a Heroic library entry"""
|
||||||
|
|
||||||
# Skip games that are not installed
|
# Skip games that are not installed
|
||||||
@@ -72,20 +74,20 @@ class HeroicSourceIterator(SourceIterator):
|
|||||||
),
|
),
|
||||||
"executable": self.source.executable_format.format(app_name=app_name),
|
"executable": self.source.executable_format.format(app_name=app_name),
|
||||||
}
|
}
|
||||||
|
game = Game(values, allow_side_effects=False)
|
||||||
|
|
||||||
# Save image from the heroic cache
|
# Get the image path from the heroic cache
|
||||||
# Filenames are derived from the URL that heroic used to get the file
|
# Filenames are derived from the URL that heroic used to get the file
|
||||||
uri: str = entry["art_square"]
|
uri: str = entry["art_square"]
|
||||||
if service == "epic":
|
if service == "epic":
|
||||||
uri += "?h=400&resize=1&w=300"
|
uri += "?h=400&resize=1&w=300"
|
||||||
digest = sha256(uri.encode()).hexdigest()
|
digest = sha256(uri.encode()).hexdigest()
|
||||||
image_path = self.source.location / "images-cache" / digest
|
image_path = self.source.location / "images-cache" / digest
|
||||||
if image_path.is_file():
|
additional_data = {"local_image_path": image_path}
|
||||||
save_cover(values["game_id"], resize_cover(image_path))
|
|
||||||
|
|
||||||
return Game(values, allow_side_effects=False)
|
return (game, additional_data)
|
||||||
|
|
||||||
def generator_builder(self) -> Generator[Optional[Game], None, None]:
|
def generator_builder(self) -> SourceIterationResult:
|
||||||
"""Generator method producing games from all the Heroic sub-sources"""
|
"""Generator method producing games from all the Heroic sub-sources"""
|
||||||
|
|
||||||
for sub_source in self.sub_sources.values():
|
for sub_source in self.sub_sources.values():
|
||||||
@@ -102,12 +104,12 @@ class HeroicSourceIterator(SourceIterator):
|
|||||||
continue
|
continue
|
||||||
for entry in library:
|
for entry in library:
|
||||||
try:
|
try:
|
||||||
game = self.game_from_library_entry(entry)
|
result = self.game_from_library_entry(entry)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Skip invalid games
|
# Skip invalid games
|
||||||
logging.warning("Invalid Heroic game skipped in %s", str(file))
|
logging.warning("Invalid Heroic game skipped in %s", str(file))
|
||||||
continue
|
continue
|
||||||
yield game
|
yield result
|
||||||
|
|
||||||
|
|
||||||
class HeroicSource(Source):
|
class HeroicSource(Source):
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
from sqlite3 import connect
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from sqlite3 import connect
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Optional, Generator
|
|
||||||
|
|
||||||
from src import shared
|
from src import shared
|
||||||
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
from src.importer.sources.source import (
|
from src.importer.sources.source import (
|
||||||
Source,
|
|
||||||
SourceIterator,
|
|
||||||
LinuxSource,
|
LinuxSource,
|
||||||
|
Source,
|
||||||
|
SourceIterationResult,
|
||||||
|
SourceIterator,
|
||||||
WindowsSource,
|
WindowsSource,
|
||||||
)
|
)
|
||||||
|
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
||||||
|
|
||||||
|
|
||||||
class ItchSourceIterator(SourceIterator):
|
class ItchSourceIterator(SourceIterator):
|
||||||
source: "ItchSource"
|
source: "ItchSource"
|
||||||
|
|
||||||
def generator_builder(self) -> Generator[Optional[Game], None, None]:
|
def generator_builder(self) -> SourceIterationResult:
|
||||||
"""Generator method producing games"""
|
"""Generator method producing games"""
|
||||||
|
|
||||||
# Query the database
|
# Query the database
|
||||||
@@ -48,7 +48,7 @@ class ItchSourceIterator(SourceIterator):
|
|||||||
"game_id": self.source.game_id_format.format(game_id=row[0]),
|
"game_id": self.source.game_id_format.format(game_id=row[0]),
|
||||||
"executable": self.source.executable_format.format(cave_id=row[4]),
|
"executable": self.source.executable_format.format(cave_id=row[4]),
|
||||||
}
|
}
|
||||||
additional_data = (row[3], row[2])
|
additional_data = {"itch_cover_url": row[2], "itch_still_cover_url": row[3]}
|
||||||
game = Game(values, allow_side_effects=False)
|
game = Game(values, allow_side_effects=False)
|
||||||
yield (game, additional_data)
|
yield (game, additional_data)
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
from sqlite3 import connect
|
from sqlite3 import connect
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Optional, Generator
|
|
||||||
|
|
||||||
from src import shared
|
from src import shared
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
from src.importer.sources.source import LinuxSource, Source, SourceIterator
|
from src.importer.sources.source import (
|
||||||
|
LinuxSource,
|
||||||
|
Source,
|
||||||
|
SourceIterationResult,
|
||||||
|
SourceIterator,
|
||||||
|
)
|
||||||
from src.utils.decorators import replaced_by_path
|
from src.utils.decorators import replaced_by_path
|
||||||
from src.utils.save_cover import resize_cover, save_cover
|
|
||||||
|
|
||||||
|
|
||||||
class LutrisSourceIterator(SourceIterator):
|
class LutrisSourceIterator(SourceIterator):
|
||||||
source: "LutrisSource"
|
source: "LutrisSource"
|
||||||
|
|
||||||
def generator_builder(self) -> Generator[Optional[Game], None, None]:
|
def generator_builder(self) -> SourceIterationResult:
|
||||||
"""Generator method producing games"""
|
"""Generator method producing games"""
|
||||||
|
|
||||||
# Query the database
|
# Query the database
|
||||||
@@ -48,13 +51,12 @@ class LutrisSourceIterator(SourceIterator):
|
|||||||
}
|
}
|
||||||
game = Game(values, allow_side_effects=False)
|
game = Game(values, allow_side_effects=False)
|
||||||
|
|
||||||
# Save official image
|
# Get official image path
|
||||||
image_path = self.source.location / "covers" / "coverart" / f"{row[2]}.jpg"
|
image_path = self.source.location / "covers" / "coverart" / f"{row[2]}.jpg"
|
||||||
if image_path.exists():
|
additional_data = {"local_image_path": image_path}
|
||||||
save_cover(values["game_id"], resize_cover(image_path))
|
|
||||||
|
|
||||||
# Produce game
|
# Produce game
|
||||||
yield game
|
yield (game, additional_data)
|
||||||
|
|
||||||
|
|
||||||
class LutrisSource(Source):
|
class LutrisSource(Source):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from abc import abstractmethod
|
|||||||
from collections.abc import Iterable, Iterator
|
from collections.abc import Iterable, Iterator
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Generator, Any
|
from typing import Generator, Any, TypedDict
|
||||||
|
|
||||||
from src import shared
|
from src import shared
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from time import time
|
from time import time
|
||||||
from typing import Iterable, Optional, Generator
|
from typing import Iterable
|
||||||
|
|
||||||
from src import shared
|
from src import shared
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
from src.importer.sources.source import (
|
from src.importer.sources.source import (
|
||||||
LinuxSource,
|
LinuxSource,
|
||||||
Source,
|
Source,
|
||||||
|
SourceIterationResult,
|
||||||
SourceIterator,
|
SourceIterator,
|
||||||
WindowsSource,
|
WindowsSource,
|
||||||
)
|
)
|
||||||
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
from src.utils.decorators import replaced_by_env_path, replaced_by_path
|
||||||
from src.utils.save_cover import resize_cover, save_cover
|
|
||||||
from src.utils.steam import SteamHelper, SteamInvalidManifestError
|
from src.utils.steam import SteamHelper, SteamInvalidManifestError
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ class SteamSourceIterator(SourceIterator):
|
|||||||
)
|
)
|
||||||
return manifests
|
return manifests
|
||||||
|
|
||||||
def generator_builder(self) -> Generator[Optional[Game], None, None]:
|
def generator_builder(self) -> SourceIterationResult:
|
||||||
"""Generator method producing games"""
|
"""Generator method producing games"""
|
||||||
appid_cache = set()
|
appid_cache = set()
|
||||||
manifests = self.get_manifests()
|
manifests = self.get_manifests()
|
||||||
@@ -85,11 +85,10 @@ class SteamSourceIterator(SourceIterator):
|
|||||||
/ "librarycache"
|
/ "librarycache"
|
||||||
/ f"{appid}_library_600x900.jpg"
|
/ f"{appid}_library_600x900.jpg"
|
||||||
)
|
)
|
||||||
if image_path.is_file():
|
additional_data = {"local_image_path": image_path}
|
||||||
save_cover(game.game_id, resize_cover(image_path))
|
|
||||||
|
|
||||||
# Produce game
|
# Produce game
|
||||||
yield game
|
yield (game, additional_data)
|
||||||
|
|
||||||
|
|
||||||
class SteamSource(Source):
|
class SteamSource(Source):
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ from src.store.managers.display_manager import DisplayManager
|
|||||||
from src.store.managers.file_manager import FileManager
|
from src.store.managers.file_manager import FileManager
|
||||||
from src.store.managers.sgdb_manager import SGDBManager
|
from src.store.managers.sgdb_manager import SGDBManager
|
||||||
from src.store.managers.steam_api_manager import SteamAPIManager
|
from src.store.managers.steam_api_manager import SteamAPIManager
|
||||||
|
from src.store.managers.local_cover_manager import LocalCoverManager
|
||||||
|
from src.store.managers.itch_cover_manager import ItchCoverManager
|
||||||
from src.store.store import Store
|
from src.store.store import Store
|
||||||
from src.window import CartridgesWindow
|
from src.window import CartridgesWindow
|
||||||
|
|
||||||
@@ -85,7 +87,9 @@ class CartridgesApplication(Adw.Application):
|
|||||||
self.load_games_from_disk()
|
self.load_games_from_disk()
|
||||||
|
|
||||||
# Add rest of the managers for game imports
|
# Add rest of the managers for game imports
|
||||||
|
shared.store.add_manager(LocalCoverManager())
|
||||||
shared.store.add_manager(SteamAPIManager())
|
shared.store.add_manager(SteamAPIManager())
|
||||||
|
shared.store.add_manager(ItchCoverManager())
|
||||||
shared.store.add_manager(SGDBManager())
|
shared.store.add_manager(SGDBManager())
|
||||||
shared.store.add_manager(FileManager())
|
shared.store.add_manager(FileManager())
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class AsyncManager(Manager):
|
|||||||
self.cancellable = Gio.Cancellable()
|
self.cancellable = Gio.Cancellable()
|
||||||
|
|
||||||
def process_game(
|
def process_game(
|
||||||
self, game: Game, additional_data: tuple, callback: Callable[["Manager"], Any]
|
self, game: Game, additional_data: dict, callback: Callable[["Manager"], Any]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Create a task to process the game in a separate thread"""
|
"""Create a task to process the game in a separate thread"""
|
||||||
task = Task.new(None, self.cancellable, self._task_callback, (callback,))
|
task = Task.new(None, self.cancellable, self._task_callback, (callback,))
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class DisplayManager(Manager):
|
|||||||
|
|
||||||
run_after = set((SteamAPIManager, SGDBManager))
|
run_after = set((SteamAPIManager, SGDBManager))
|
||||||
|
|
||||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
def manager_logic(self, game: Game, _additional_data: dict) -> None:
|
||||||
# TODO decouple a game from its widget
|
# TODO decouple a game from its widget
|
||||||
shared.win.games[game.game_id] = game
|
shared.win.games[game.game_id] = game
|
||||||
game.update()
|
game.update()
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ class FileManager(AsyncManager):
|
|||||||
|
|
||||||
run_after = set((SteamAPIManager,))
|
run_after = set((SteamAPIManager,))
|
||||||
|
|
||||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
def manager_logic(self, game: Game, _additional_data: dict) -> None:
|
||||||
game.save()
|
game.save()
|
||||||
|
|||||||
19
src/store/managers/itch_cover_manager.py
Normal file
19
src/store/managers/itch_cover_manager.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from urllib3.exceptions import SSLError
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from requests import HTTPError
|
||||||
|
|
||||||
|
from src.game import Game
|
||||||
|
from src.store.managers.async_manager import AsyncManager
|
||||||
|
from src.store.managers.local_cover_manager import LocalCoverManager
|
||||||
|
|
||||||
|
|
||||||
|
class ItchCoverManager(AsyncManager):
|
||||||
|
"""Manager in charge of downloading the game's cover from itch.io"""
|
||||||
|
|
||||||
|
run_after = set((LocalCoverManager,))
|
||||||
|
retryable_on = set((HTTPError, SSLError))
|
||||||
|
|
||||||
|
def manager_logic(self, game: Game, additional_data: dict) -> None:
|
||||||
|
# TODO move itch cover logic here
|
||||||
|
pass
|
||||||
23
src/store/managers/local_cover_manager.py
Normal file
23
src/store/managers/local_cover_manager.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from src.game import Game
|
||||||
|
from src.store.managers.manager import Manager
|
||||||
|
from src.store.managers.steam_api_manager import SteamAPIManager
|
||||||
|
from src.utils.save_cover import save_cover, resize_cover
|
||||||
|
|
||||||
|
|
||||||
|
class LocalCoverManager(Manager):
|
||||||
|
"""Manager in charge of adding the local cover image of the game"""
|
||||||
|
|
||||||
|
run_after = set((SteamAPIManager,))
|
||||||
|
|
||||||
|
def manager_logic(self, game: Game, additional_data: dict) -> None:
|
||||||
|
# Ensure that the cover path is in the additional data
|
||||||
|
try:
|
||||||
|
image_path: Path = additional_data["local_image_path"]
|
||||||
|
except KeyError:
|
||||||
|
return
|
||||||
|
if not image_path.is_file():
|
||||||
|
return
|
||||||
|
# Save the image
|
||||||
|
save_cover(game.game_id, resize_cover(image_path))
|
||||||
@@ -49,7 +49,7 @@ class Manager:
|
|||||||
return errors
|
return errors
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def manager_logic(self, game: Game, additional_data: tuple) -> None:
|
def manager_logic(self, game: Game, additional_data: dict) -> None:
|
||||||
"""
|
"""
|
||||||
Manager specific logic triggered by the run method
|
Manager specific logic triggered by the run method
|
||||||
* Implemented by final child classes
|
* Implemented by final child classes
|
||||||
@@ -59,7 +59,7 @@ class Manager:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def execute_resilient_manager_logic(
|
def execute_resilient_manager_logic(
|
||||||
self, game: Game, additional_data: tuple, try_index: int = 0
|
self, game: Game, additional_data: dict, try_index: int = 0
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Execute the manager logic and handle its errors by reporting them or retrying"""
|
"""Execute the manager logic and handle its errors by reporting them or retrying"""
|
||||||
try:
|
try:
|
||||||
@@ -93,7 +93,7 @@ class Manager:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def process_game(
|
def process_game(
|
||||||
self, game: Game, additional_data: tuple, callback: Callable[["Manager"], Any]
|
self, game: Game, additional_data: dict, callback: Callable[["Manager"], Any]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Pass the game through the manager"""
|
"""Pass the game through the manager"""
|
||||||
self.execute_resilient_manager_logic(game, additional_data)
|
self.execute_resilient_manager_logic(game, additional_data)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ from urllib3.exceptions import SSLError
|
|||||||
|
|
||||||
from src.game import Game
|
from src.game import Game
|
||||||
from src.store.managers.async_manager import AsyncManager
|
from src.store.managers.async_manager import AsyncManager
|
||||||
|
from src.store.managers.itch_cover_manager import ItchCoverManager
|
||||||
|
from src.store.managers.local_cover_manager import LocalCoverManager
|
||||||
from src.store.managers.steam_api_manager import SteamAPIManager
|
from src.store.managers.steam_api_manager import SteamAPIManager
|
||||||
from src.utils.steamgriddb import HTTPError, SGDBAuthError, SGDBHelper
|
from src.utils.steamgriddb import HTTPError, SGDBAuthError, SGDBHelper
|
||||||
|
|
||||||
@@ -9,10 +11,10 @@ from src.utils.steamgriddb import HTTPError, SGDBAuthError, SGDBHelper
|
|||||||
class SGDBManager(AsyncManager):
|
class SGDBManager(AsyncManager):
|
||||||
"""Manager in charge of downloading a game's cover from steamgriddb"""
|
"""Manager in charge of downloading a game's cover from steamgriddb"""
|
||||||
|
|
||||||
run_after = set((SteamAPIManager,))
|
run_after = set((SteamAPIManager, LocalCoverManager, ItchCoverManager))
|
||||||
retryable_on = set((HTTPError, SSLError))
|
retryable_on = set((HTTPError, SSLError))
|
||||||
|
|
||||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
def manager_logic(self, game: Game, _additional_data: dict) -> None:
|
||||||
try:
|
try:
|
||||||
sgdb = SGDBHelper()
|
sgdb = SGDBHelper()
|
||||||
sgdb.conditionaly_update_cover(game)
|
sgdb.conditionaly_update_cover(game)
|
||||||
|
|||||||
@@ -15,11 +15,10 @@ class SteamAPIManager(AsyncManager):
|
|||||||
|
|
||||||
retryable_on = set((HTTPError, SSLError))
|
retryable_on = set((HTTPError, SSLError))
|
||||||
|
|
||||||
def manager_logic(self, game: Game, _additional_data: tuple) -> None:
|
def manager_logic(self, game: Game, _additional_data: dict) -> None:
|
||||||
# Skip non-steam games
|
# Skip non-steam games
|
||||||
if not game.source.startswith("steam_"):
|
if not game.source.startswith("steam_"):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get online metadata
|
# Get online metadata
|
||||||
appid = str(game.game_id).split("_")[-1]
|
appid = str(game.game_id).split("_")[-1]
|
||||||
steam = SteamHelper()
|
steam = SteamHelper()
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ class Pipeline(GObject.Object):
|
|||||||
"""Class representing a set of managers for a game"""
|
"""Class representing a set of managers for a game"""
|
||||||
|
|
||||||
game: Game
|
game: Game
|
||||||
additional_data: tuple
|
additional_data: dict
|
||||||
|
|
||||||
waiting: set[Manager]
|
waiting: set[Manager]
|
||||||
running: set[Manager]
|
running: set[Manager]
|
||||||
done: set[Manager]
|
done: set[Manager]
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, game: Game, additional_data: tuple, managers: Iterable[Manager]
|
self, game: Game, additional_data: dict, managers: Iterable[Manager]
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.game = game
|
self.game = game
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class Store:
|
|||||||
self.managers.add(manager)
|
self.managers.add(manager)
|
||||||
|
|
||||||
def add_game(
|
def add_game(
|
||||||
self, game: Game, additional_data: tuple, replace=False
|
self, game: Game, additional_data: dict, replace=False
|
||||||
) -> Pipeline | None:
|
) -> Pipeline | None:
|
||||||
"""Add a game to the app if not already there
|
"""Add a game to the app if not already there
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user