Compare commits

...

5 Commits
0.56 ... 0.57

Author SHA1 Message Date
Rafal Makagon
8bf367d0f9 Increment vesion 2019-11-18 13:59:09 +01:00
Rafal Makagon
2cf83395fa fix parse sphinx parse error
+ other small imporvements in docs
2019-11-15 16:06:45 +01:00
Aliaksei Paulouski
4aa76b6e3d SDK-3137: friends and presence updates 2019-11-13 13:40:53 +01:00
Aleksej Pawlowskij
c03465e8f2 SDK-3145: Add optional profile and avatar url 2019-11-13 08:49:38 +01:00
mezzode
810a87718d Fix incorrect field name in GameTime docstring 2019-11-08 11:25:58 +01:00
5 changed files with 136 additions and 27 deletions

View File

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name="galaxy.plugin.api", name="galaxy.plugin.api",
version="0.56", version="0.57",
description="GOG Galaxy Integrations Python API", description="GOG Galaxy Integrations Python API",
author='Galaxy team', author='Galaxy team',
author_email='galaxy@gog.com', author_email='galaxy@gog.com',

View File

@@ -397,6 +397,13 @@ class Plugin:
params = {"user_id": user_id} params = {"user_id": user_id}
self._connection.send_notification("friend_removed", params) self._connection.send_notification("friend_removed", params)
def update_friend_info(self, user: UserInfo) -> None:
"""Notify the client about the updated friend information.
:param user: UserInfo of a friend whose info was updated
"""
self._connection.send_notification("friend_updated", params={"friend_info": user})
def update_game_time(self, game_time: GameTime) -> None: def update_game_time(self, game_time: GameTime) -> None:
"""Notify the client to update game time for a game. """Notify the client to update game time for a game.
@@ -405,6 +412,20 @@ class Plugin:
params = {"game_time": game_time} params = {"game_time": game_time}
self._connection.send_notification("game_time_updated", params) self._connection.send_notification("game_time_updated", params)
def update_user_presence(self, user_id: str, user_presence: UserPresence) -> None:
"""Notify the client about the updated user presence information.
:param user_id: the id of the user whose presence information is updated
:param user_presence: presence information of the specified user
"""
self._connection.send_notification(
"user_presence_updated",
{
"user_id": user_id,
"presence": user_presence
}
)
def _game_time_import_success(self, game_time: GameTime) -> None: def _game_time_import_success(self, game_time: GameTime) -> None:
params = {"game_time": game_time} params = {"game_time": game_time}
self._connection.send_notification("game_time_import_success", params) self._connection.send_notification("game_time_import_success", params)
@@ -557,10 +578,11 @@ class Plugin:
async def pass_login_credentials(self, step: str, credentials: Dict[str, str], cookies: List[Dict[str, str]]) \ async def pass_login_credentials(self, step: str, credentials: Dict[str, str], cookies: List[Dict[str, str]]) \
-> Union[NextStep, Authentication]: -> Union[NextStep, Authentication]:
"""This method is called if we return galaxy.api.types.NextStep from authenticate or from pass_login_credentials. """This method is called if we return :class:`~galaxy.api.types.NextStep` from :meth:`.authenticate`
or :meth:`.pass_login_credentials`.
This method's parameters provide the data extracted from the web page navigation that previous NextStep finished on. This method's parameters provide the data extracted from the web page navigation that previous NextStep finished on.
This method should either return galaxy.api.types.Authentication if the authentication is finished This method should either return :class:`~galaxy.api.types.Authentication` if the authentication is finished
or galaxy.api.types.NextStep if it requires going to another cef url. or :class:`~galaxy.api.types.NextStep` if it requires going to another cef url.
This method is called by the GOG Galaxy Client. This method is called by the GOG Galaxy Client.
:param step: deprecated. :param step: deprecated.

View File

