|
10 | 10 | from galaxy.api.consts import Feature, OSCompatibility
|
11 | 11 | from galaxy.api.errors import ImportInProgress, UnknownError
|
12 | 12 | from galaxy.api.jsonrpc import ApplicationError, NotificationClient, Server
|
13 |
| -from galaxy.api.types import Achievement, Authentication, FriendInfo, Game, GameTime, LocalGame, NextStep, GameLibrarySettings |
| 13 | +from galaxy.api.types import ( |
| 14 | + Achievement, Authentication, FriendInfo, Game, GameLibrarySettings, GameTime, LocalGame, NextStep, UserPresence |
| 15 | +) |
14 | 16 | from galaxy.task_manager import TaskManager
|
15 | 17 |
|
16 | 18 |
|
@@ -49,6 +51,7 @@ def __init__(self, platform, version, reader, writer, handshake_token):
|
49 | 51 | self._game_times_import_in_progress = False
|
50 | 52 | self._game_library_settings_import_in_progress = False
|
51 | 53 | self._os_compatibility_import_in_progress = False
|
| 54 | + self._user_presence_import_in_progress = False |
52 | 55 |
|
53 | 56 | self._persistent_cache = dict()
|
54 | 57 |
|
@@ -118,6 +121,9 @@ def __init__(self, platform, version, reader, writer, handshake_token):
|
118 | 121 | self._register_method("start_os_compatibility_import", self._start_os_compatibility_import)
|
119 | 122 | self._detect_feature(Feature.ImportOSCompatibility, ["get_os_compatibility"])
|
120 | 123 |
|
| 124 | + self._register_method("start_user_presence_import", self._start_user_presence_import) |
| 125 | + self._detect_feature(Feature.ImportUserPresence, ["get_user_presence"]) |
| 126 | + |
121 | 127 | async def __aenter__(self):
|
122 | 128 | return self
|
123 | 129 |
|
@@ -265,7 +271,7 @@ async def pass_login_credentials(self, step, credentials, cookies):
|
265 | 271 |
|
266 | 272 | """
|
267 | 273 | # temporary solution for persistent_cache vs credentials issue
|
268 |
| - self.persistent_cache['credentials'] = credentials # type: ignore |
| 274 | + self.persistent_cache["credentials"] = credentials # type: ignore |
269 | 275 |
|
270 | 276 | self._notification_client.notify("store_credentials", credentials, sensitive_params=True)
|
271 | 277 |
|
@@ -450,6 +456,27 @@ def _os_compatibility_import_failure(self, game_id: str, error: ApplicationError
|
450 | 456 | def _os_compatibility_import_finished(self) -> None:
|
451 | 457 | self._notification_client.notify("os_compatibility_import_finished", None)
|
452 | 458 |
|
| 459 | + def _user_presence_import_success(self, user_id: str, user_presence: UserPresence) -> None: |
| 460 | + self._notification_client.notify( |
| 461 | + "user_presence_import_success", |
| 462 | + { |
| 463 | + "user_id": user_id, |
| 464 | + "presence": user_presence |
| 465 | + } |
| 466 | + ) |
| 467 | + |
| 468 | + def _user_presence_import_failure(self, user_id: str, error: ApplicationError) -> None: |
| 469 | + self._notification_client.notify( |
| 470 | + "user_presence_import_failure", |
| 471 | + { |
| 472 | + "user_id": user_id, |
| 473 | + "error": error.json() |
| 474 | + } |
| 475 | + ) |
| 476 | + |
| 477 | + def _user_presence_import_finished(self) -> None: |
| 478 | + self._notification_client.notify("user_presence_import_finished", None) |
| 479 | + |
453 | 480 | def lost_authentication(self) -> None:
|
454 | 481 | """Notify the client that integration has lost authentication for the
|
455 | 482 | current user and is unable to perform actions which would require it.
|
@@ -912,6 +939,62 @@ async def get_os_compatibility(self, game_id: str, context: Any) -> Optional[OSC
|
912 | 939 | def os_compatibility_import_complete(self) -> None:
|
913 | 940 | """Override this method to handle operations after OS compatibility import is finished (like updating cache)."""
|
914 | 941 |
|
| 942 | + async def _start_user_presence_import(self, user_ids: List[str]) -> None: |
| 943 | + if self._user_presence_import_in_progress: |
| 944 | + raise ImportInProgress() |
| 945 | + |
| 946 | + context = await self.prepare_user_presence_context(user_ids) |
| 947 | + |
| 948 | + async def import_user_presence(user_id, context_) -> None: |
| 949 | + try: |
| 950 | + self._user_presence_import_success(user_id, await self.get_user_presence(user_id, context_)) |
| 951 | + except ApplicationError as error: |
| 952 | + self._user_presence_import_failure(user_id, error) |
| 953 | + except Exception: |
| 954 | + logging.exception("Unexpected exception raised in import_user_presence") |
| 955 | + self._user_presence_import_failure(user_id, UnknownError()) |
| 956 | + |
| 957 | + async def import_user_presence_set(user_ids_, context_) -> None: |
| 958 | + try: |
| 959 | + await asyncio.gather(*[ |
| 960 | + import_user_presence(user_id, context_) |
| 961 | + for user_id in user_ids_ |
| 962 | + ]) |
| 963 | + finally: |
| 964 | + self._user_presence_import_finished() |
| 965 | + self._user_presence_import_in_progress = False |
| 966 | + self.user_presence_import_complete() |
| 967 | + |
| 968 | + self._external_task_manager.create_task( |
| 969 | + import_user_presence_set(user_ids, context), |
| 970 | + "user presence import", |
| 971 | + handle_exceptions=False |
| 972 | + ) |
| 973 | + self._user_presence_import_in_progress = True |
| 974 | + |
| 975 | + async def prepare_user_presence_context(self, user_ids: List[str]) -> Any: |
| 976 | + """Override this method to prepare context for get_user_presence. |
| 977 | + This allows for optimizations like batch requests to platform API. |
| 978 | + Default implementation returns None. |
| 979 | +
|
| 980 | + :param user_ids: the ids of the users for whom presence information is imported |
| 981 | + :return: context |
| 982 | + """ |
| 983 | + return None |
| 984 | + |
| 985 | + async def get_user_presence(self, user_id: str, context: Any) -> UserPresence: |
| 986 | + """Override this method to return presence information for the user with the provided user_id. |
| 987 | + This method is called by import task initialized by GOG Galaxy Client. |
| 988 | +
|
| 989 | + :param user_id: the id of the user for whom presence information is imported |
| 990 | + :param context: the value returned from :meth:`prepare_user_presence_context` |
| 991 | + :return: UserPresence presence information of the provided user |
| 992 | + """ |
| 993 | + raise NotImplementedError() |
| 994 | + |
| 995 | + def user_presence_import_complete(self) -> None: |
| 996 | + """Override this method to handle operations after presence import is finished (like updating cache).""" |
| 997 | + |
915 | 998 |
|
916 | 999 | def create_and_run_plugin(plugin_class, argv):
|
917 | 1000 | """Call this method as an entry point for the implemented integration.
|
|
0 commit comments