🎨 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:
GeoffreyCoulaud
2023-06-07 15:00:42 +02:00
parent 98f02da36c
commit 5dc6ec899a
18 changed files with 106 additions and 54 deletions

View File

@@ -120,7 +120,7 @@ class Importer:
# Handle the result depending on its type
if isinstance(iteration_result, Game):
game = iteration_result
additional_data = tuple()
additional_data = {}
elif isinstance(iteration_result, tuple):
game, additional_data = iteration_result
elif iteration_result is None:

View File

@@ -1,20 +1,23 @@
from pathlib import Path
from time import time
from typing import Optional, Generator
import yaml
from src import shared
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.save_cover import resize_cover, save_cover
class BottlesSourceIterator(SourceIterator):
source: "BottlesSource"
def generator_builder(self) -> Generator[Optional[Game], None, None]:
def generator_builder(self) -> SourceIterationResult:
"""Generator method producing games"""
data = (self.source.location / "library.yml").read_text("utf-8")
@@ -34,17 +37,16 @@ class BottlesSourceIterator(SourceIterator):
}
game = Game(values, allow_side_effects=False)
# Save official cover
# Get official cover path
bottle_path = entry["bottle"]["path"]
image_name = entry["thumbnail"].split(":")[1]
image_path = (
self.source.location / "bottles" / bottle_path / "grids" / image_name
)
if image_path.is_file():
save_cover(values["game_id"], resize_cover(image_path))
additional_data = {"local_image_path": image_path}
# Produce game
yield game
yield (game, additional_data)
class BottlesSource(Source):

View File

@@ -4,18 +4,18 @@ from hashlib import sha256
from json import JSONDecodeError
from pathlib import Path
from time import time
from typing import Optional, TypedDict, Generator
from typing import Optional, TypedDict
from src import shared
from src.game import Game
from src.importer.sources.source import (
LinuxSource,
Source,
SourceIterationResult,
SourceIterator,
WindowsSource,
)
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):
@@ -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"""
# Skip games that are not installed
@@ -72,20 +74,20 @@ class HeroicSourceIterator(SourceIterator):
),
"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
uri: str = entry["art_square"]
if service == "epic":
uri += "?h=400&resize=1&w=300"
digest = sha256(uri.encode()).hexdigest()
image_path = self.source.location / "images-cache" / digest
if image_path.is_file():
save_cover(values["game_id"], resize_cover(image_path))
additional_data = {"local_image_path": 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"""
for sub_source in self.sub_sources.values():
@@ -102,12 +104,12 @@ class HeroicSourceIterator(SourceIterator):
continue
for entry in library:
try:
game = self.game_from_library_entry(entry)
result = self.game_from_library_entry(entry)
except KeyError:
# Skip invalid games
logging.warning("Invalid Heroic game skipped in %s", str(file))
continue
yield game
yield result
class HeroicSource(Source):

View File

@@ -1,23 +1,23 @@
from sqlite3 import connect
from pathlib import Path
from sqlite3 import connect
from time import time
from typing import Optional, Generator
from src import shared
from src.utils.decorators import replaced_by_env_path, replaced_by_path
from src.game import Game
from src.importer.sources.source import (
Source,
SourceIterator,
LinuxSource,
Source,
SourceIterationResult,
SourceIterator,
WindowsSource,
)
from src.utils.decorators import replaced_by_env_path, replaced_by_path
class ItchSourceIterator(SourceIterator):
source: "ItchSource"
def generator_builder(self) -> Generator[Optional[Game], None, None]:
def generator_builder(self) -> SourceIterationResult:
"""Generator method producing games"""
# Query the database
@@ -48,7 +48,7 @@ class ItchSourceIterator(SourceIterator):
"game_id": self.source.game_id_format.format(game_id=row[0]),
"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)
yield (game, additional_data)

View File

@@ -1,18 +1,21 @@
from sqlite3 import connect
from time import time
from typing import Optional, Generator
from src import shared
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.save_cover import resize_cover, save_cover
class LutrisSourceIterator(SourceIterator):
source: "LutrisSource"
def generator_builder(self) -> Generator[Optional[Game], None, None]:
def generator_builder(self) -> SourceIterationResult:
"""Generator method producing games"""
# Query the database
@@ -48,13 +51,12 @@ class LutrisSourceIterator(SourceIterator):
}
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"
if image_path.exists():
save_cover(values["game_id"], resize_cover(image_path))
additional_data = {"local_image_path": image_path}
# Produce game
yield game
yield (game, additional_data)
class LutrisSource(Source):

View File

@@ -3,7 +3,7 @@ from abc import abstractmethod
from collections.abc import Iterable, Iterator
from functools import wraps
from pathlib import Path
from typing import Generator, Any
from typing import Generator, Any, TypedDict
from src import shared
from src.game import Game

View File

@@ -1,18 +1,18 @@
import re
from pathlib import Path
from time import time
from typing import Iterable, Optional, Generator
from typing import Iterable
from src import shared
from src.game import Game
from src.importer.sources.source import (
LinuxSource,
Source,
SourceIterationResult,
SourceIterator,
WindowsSource,
)
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
@@ -44,7 +44,7 @@ class SteamSourceIterator(SourceIterator):
)
return manifests
def generator_builder(self) -> Generator[Optional[Game], None, None]:
def generator_builder(self) -> SourceIterationResult:
"""Generator method producing games"""
appid_cache = set()
manifests = self.get_manifests()
@@ -85,11 +85,10 @@ class SteamSourceIterator(SourceIterator):
/ "librarycache"
/ f"{appid}_library_600x900.jpg"
)
if image_path.is_file():
save_cover(game.game_id, resize_cover(image_path))
additional_data = {"local_image_path": image_path}
# Produce game
yield game
yield (game, additional_data)
class SteamSource(Source):