@@ -61,9 +61,11 @@ class NextStep:
if not stored_credentials: if not stored_credentials:
return NextStep("web_session", PARAMS, cookies=COOKIES, js=JS) return NextStep("web_session", PARAMS, cookies=COOKIES, js=JS)
:param auth_params: configuration options: {"window_title": :class:`str`, "window_width": :class:`str`, "window_height": :class:`int`, "start_uri": :class:`int`, "end_uri_regex": :class:`str`} :param auth_params: configuration options: {"window_title": :class:`str`, "window_width": :class:`str`,
"window_height": :class:`int`, "start_uri": :class:`int`, "end_uri_regex": :class:`str`}
:param cookies: browser initial set of cookies :param cookies: browser initial set of cookies
:param js: a map of the url regex patterns into the list of *js* scripts that should be executed on every document at given step of internal browser authentication. :param js: a map of the url regex patterns into the list of *js* scripts that should be executed
on every document at given step of internal browser authentication.
""" """
next_step: str next_step: str
auth_params: Dict[str, str] auth_params: Dict[str, str]
@@ -142,7 +144,8 @@ class LocalGame:
class FriendInfo: class FriendInfo:
""" """
.. deprecated:: 0.56 .. deprecated:: 0.56
Use: :class:`UserInfo`. Use :class:`UserInfo`.
Information about a friend of the currently authenticated user. Information about a friend of the currently authenticated user.
:param user_id: id of the user :param user_id: id of the user
@@ -158,9 +161,14 @@ class UserInfo:
:param user_id: id of the user :param user_id: id of the user
:param user_name: username of the user :param user_name: username of the user
:param avatar_url: the URL of the user avatar
:param profile_url: the URL of the user profile
""" """
user_id: str user_id: str
user_name: str user_name: str
avatar_url: Optional[str]
profile_url: Optional[str]
@dataclass @dataclass
class GameTime: class GameTime:
@@ -169,7 +177,7 @@ class GameTime:
:param game_id: id of the related game :param game_id: id of the related game
:param time_played: the total time spent in the game in **minutes** :param time_played: the total time spent in the game in **minutes**
:param last_time_played: last time the game was played (**unix timestamp**) :param last_played_time: last time the game was played (**unix timestamp**)
""" """
game_id: str game_id: str
time_played: Optional[int] time_played: Optional[int]
@@ -182,7 +190,7 @@ class GameLibrarySettings:
:param game_id: id of the related game :param game_id: id of the related game
:param tags: collection of tags assigned to the game :param tags: collection of tags assigned to the game
:param hidden: indicates if the game should be hidden in GOG Galaxy application :param hidden: indicates if the game should be hidden in GOG Galaxy client
""" """
game_id: str game_id: str
tags: Optional[List[str]] tags: Optional[List[str]]
@@ -193,12 +201,18 @@ class GameLibrarySettings:
class UserPresence: class UserPresence:
"""Presence information of a user. """Presence information of a user.
The GOG Galaxy client will prefer to generate user status basing on `game_id` (or `game_title`)
and `in_game_status` fields but if plugin is not capable of delivering it then the `full_status` will be used if
available
:param presence_state: the state of the user :param presence_state: the state of the user
:param game_id: id of the game a user is currently in :param game_id: id of the game a user is currently in
:param game_title: name of the game a user is currently in :param game_title: name of the game a user is currently in
:param presence_status: detailed user's presence description :param in_game_status: status set by the game itself e.x. "In Main Menu"
:param full_status: full user status e.x. "Playing <title_name>: <in_game_status>"
""" """
presence_state: PresenceState presence_state: PresenceState
game_id: Optional[str] = None game_id: Optional[str] = None
game_title: Optional[str] = None game_title: Optional[str] = None
presence_status: Optional[str] = None in_game_status: Optional[str] = None
full_status: Optional[str] = None

View File

@@ -17,8 +17,8 @@ async def test_get_friends_success(plugin, read, write):
read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)] read.side_effect = [async_return_value(create_message(request)), async_return_value(b"", 10)]
plugin.get_friends.return_value = async_return_value([ plugin.get_friends.return_value = async_return_value([
UserInfo("3", "Jan"), UserInfo("3", "Jan", "https://avatar.url/u3", None),
UserInfo("5", "Ola") UserInfo("5", "Ola", None, "https://profile.url/u5")
]) ])
await plugin.run() await plugin.run()
plugin.get_friends.assert_called_with() plugin.get_friends.assert_called_with()
@@ -29,8 +29,8 @@ async def test_get_friends_success(plugin, read, write):
"id": "3", "id": "3",
"result": { "result": {
"friend_info_list": [ "friend_info_list": [
{"user_id": "3", "user_name": "Jan"}, {"user_id": "3", "user_name": "Jan", "avatar_url": "https://avatar.url/u3"},
{"user_id": "5", "user_name": "Ola"} {"user_id": "5", "user_name": "Ola", "profile_url": "https://profile.url/u5"}
] ]
} }
} }
@@ -64,7 +64,7 @@ async def test_get_friends_failure(plugin, read, write):
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_add_friend(plugin, write): async def test_add_friend(plugin, write):
friend = UserInfo("7", "Kuba") friend = UserInfo("7", "Kuba", avatar_url="https://avatar.url/kuba.jpg", profile_url="https://profile.url/kuba")
plugin.add_friend(friend) plugin.add_friend(friend)
await skip_loop() await skip_loop()
@@ -74,7 +74,12 @@ async def test_add_friend(plugin, write):
"jsonrpc": "2.0", "jsonrpc": "2.0",
"method": "friend_added", "method": "friend_added",
"params": { "params": {
"friend_info": {"user_id": "7", "user_name": "Kuba"} "friend_info": {
"user_id": "7",
"user_name": "Kuba",
"avatar_url": "https://avatar.url/kuba.jpg",
"profile_url": "https://profile.url/kuba"
}
} }
} }
] ]
@@ -94,3 +99,26 @@ async def test_remove_friend(plugin, write):
} }
} }
] ]
@pytest.mark.asyncio
async def test_update_friend_info(plugin, write):
plugin.update_friend_info(
UserInfo("7", "Jakub", avatar_url="https://new-avatar.url/kuba2.jpg", profile_url="https://profile.url/kuba")
)
await skip_loop()
assert get_messages(write) == [
{
"jsonrpc": "2.0",
"method": "friend_updated",
"params": {
"friend_info": {
"user_id": "7",
"user_name": "Jakub",
"avatar_url": "https://new-avatar.url/kuba2.jpg",
"profile_url": "https://profile.url/kuba"
}
}
}
]

