mirror of
https://github.com/lutris/lutris
synced 2024-09-04 23:13:35 +00:00
Distinguish between service type and service ID, where the ID contains extra information to distingish between different service accounts
This commit is contained in:
parent
3c6245546c
commit
5eb0d11dfa
|
@ -54,7 +54,7 @@ from lutris.util.http import HTTPError, Request
|
|||
from lutris.util.log import logger
|
||||
from lutris.util.steam.appmanifest import AppManifest, get_appmanifests
|
||||
from lutris.util.steam.config import get_steamapps_dirs
|
||||
from lutris.services import get_enabled_services
|
||||
from lutris.services import get_service
|
||||
from lutris.database.services import ServiceGameCollection
|
||||
|
||||
from .lutriswindow import LutrisWindow
|
||||
|
@ -663,7 +663,7 @@ class Application(Gtk.Application):
|
|||
if service:
|
||||
service_game = ServiceGameCollection.get_game(service, appid)
|
||||
if service_game:
|
||||
service = get_enabled_services()[service]()
|
||||
service = get_service(service)
|
||||
service.install(service_game)
|
||||
return 0
|
||||
|
||||
|
@ -747,8 +747,8 @@ class Application(Gtk.Application):
|
|||
@watch_errors(error_result=True)
|
||||
def on_game_install(self, game):
|
||||
"""Request installation of a game"""
|
||||
if game.service and game.service != "lutris":
|
||||
service = get_enabled_services()[game.service]()
|
||||
service = get_service(game.service) if game.service else None
|
||||
if service and service.type != "lutris":
|
||||
db_game = ServiceGameCollection.get_game(service.id, game.appid)
|
||||
if not db_game:
|
||||
logger.error("Can't find %s for %s", game.name, service.name)
|
||||
|
@ -780,7 +780,7 @@ class Application(Gtk.Application):
|
|||
|
||||
@watch_errors(error_result=True)
|
||||
def on_game_install_update(self, game):
|
||||
service = get_enabled_services()[game.service]()
|
||||
service = get_service(game.service)
|
||||
db_game = games_db.get_game_by_field(game.id, "id")
|
||||
installers = service.get_update_installers(db_game)
|
||||
if installers:
|
||||
|
@ -791,7 +791,7 @@ class Application(Gtk.Application):
|
|||
|
||||
@watch_errors(error_result=True)
|
||||
def on_game_install_dlc(self, game):
|
||||
service = get_enabled_services()[game.service]()
|
||||
service = get_service(game.service)
|
||||
db_game = games_db.get_game_by_field(game.id, "id")
|
||||
installers = service.get_dlc_installers_runner(db_game, db_game["runner"])
|
||||
if installers:
|
||||
|
|
|
@ -45,7 +45,7 @@ class ServicesBox(BaseConfigBox):
|
|||
)
|
||||
service = SERVICES[service_key]
|
||||
|
||||
icon = ScaledImage.get_runtime_icon_image(service.icon, service.id,
|
||||
icon = ScaledImage.get_runtime_icon_image(service.icon, service.type,
|
||||
scale_factor=self.get_scale_factor(),
|
||||
visible=True)
|
||||
box.pack_start(icon, False, False, 0)
|
||||
|
|
|
@ -448,16 +448,16 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
return True
|
||||
return self.filters["text"] in game["name"].lower()
|
||||
|
||||
def set_service(self, service_name):
|
||||
if self.service and self.service.id == service_name:
|
||||
def set_service(self, service_id):
|
||||
if self.service and self.service.id == service_id:
|
||||
return self.service
|
||||
if not service_name:
|
||||
if not service_id:
|
||||
self.service = None
|
||||
return
|
||||
try:
|
||||
self.service = services.SERVICES[service_name]()
|
||||
self.service = services.get_service(service_id)
|
||||
except KeyError:
|
||||
logger.error("Non existent service '%s'", service_name)
|
||||
logger.error("Non existent service '%s'", service_id)
|
||||
self.service = None
|
||||
return self.service
|
||||
|
||||
|
@ -469,10 +469,10 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
service_game[field] = lutris_game[field]
|
||||
return service_game
|
||||
|
||||
def get_service_games(self, service_name):
|
||||
"""Switch the current service to service_name and return games if available"""
|
||||
service_games = ServiceGameCollection.get_for_service(service_name)
|
||||
if service_name == "lutris":
|
||||
def get_service_games(self, service_id):
|
||||
"""Switch the current service to service_id and return games if available"""
|
||||
service_games = ServiceGameCollection.get_for_service(service_id)
|
||||
if service_id == "lutris":
|
||||
lutris_games = {g["slug"]: g for g in games_db.get_games()}
|
||||
else:
|
||||
lutris_games = {g["service_id"]: g for g in games_db.get_games(filters={"service": self.service.id})}
|
||||
|
@ -485,12 +485,12 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
]
|
||||
|
||||
def get_games_from_filters(self):
|
||||
service_name = self.filters.get("service")
|
||||
if service_name in services.SERVICES:
|
||||
service_id = self.filters.get("service")
|
||||
if service_id and services.service_type_for_id(service_id) in services.SERVICES:
|
||||
if self.service.online and not self.service.is_authenticated():
|
||||
self.show_label(_("Connect your %s account to access your games") % self.service.name)
|
||||
return []
|
||||
return self.get_service_games(service_name)
|
||||
return self.get_service_games(service_id)
|
||||
if self.filters.get("dynamic_category") in self.dynamic_categories_game_factories:
|
||||
return self.dynamic_categories_game_factories[self.filters["dynamic_category"]]()
|
||||
if self.filters.get("category") and self.filters["category"] != "all":
|
||||
|
@ -706,7 +706,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
def load_icon_type(self):
|
||||
"""Return the icon style depending on the type of view."""
|
||||
setting_key = "icon_type_%sview" % self.current_view_type
|
||||
if self.service and self.service.id != "lutris":
|
||||
if self.service and self.service.type != "lutris":
|
||||
setting_key += "_%s" % self.service.id
|
||||
self.icon_type = settings.read_setting(setting_key)
|
||||
return self.icon_type
|
||||
|
@ -715,7 +715,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
"""Save icon type to settings"""
|
||||
self.icon_type = icon_type
|
||||
setting_key = "icon_type_%sview" % self.current_view_type
|
||||
if self.service and self.service.id != "lutris":
|
||||
if self.service and self.service.type != "lutris":
|
||||
setting_key += "_%s" % self.service.id
|
||||
settings.write_setting(setting_key, self.icon_type)
|
||||
self.redraw_view()
|
||||
|
@ -967,8 +967,8 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
row_type = "category"
|
||||
self.filters[row_type] = row_id
|
||||
|
||||
service_name = self.filters.get("service")
|
||||
self.set_service(service_name)
|
||||
service_id = self.filters.get("service")
|
||||
self.set_service(service_id)
|
||||
self._bind_zoom_adjustment()
|
||||
self.redraw_view()
|
||||
|
||||
|
@ -1074,7 +1074,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
if self.service:
|
||||
logger.debug("Looking up %s game %s", self.service.id, game_id)
|
||||
db_game = games_db.get_game_for_service(self.service.id, game_id)
|
||||
if self.service.id == "lutris":
|
||||
if self.service.type == "lutris":
|
||||
if not db_game or not db_game["installed"]:
|
||||
self.service.install(game_id)
|
||||
return
|
||||
|
|
|
@ -4,7 +4,7 @@ import time
|
|||
from lutris.database import games
|
||||
from lutris.database.games import get_service_games
|
||||
from lutris.runners import get_runner_human_name
|
||||
from lutris.services import SERVICES
|
||||
from lutris.services import get_service
|
||||
from lutris.util.log import logger
|
||||
from lutris.util.strings import get_formatted_playtime, gtk_safe
|
||||
|
||||
|
@ -104,11 +104,15 @@ class StoreItem:
|
|||
"""Platform"""
|
||||
_platform = self._get_game_attribute("platform")
|
||||
|
||||
if not _platform and self.service in SERVICES:
|
||||
service = SERVICES[self.service]()
|
||||
_platforms = service.get_game_platforms(self._game_data)
|
||||
if _platforms:
|
||||
_platform = ", ".join(_platforms)
|
||||
if not _platform:
|
||||
try:
|
||||
service = get_service(self.service)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
_platforms = service.get_game_platforms(self._game_data)
|
||||
if _platforms:
|
||||
_platform = ", ".join(_platforms)
|
||||
|
||||
return gtk_safe(_platform)
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class GameBar(Gtk.Box):
|
|||
self.service = None
|
||||
if db_game.get("service"):
|
||||
try:
|
||||
self.service = services.SERVICES[db_game["service"]]()
|
||||
self.service = services.get_service(db_game["service"])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
|
|
@ -138,7 +138,7 @@ class ServiceSidebarRow(SidebarRow):
|
|||
|
||||
@property
|
||||
def sort_key(self):
|
||||
return SERVICE_INDICES[self.id]
|
||||
return SERVICE_INDICES[services.service_type_for_id(self.id)]
|
||||
|
||||
def get_actions(self):
|
||||
"""Return the definition of buttons to be added to the row"""
|
||||
|
@ -527,12 +527,11 @@ class LutrisSidebar(Gtk.ListBox):
|
|||
self.installed_runners = [runner.name for runner in runners.get_installed()]
|
||||
self.active_platforms = games_db.get_used_platforms()
|
||||
|
||||
for service_name, service_class in self.active_services.items():
|
||||
if service_name not in self.service_rows:
|
||||
service = service_class()
|
||||
for service_id, service in self.active_services.items():
|
||||
if service_id not in self.service_rows:
|
||||
row_class = OnlineServiceSidebarRow if service.online else ServiceSidebarRow
|
||||
service_row = row_class(service)
|
||||
self.service_rows[service_name] = service_row
|
||||
self.service_rows[service_id] = service_row
|
||||
insert_row(service_row)
|
||||
|
||||
for runner_name in self.installed_runners:
|
||||
|
|
|
@ -11,7 +11,7 @@ from lutris.installer.errors import ScriptingError
|
|||
from lutris.installer.installer_file import InstallerFile
|
||||
from lutris.installer.legacy import get_game_launcher
|
||||
from lutris.runners import import_runner
|
||||
from lutris.services import SERVICES
|
||||
from lutris.services import SERVICES, get_service
|
||||
from lutris.util.game_finder import find_linux_game_executable, find_windows_game_executable
|
||||
from lutris.util.gog import convert_gog_config_to_lutris, get_gog_config_from_path, get_gog_game_path
|
||||
from lutris.util.log import logger
|
||||
|
@ -52,12 +52,12 @@ class LutrisInstaller: # pylint: disable=too-many-instance-attributes
|
|||
if initial:
|
||||
return initial
|
||||
if "steam" in self.runner and "steam" in SERVICES:
|
||||
return SERVICES["steam"]()
|
||||
return get_service("steam")
|
||||
version = self.version.lower()
|
||||
if "humble" in version and "humblebundle" in SERVICES:
|
||||
return SERVICES["humblebundle"]()
|
||||
return get_service("humblebundle")
|
||||
if "gog" in version and "gog" in SERVICES:
|
||||
return SERVICES["gog"]()
|
||||
return get_service("gog")
|
||||
if "itch.io" in version and "itchio" in SERVICES:
|
||||
return SERVICES["itchio"]()
|
||||
|
||||
|
@ -69,12 +69,12 @@ class LutrisInstaller: # pylint: disable=too-many-instance-attributes
|
|||
if not self.service:
|
||||
return
|
||||
service_id = None
|
||||
if self.service.id == "steam":
|
||||
if self.service.type == "steam":
|
||||
service_id = installer.get("steamid") or installer.get("service_id")
|
||||
game_config = self.script.get("game", {})
|
||||
if self.service.id == "gog":
|
||||
if self.service.type == "gog":
|
||||
service_id = game_config.get("gogid") or installer.get("gogid") or installer.get("service_id")
|
||||
if self.service.id == "humblebundle":
|
||||
if self.service.type == "humblebundle":
|
||||
service_id = game_config.get("humbleid") or installer.get("humblestoreid") or installer.get("service_id")
|
||||
if self.service.id == "itchio":
|
||||
service_id = game_config.get("itchid") or installer.get("itchid") or installer.get("service_id")
|
||||
|
|
|
@ -26,7 +26,8 @@ DEFAULT_SERVICES = ["lutris", "gog", "egs", "ea_app", "ubisoft", "steam"]
|
|||
|
||||
|
||||
def get_services():
|
||||
"""Return a mapping of available services"""
|
||||
"""Return a mapping of available service classes by their respective
|
||||
service type names"""
|
||||
_services = {
|
||||
"lutris": LutrisService,
|
||||
"gog": GOGService,
|
||||
|
@ -64,8 +65,21 @@ if os.environ.get("LUTRIS_ENABLE_ALL_SERVICES"):
|
|||
SERVICES.update(WIP_SERVICES)
|
||||
|
||||
|
||||
def service_type_for_id(service_id):
|
||||
"""Derive the service type name from a service ID by dropping everything
|
||||
following the first tilde character"""
|
||||
return service_id.split("~", 1)[0]
|
||||
|
||||
|
||||
def get_service(service_id):
|
||||
"""Return a new service instance object for the given service ID
|
||||
|
||||
Raises `KeyError` if no matching service """
|
||||
return SERVICES[service_type_for_id(service_id)](id=service_id)
|
||||
|
||||
|
||||
def get_enabled_services():
|
||||
return {
|
||||
key: _class for key, _class in SERVICES.items()
|
||||
if settings.read_setting(key, section="services").lower() == "true"
|
||||
_type: _class(id=_type) for _type, _class in SERVICES.items()
|
||||
if settings.read_setting(_type, section="services").lower() == "true"
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class AmazonGame(ServiceGame):
|
|||
class AmazonService(OnlineService):
|
||||
"""Service class for Amazon"""
|
||||
|
||||
id = "amazon"
|
||||
type = "amazon"
|
||||
name = _("Amazon Prime Gaming")
|
||||
icon = "amazon"
|
||||
has_extras = False
|
||||
|
|
|
@ -73,7 +73,8 @@ class LutrisCoverartMedium(LutrisCoverart):
|
|||
|
||||
class BaseService(GObject.Object):
|
||||
"""Base class for local services"""
|
||||
id = NotImplemented
|
||||
type = NotImplemented # String identifier for this kind of service
|
||||
id: str # Identifier of a single account created at this service
|
||||
_matcher = None
|
||||
has_extras = False
|
||||
name = NotImplemented
|
||||
|
@ -95,6 +96,10 @@ class BaseService(GObject.Object):
|
|||
"service-logout": (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
}
|
||||
|
||||
def __init__(self, id):
|
||||
super().__init__()
|
||||
self.id = id
|
||||
|
||||
@property
|
||||
def matcher(self):
|
||||
if self._matcher:
|
||||
|
|
|
@ -87,7 +87,7 @@ class BattleNetGame(ServiceGame):
|
|||
class BattleNetService(BaseService):
|
||||
"""Service class for Battle.net"""
|
||||
|
||||
id = "battlenet"
|
||||
type = "battlenet"
|
||||
name = _("Battle.net")
|
||||
icon = "battlenet"
|
||||
runner = "wine"
|
||||
|
|
|
@ -24,7 +24,7 @@ class DolphinBanner(ServiceMedia):
|
|||
|
||||
|
||||
class DolphinService(BaseService):
|
||||
id = "dolphin"
|
||||
type = "dolphin"
|
||||
icon = "dolphin"
|
||||
name = _("Dolphin")
|
||||
local = True
|
||||
|
|
|
@ -131,7 +131,7 @@ class LegacyRenegotiationHTTPAdapter(requests.adapters.HTTPAdapter):
|
|||
class EAAppService(OnlineService):
|
||||
"""Service class for EA App"""
|
||||
|
||||
id = "ea_app"
|
||||
type = "ea_app"
|
||||
name = _("EA App")
|
||||
icon = "ea_app"
|
||||
client_installer = "ea-app"
|
||||
|
@ -159,8 +159,8 @@ class EAAppService(OnlineService):
|
|||
) % origin_redirect_uri
|
||||
login_user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0 QtWebEngine/5.8.0"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, id):
|
||||
super().__init__(id=id)
|
||||
|
||||
self.session = requests.session()
|
||||
self.session.mount("https://", LegacyRenegotiationHTTPAdapter())
|
||||
|
|
|
@ -132,7 +132,7 @@ class EGSGame(ServiceGame):
|
|||
class EpicGamesStoreService(OnlineService):
|
||||
"""Service class for Epic Games Store"""
|
||||
|
||||
id = "egs"
|
||||
type = "egs"
|
||||
name = _("Epic Games Store")
|
||||
login_window_width = 500
|
||||
login_window_height = 850
|
||||
|
@ -170,8 +170,8 @@ class EpicGamesStoreService(OnlineService):
|
|||
'Chrome/84.0.4147.38 Safari/537.36'
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, id):
|
||||
super().__init__(id)
|
||||
self.session = requests.session()
|
||||
self.session.headers['User-Agent'] = self.user_agent
|
||||
if os.path.exists(self.token_path):
|
||||
|
|
|
@ -54,7 +54,7 @@ class FlathubGame(ServiceGame):
|
|||
class FlathubService(BaseService):
|
||||
"""Service class for Flathub"""
|
||||
|
||||
id = "flathub"
|
||||
type = "flathub"
|
||||
name = _("Flathub")
|
||||
icon = "flathub"
|
||||
medias = {
|
||||
|
|
|
@ -54,7 +54,7 @@ class GOGGame(ServiceGame):
|
|||
@classmethod
|
||||
def new_from_gog_game(cls, gog_game):
|
||||
"""Return a GOG game instance from the API info"""
|
||||
service_game = GOGGame()
|
||||
service_game = cls()
|
||||
service_game.appid = str(gog_game["id"])
|
||||
service_game.slug = gog_game["slug"]
|
||||
service_game.name = gog_game["title"]
|
||||
|
@ -65,7 +65,7 @@ class GOGGame(ServiceGame):
|
|||
class GOGService(OnlineService):
|
||||
"""Service class for GOG"""
|
||||
|
||||
id = "gog"
|
||||
type = "gog"
|
||||
name = _("GOG")
|
||||
icon = "gog"
|
||||
has_extras = True
|
||||
|
@ -89,8 +89,8 @@ class GOGService(OnlineService):
|
|||
token_path = os.path.join(settings.CACHE_DIR, ".gog.token")
|
||||
cache_path = os.path.join(settings.CACHE_DIR, "gog-library.json")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, id):
|
||||
super().__init__(id)
|
||||
|
||||
gog_locales = {
|
||||
"en": "en-US",
|
||||
|
@ -133,7 +133,7 @@ class GOGService(OnlineService):
|
|||
if not self.is_connected():
|
||||
logger.error("User not connected to GOG")
|
||||
return
|
||||
games = [GOGGame.new_from_gog_game(game) for game in self.get_library()]
|
||||
games = [self.get_service_game(game) for game in self.get_library()]
|
||||
for game in games:
|
||||
game.save()
|
||||
self.match_games()
|
||||
|
|
|
@ -56,7 +56,7 @@ class HumbleBundleGame(ServiceGame):
|
|||
class HumbleBundleService(OnlineService):
|
||||
"""Service for Humble Bundle"""
|
||||
|
||||
id = "humblebundle"
|
||||
type = "humblebundle"
|
||||
_matcher = "humble"
|
||||
name = _("Humble Bundle")
|
||||
icon = "humblebundle"
|
||||
|
|
|
@ -74,7 +74,7 @@ class ItchIoGameTraits():
|
|||
class ItchIoService(OnlineService):
|
||||
"""Service class for itch.io"""
|
||||
|
||||
id = "itchio"
|
||||
type = "itchio"
|
||||
# According to their branding, "itch.io" is supposed to be all lowercase
|
||||
name = _("itch.io")
|
||||
icon = "itchio"
|
||||
|
|
|
@ -35,7 +35,7 @@ class LutrisGame(ServiceGame):
|
|||
class LutrisService(OnlineService):
|
||||
"""Service for Lutris games"""
|
||||
|
||||
id = "lutris"
|
||||
type = "lutris"
|
||||
name = _("Lutris")
|
||||
icon = "lutris"
|
||||
online = True
|
||||
|
|
|
@ -7,6 +7,6 @@ from lutris.services.base import BaseService
|
|||
|
||||
class MAMEService(BaseService):
|
||||
"""Service class for MAME"""
|
||||
id = "mame"
|
||||
type = "mame"
|
||||
name = _("MAME")
|
||||
icon = "mame"
|
||||
|
|
|
@ -125,7 +125,7 @@ class LegacyRenegotiationHTTPAdapter(requests.adapters.HTTPAdapter):
|
|||
class OriginService(OnlineService):
|
||||
"""Service class for EA Origin"""
|
||||
|
||||
id = "origin"
|
||||
type = "origin"
|
||||
name = _("Origin")
|
||||
icon = "origin"
|
||||
client_installer = "origin"
|
||||
|
@ -149,8 +149,8 @@ class OriginService(OnlineService):
|
|||
) % redirect_uri
|
||||
login_user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0 QtWebEngine/5.8.0"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, id):
|
||||
super().__init__(id)
|
||||
|
||||
self.session = requests.session()
|
||||
self.session.mount("https://", LegacyRenegotiationHTTPAdapter())
|
||||
|
|
|
@ -72,7 +72,7 @@ class SteamGame(ServiceGame):
|
|||
|
||||
|
||||
class SteamService(BaseService):
|
||||
id = "steam"
|
||||
type = "steam"
|
||||
name = _("Steam")
|
||||
icon = "steam-client"
|
||||
medias = {
|
||||
|
|
|
@ -21,7 +21,7 @@ class SteamWindowsGame(SteamGame):
|
|||
|
||||
|
||||
class SteamWindowsService(SteamService):
|
||||
id = "steamwindows"
|
||||
type = "steamwindows"
|
||||
name = _("Steam for Windows")
|
||||
runner = "wine"
|
||||
game_class = SteamWindowsGame
|
||||
|
|
|
@ -78,7 +78,7 @@ class UbisoftGame(ServiceGame):
|
|||
|
||||
class UbisoftConnectService(OnlineService):
|
||||
"""Service class for Ubisoft Connect"""
|
||||
id = "ubisoft"
|
||||
type = "ubisoft"
|
||||
name = _("Ubisoft Connect")
|
||||
icon = "ubisoft"
|
||||
runner = "wine"
|
||||
|
@ -105,8 +105,8 @@ class UbisoftConnectService(OnlineService):
|
|||
}
|
||||
default_format = "cover"
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, id):
|
||||
super().__init__(id)
|
||||
self.client = UbisoftConnectClient(self)
|
||||
|
||||
def auth_lost(self):
|
||||
|
|
|
@ -40,7 +40,7 @@ class XDGMedia(ServiceMedia):
|
|||
|
||||
|
||||
class XDGService(BaseService):
|
||||
id = "xdg"
|
||||
type = "xdg"
|
||||
name = _("Local")
|
||||
icon = "linux"
|
||||
online = False
|
||||
|
|
Loading…
Reference in a new issue