View File

@@ -5,14 +5,14 @@ import pytest
from galaxy.api.consts import PresenceState from galaxy.api.consts import PresenceState
from galaxy.api.errors import BackendError from galaxy.api.errors import BackendError
from galaxy.api.types import UserPresence from galaxy.api.types import UserPresence
from galaxy.unittest.mock import async_return_value from galaxy.unittest.mock import async_return_value, skip_loop
from tests import create_message, get_messages from tests import create_message, get_messages
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_user_presence_success(plugin, read, write): async def test_get_user_presence_success(plugin, read, write):
context = "abc" context = "abc"
user_ids = ["666", "13", "42", "69"] user_ids = ["666", "13", "42", "69", "22"]
plugin.prepare_user_presence_context.return_value = async_return_value(context) plugin.prepare_user_presence_context.return_value = async_return_value(context)
request = { request = {
"jsonrpc": "2.0", "jsonrpc": "2.0",
@@ -26,25 +26,36 @@ async def test_get_user_presence_success(plugin, read, write):
PresenceState.Unknown, PresenceState.Unknown,
"game-id1", "game-id1",
None, None,
"unknown state" "unknown state",
None
)), )),
async_return_value(UserPresence( async_return_value(UserPresence(
PresenceState.Offline, PresenceState.Offline,
None, None,
None, None,
"Going to grandma's house" "Going to grandma's house",
None
)), )),
async_return_value(UserPresence( async_return_value(UserPresence(
PresenceState.Online, PresenceState.Online,
"game-id3", "game-id3",
"game-title3", "game-title3",
"Pew pew" "Pew pew",
None
)), )),
async_return_value(UserPresence( async_return_value(UserPresence(
PresenceState.Away, PresenceState.Away,
None, None,
"game-title4", "game-title4",
"AFKKTHXBY" "AFKKTHXBY",
None
)),
async_return_value(UserPresence(
PresenceState.Away,
None,
"game-title5",
None,
"Playing game-title5: In Menu"
)), )),
] ]
await plugin.run() await plugin.run()
@@ -67,7 +78,7 @@ async def test_get_user_presence_success(plugin, read, write):
"presence": { "presence": {
"presence_state": PresenceState.Unknown.value, "presence_state": PresenceState.Unknown.value,
"game_id": "game-id1", "game_id": "game-id1",
"presence_status": "unknown state" "in_game_status": "unknown state"
} }
} }
}, },
@@ -78,7 +89,7 @@ async def test_get_user_presence_success(plugin, read, write):
"user_id": "13", "user_id": "13",
"presence": { "presence": {
"presence_state": PresenceState.Offline.value, "presence_state": PresenceState.Offline.value,
"presence_status": "Going to grandma's house" "in_game_status": "Going to grandma's house"
} }
} }
}, },
@@ -91,7 +102,7 @@ async def test_get_user_presence_success(plugin, read, write):
"presence_state": PresenceState.Online.value, "presence_state": PresenceState.Online.value,
"game_id": "game-id3", "game_id": "game-id3",
"game_title": "game-title3", "game_title": "game-title3",
"presence_status": "Pew pew" "in_game_status": "Pew pew"
} }
} }
}, },
@@ -103,7 +114,19 @@ async def test_get_user_presence_success(plugin, read, write):
"presence": { "presence": {
"presence_state": PresenceState.Away.value, "presence_state": PresenceState.Away.value,
"game_title": "game-title4", "game_title": "game-title4",
"presence_status": "AFKKTHXBY" "in_game_status": "AFKKTHXBY"
}
}
},
{
"jsonrpc": "2.0",
"method": "user_presence_import_success",
"params": {
"user_id": "22",
"presence": {
"presence_state": PresenceState.Away.value,
"game_title": "game-title5",
"full_status": "Playing game-title5: In Menu"
} }
} }
}, },
@@ -229,3 +252,25 @@ async def test_import_already_in_progress_error(plugin, read, write):
"message": "Import already in progress" "message": "Import already in progress"
} }
} in responses } in responses
@pytest.mark.asyncio
async def test_update_user_presence(plugin, write):
plugin.update_user_presence("42", UserPresence(PresenceState.Online, "game-id", "game-title", "Pew pew"))
await skip_loop()
assert get_messages(write) == [
{
"jsonrpc": "2.0",
"method": "user_presence_updated",
"params": {
"user_id": "42",
"presence": {
"presence_state": PresenceState.Online.value,
"game_id": "game-id",
"game_title": "game-title",
"in_game_status": "Pew pew"
}
}
}
]