mirror of
https://github.com/gogcom/galaxy-integrations-python-api.git
synced 2026-01-01 03:18:25 -05:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
223adf6a38 | ||
|
|
bfb63a42bd | ||
|
|
53b3062719 | ||
|
|
49eb10ac8a | ||
|
|
10ecef791f | ||
|
|
ce193f39bc |
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 GOG sp. z o.o.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
2
setup.py
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="galaxy.plugin.api",
|
name="galaxy.plugin.api",
|
||||||
version="0.41",
|
version="0.43",
|
||||||
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',
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ class Feature(Enum):
|
|||||||
ImportUsers = "ImportUsers"
|
ImportUsers = "ImportUsers"
|
||||||
VerifyGame = "VerifyGame"
|
VerifyGame = "VerifyGame"
|
||||||
ImportFriends = "ImportFriends"
|
ImportFriends = "ImportFriends"
|
||||||
|
ShutdownPlatformClient = "ShutdownPlatformClient"
|
||||||
|
|
||||||
|
|
||||||
class LicenseType(Enum):
|
class LicenseType(Enum):
|
||||||
@@ -116,11 +117,3 @@ class LocalGameState(Flag):
|
|||||||
None_ = 0
|
None_ = 0
|
||||||
Installed = 1
|
Installed = 1
|
||||||
Running = 2
|
Running = 2
|
||||||
|
|
||||||
|
|
||||||
class PresenceState(Enum):
|
|
||||||
""""Possible states that a user can be in."""
|
|
||||||
Unknown = "Unknown"
|
|
||||||
Online = "online"
|
|
||||||
Offline = "offline"
|
|
||||||
Away = "away"
|
|
||||||
|
|||||||
@@ -5,16 +5,17 @@ import logging.handlers
|
|||||||
import dataclasses
|
import dataclasses
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
from itertools import count
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from typing import Any, List, Dict, Optional, Union
|
from typing import Any, List, Dict, Optional, Union
|
||||||
|
|
||||||
from galaxy.api.types import Achievement, Game, LocalGame, FriendInfo, GameTime, UserInfo, Room
|
from galaxy.api.types import Achievement, Game, LocalGame, FriendInfo, GameTime
|
||||||
|
|
||||||
from galaxy.api.jsonrpc import Server, NotificationClient, ApplicationError
|
from galaxy.api.jsonrpc import Server, NotificationClient, ApplicationError
|
||||||
from galaxy.api.consts import Feature
|
from galaxy.api.consts import Feature
|
||||||
from galaxy.api.errors import UnknownError, ImportInProgress
|
from galaxy.api.errors import UnknownError, ImportInProgress
|
||||||
from galaxy.api.types import Authentication, NextStep, Message
|
from galaxy.api.types import Authentication, NextStep
|
||||||
|
|
||||||
|
|
||||||
class JSONEncoder(json.JSONEncoder):
|
class JSONEncoder(json.JSONEncoder):
|
||||||
@@ -56,6 +57,9 @@ class Plugin:
|
|||||||
|
|
||||||
self._persistent_cache = dict()
|
self._persistent_cache = dict()
|
||||||
|
|
||||||
|
self._tasks = OrderedDict()
|
||||||
|
self._task_counter = count()
|
||||||
|
|
||||||
# internal
|
# internal
|
||||||
self._register_method("shutdown", self._shutdown, internal=True)
|
self._register_method("shutdown", self._shutdown, internal=True)
|
||||||
self._register_method("get_capabilities", self._get_capabilities, internal=True)
|
self._register_method("get_capabilities", self._get_capabilities, internal=True)
|
||||||
@@ -107,46 +111,17 @@ class Plugin:
|
|||||||
self.uninstall_game,
|
self.uninstall_game,
|
||||||
feature=Feature.UninstallGame
|
feature=Feature.UninstallGame
|
||||||
)
|
)
|
||||||
|
self._register_notification(
|
||||||
|
"shutdown_platform_client",
|
||||||
|
self.shutdown_platform_client,
|
||||||
|
feature=Feature.ShutdownPlatformClient
|
||||||
|
)
|
||||||
self._register_method(
|
self._register_method(
|
||||||
"import_friends",
|
"import_friends",
|
||||||
self.get_friends,
|
self.get_friends,
|
||||||
result_name="friend_info_list",
|
result_name="friend_info_list",
|
||||||
feature=Feature.ImportFriends
|
feature=Feature.ImportFriends
|
||||||
)
|
)
|
||||||
self._register_method(
|
|
||||||
"import_user_infos",
|
|
||||||
self.get_users,
|
|
||||||
result_name="user_info_list",
|
|
||||||
feature=Feature.ImportUsers
|
|
||||||
)
|
|
||||||
self._register_method(
|
|
||||||
"send_message",
|
|
||||||
self.send_message,
|
|
||||||
feature=Feature.Chat
|
|
||||||
)
|
|
||||||
self._register_method(
|
|
||||||
"mark_as_read",
|
|
||||||
self.mark_as_read,
|
|
||||||
feature=Feature.Chat
|
|
||||||
)
|
|
||||||
self._register_method(
|
|
||||||
"import_rooms",
|
|
||||||
self.get_rooms,
|
|
||||||
result_name="rooms",
|
|
||||||
feature=Feature.Chat
|
|
||||||
)
|
|
||||||
self._register_method(
|
|
||||||
"import_room_history_from_message",
|
|
||||||
self.get_room_history_from_message,
|
|
||||||
result_name="messages",
|
|
||||||
feature=Feature.Chat
|
|
||||||
)
|
|
||||||
self._register_method(
|
|
||||||
"import_room_history_from_timestamp",
|
|
||||||
self.get_room_history_from_timestamp,
|
|
||||||
result_name="messages",
|
|
||||||
feature=Feature.Chat
|
|
||||||
)
|
|
||||||
self._register_method(
|
self._register_method(
|
||||||
"import_game_times",
|
"import_game_times",
|
||||||
self.get_game_times,
|
self.get_game_times,
|
||||||
@@ -215,6 +190,24 @@ class Plugin:
|
|||||||
if self._pass_control_task is not None:
|
if self._pass_control_task is not None:
|
||||||
await self._pass_control_task
|
await self._pass_control_task
|
||||||
|
|
||||||
|
def create_task(self, coro, description):
|
||||||
|
"""Wrapper around asyncio.create_task - takes care of canceling tasks on shutdown"""
|
||||||
|
async def task_wrapper(task_id):
|
||||||
|
try:
|
||||||
|
return await coro
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
logging.debug("Canceled task %d (%s)", task_id, description)
|
||||||
|
except Exception:
|
||||||
|
logging.exception("Exception raised in task %d (%s)", task_id, description)
|
||||||
|
finally:
|
||||||
|
del self._tasks[task_id]
|
||||||
|
|
||||||
|
task_id = next(self._task_counter)
|
||||||
|
logging.debug("Creating task %d (%s)", task_id, description)
|
||||||
|
task = asyncio.create_task(task_wrapper(task_id))
|
||||||
|
self._tasks[task_id] = task
|
||||||
|
return task
|
||||||
|
|
||||||
async def _pass_control(self):
|
async def _pass_control(self):
|
||||||
while self._active:
|
while self._active:
|
||||||
try:
|
try:
|
||||||
@@ -228,6 +221,8 @@ class Plugin:
|
|||||||
self._server.stop()
|
self._server.stop()
|
||||||
self._active = False
|
self._active = False
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
|
for task in self._tasks.values():
|
||||||
|
task.cancel()
|
||||||
|
|
||||||
def _get_capabilities(self):
|
def _get_capabilities(self):
|
||||||
return {
|
return {
|
||||||
@@ -412,26 +407,6 @@ class Plugin:
|
|||||||
params = {"user_id": user_id}
|
params = {"user_id": user_id}
|
||||||
self._notification_client.notify("friend_removed", params)
|
self._notification_client.notify("friend_removed", params)
|
||||||
|
|
||||||
def update_room(
|
|
||||||
self,
|
|
||||||
room_id: str,
|
|
||||||
unread_message_count: Optional[int]=None,
|
|
||||||
new_messages: Optional[List[Message]]=None
|
|
||||||
) -> None:
|
|
||||||
"""WIP, Notify the client to update the information regarding
|
|
||||||
a chat room that the currently authenticated user is in.
|
|
||||||
|
|
||||||
:param room_id: id of the room to update
|
|
||||||
:param unread_message_count: information about the new unread message count in the room
|
|
||||||
:param new_messages: list of new messages that the user received
|
|
||||||
"""
|
|
||||||
params = {"room_id": room_id}
|
|
||||||
if unread_message_count is not None:
|
|
||||||
params["unread_message_count"] = unread_message_count
|
|
||||||
if new_messages is not None:
|
|
||||||
params["messages"] = new_messages
|
|
||||||
self._notification_client.notify("chat_room_updated", params)
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
@@ -718,6 +693,11 @@ class Plugin:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
async def shutdown_platform_client(self) -> None:
|
||||||
|
"""Override this method to gracefully terminate platform client.
|
||||||
|
This method is called by the GOG Galaxy Client."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
async def get_friends(self) -> List[FriendInfo]:
|
async def get_friends(self) -> List[FriendInfo]:
|
||||||
"""Override this method to return the friends list
|
"""Override this method to return the friends list
|
||||||
of the currently authenticated user.
|
of the currently authenticated user.
|
||||||
@@ -738,57 +718,6 @@ class Plugin:
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
async def get_users(self, user_id_list: List[str]) -> List[UserInfo]:
|
|
||||||
"""WIP, Override this method to return the list of users matching the provided ids.
|
|
||||||
This method is called by the GOG Galaxy Client.
|
|
||||||
|
|
||||||
:param user_id_list: list of user ids
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
async def send_message(self, room_id: str, message_text: str) -> None:
|
|
||||||
"""WIP, Override this method to send message to a chat room.
|
|
||||||
This method is called by the GOG Galaxy Client.
|
|
||||||
|
|
||||||
:param room_id: id of the room to which the message should be sent
|
|
||||||
:param message_text: text which should be sent in the message
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
async def mark_as_read(self, room_id: str, last_message_id: str) -> None:
|
|
||||||
"""WIP, Override this method to mark messages in a chat room as read up to the id provided in the parameter.
|
|
||||||
This method is called by the GOG Galaxy Client.
|
|
||||||
|
|
||||||
:param room_id: id of the room
|
|
||||||
:param last_message_id: id of the last message; room is marked as read only if this id matches
|
|
||||||
the last message id known to the client
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
async def get_rooms(self) -> List[Room]:
|
|
||||||
"""WIP, Override this method to return the chat rooms in which the user is currently in.
|
|
||||||
This method is called by the GOG Galaxy Client
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
async def get_room_history_from_message(self, room_id: str, message_id: str) -> List[Message]:
|
|
||||||
"""WIP, Override this method to return the chat room history since the message provided in parameter.
|
|
||||||
This method is called by the GOG Galaxy Client.
|
|
||||||
|
|
||||||
:param room_id: id of the room
|
|
||||||
:param message_id: id of the message since which the history should be retrieved
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
async def get_room_history_from_timestamp(self, room_id: str, from_timestamp: int) -> List[Message]:
|
|
||||||
"""WIP, Override this method to return the chat room history since the timestamp provided in parameter.
|
|
||||||
This method is called by the GOG Galaxy Client.
|
|
||||||
|
|
||||||
:param room_id: id of the room
|
|
||||||
:param from_timestamp: timestamp since which the history should be retrieved
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
async def get_game_times(self) -> List[GameTime]:
|
async def get_game_times(self) -> List[GameTime]:
|
||||||
"""
|
"""
|
||||||
.. deprecated:: 0.33
|
.. deprecated:: 0.33
|
||||||
@@ -884,6 +813,9 @@ def create_and_run_plugin(plugin_class, argv):
|
|||||||
await plugin.run()
|
await plugin.run()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if sys.platform == "win32":
|
||||||
|
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
|
||||||
|
|
||||||
asyncio.run(coroutine())
|
asyncio.run(coroutine())
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.exception("Error while running plugin")
|
logging.exception("Error while running plugin")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List, Dict, Optional
|
from typing import List, Dict, Optional
|
||||||
|
|
||||||
from galaxy.api.consts import LicenseType, LocalGameState, PresenceState
|
from galaxy.api.consts import LicenseType, LocalGameState
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Authentication():
|
class Authentication():
|
||||||
@@ -130,34 +130,6 @@ class LocalGame():
|
|||||||
game_id: str
|
game_id: str
|
||||||
local_game_state: LocalGameState
|
local_game_state: LocalGameState
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Presence():
|
|
||||||
"""Information about a presence of a user.
|
|
||||||
|
|
||||||
:param presence_state: the state in which the user's presence is
|
|
||||||
:param game_id: id of the game which the user is currently playing
|
|
||||||
:param presence_status: optional attached string with the detailed description of the user's presence
|
|
||||||
"""
|
|
||||||
presence_state: PresenceState
|
|
||||||
game_id: Optional[str] = None
|
|
||||||
presence_status: Optional[str] = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class UserInfo():
|
|
||||||
"""Detailed information about a user.
|
|
||||||
|
|
||||||
:param user_id: of the user
|
|
||||||
:param is_friend: whether the user is a friend of the currently authenticated user
|
|
||||||
:param user_name: of the user
|
|
||||||
:param avatar_url: to the avatar of the user
|
|
||||||
:param presence: about the users presence
|
|
||||||
"""
|
|
||||||
user_id: str
|
|
||||||
is_friend: bool
|
|
||||||
user_name: str
|
|
||||||
avatar_url: str
|
|
||||||
presence: Presence
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class FriendInfo():
|
class FriendInfo():
|
||||||
"""Information about a friend of the currently authenticated user.
|
"""Information about a friend of the currently authenticated user.
|
||||||
@@ -168,32 +140,6 @@ class FriendInfo():
|
|||||||
user_id: str
|
user_id: str
|
||||||
user_name: str
|
user_name: str
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Room():
|
|
||||||
"""WIP, Chatroom.
|
|
||||||
|
|
||||||
:param room_id: id of the room
|
|
||||||
:param unread_message_count: number of unread messages in the room
|
|
||||||
:param last_message_id: id of the last message in the room
|
|
||||||
"""
|
|
||||||
room_id: str
|
|
||||||
unread_message_count: int
|
|
||||||
last_message_id: str
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Message():
|
|
||||||
"""WIP, A chatroom message.
|
|
||||||
|
|
||||||
:param message_id: id of the message
|
|
||||||
:param sender_id: id of the sender of the message
|
|
||||||
:param sent_time: time at which the message was sent
|
|
||||||
:param message_text: text attached to the message
|
|
||||||
"""
|
|
||||||
message_id: str
|
|
||||||
sender_id: str
|
|
||||||
sent_time: int
|
|
||||||
message_text: str
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class GameTime():
|
class GameTime():
|
||||||
"""Game time of a game, defines the total time spent in the game
|
"""Game time of a game, defines the total time spent in the game
|
||||||
|
|||||||
@@ -42,13 +42,8 @@ def plugin(reader, writer):
|
|||||||
"install_game",
|
"install_game",
|
||||||
"uninstall_game",
|
"uninstall_game",
|
||||||
"get_friends",
|
"get_friends",
|
||||||
"get_users",
|
"get_game_times",
|
||||||
"send_message",
|
"shutdown_platform_client"
|
||||||
"mark_as_read",
|
|
||||||
"get_rooms",
|
|
||||||
"get_room_history_from_message",
|
|
||||||
"get_room_history_from_timestamp",
|
|
||||||
"get_game_times"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
methods = (
|
methods = (
|
||||||
|
|||||||
@@ -1,354 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
import json
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from galaxy.api.types import Room, Message
|
|
||||||
from galaxy.api.errors import (
|
|
||||||
UnknownError, AuthenticationRequired, BackendNotAvailable, BackendTimeout, BackendError,
|
|
||||||
TooManyMessagesSent, IncoherentLastMessage, MessageNotFound
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_send_message_success(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "3",
|
|
||||||
"method": "send_message",
|
|
||||||
"params": {
|
|
||||||
"room_id": "14",
|
|
||||||
"message": "Hello!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.send_message.coro.return_value = None
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.send_message.assert_called_with(room_id="14", message="Hello!")
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "3",
|
|
||||||
"result": None
|
|
||||||
}
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("error,code,message", [
|
|
||||||
pytest.param(UnknownError, 0, "Unknown error", id="unknown_error"),
|
|
||||||
pytest.param(AuthenticationRequired, 1, "Authentication required", id="not_authenticated"),
|
|
||||||
pytest.param(BackendNotAvailable, 2, "Backend not available", id="backend_not_available"),
|
|
||||||
pytest.param(BackendTimeout, 3, "Backend timed out", id="backend_timeout"),
|
|
||||||
pytest.param(BackendError, 4, "Backend error", id="backend_error"),
|
|
||||||
pytest.param(TooManyMessagesSent, 300, "Too many messages sent", id="too_many_messages")
|
|
||||||
])
|
|
||||||
def test_send_message_failure(plugin, read, write, error, code, message):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "6",
|
|
||||||
"method": "send_message",
|
|
||||||
"params": {
|
|
||||||
"room_id": "15",
|
|
||||||
"message": "Bye"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.send_message.coro.side_effect = error()
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.send_message.assert_called_with(room_id="15", message="Bye")
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "6",
|
|
||||||
"error": {
|
|
||||||
"code": code,
|
|
||||||
"message": message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_mark_as_read_success(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "7",
|
|
||||||
"method": "mark_as_read",
|
|
||||||
"params": {
|
|
||||||
"room_id": "14",
|
|
||||||
"last_message_id": "67"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.mark_as_read.coro.return_value = None
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.mark_as_read.assert_called_with(room_id="14", last_message_id="67")
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "7",
|
|
||||||
"result": None
|
|
||||||
}
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("error,code,message", [
|
|
||||||
pytest.param(UnknownError, 0, "Unknown error", id="unknown_error"),
|
|
||||||
pytest.param(AuthenticationRequired, 1, "Authentication required", id="not_authenticated"),
|
|
||||||
pytest.param(BackendNotAvailable, 2, "Backend not available", id="backend_not_available"),
|
|
||||||
pytest.param(BackendTimeout, 3, "Backend timed out", id="backend_timeout"),
|
|
||||||
pytest.param(BackendError, 4, "Backend error", id="backend_error"),
|
|
||||||
pytest.param(
|
|
||||||
IncoherentLastMessage,
|
|
||||||
400,
|
|
||||||
"Different last message id on backend",
|
|
||||||
id="incoherent_last_message"
|
|
||||||
)
|
|
||||||
])
|
|
||||||
def test_mark_as_read_failure(plugin, read, write, error, code, message):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "4",
|
|
||||||
"method": "mark_as_read",
|
|
||||||
"params": {
|
|
||||||
"room_id": "18",
|
|
||||||
"last_message_id": "7"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.mark_as_read.coro.side_effect = error()
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.mark_as_read.assert_called_with(room_id="18", last_message_id="7")
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "4",
|
|
||||||
"error": {
|
|
||||||
"code": code,
|
|
||||||
"message": message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_get_rooms_success(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "2",
|
|
||||||
"method": "import_rooms"
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_rooms.coro.return_value = [
|
|
||||||
Room("13", 0, None),
|
|
||||||
Room("15", 34, "8")
|
|
||||||
]
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_rooms.assert_called_with()
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "2",
|
|
||||||
"result": {
|
|
||||||
"rooms": [
|
|
||||||
{
|
|
||||||
"room_id": "13",
|
|
||||||
"unread_message_count": 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"room_id": "15",
|
|
||||||
"unread_message_count": 34,
|
|
||||||
"last_message_id": "8"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_get_rooms_failure(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "9",
|
|
||||||
"method": "import_rooms"
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_rooms.coro.side_effect = UnknownError()
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_rooms.assert_called_with()
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "9",
|
|
||||||
"error": {
|
|
||||||
"code": 0,
|
|
||||||
"message": "Unknown error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_get_room_history_from_message_success(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "2",
|
|
||||||
"method": "import_room_history_from_message",
|
|
||||||
"params": {
|
|
||||||
"room_id": "34",
|
|
||||||
"message_id": "66"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_room_history_from_message.coro.return_value = [
|
|
||||||
Message("13", "149", 1549454837, "Hello"),
|
|
||||||
Message("14", "812", 1549454899, "Hi")
|
|
||||||
]
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_room_history_from_message.assert_called_with(room_id="34", message_id="66")
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "2",
|
|
||||||
"result": {
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"message_id": "13",
|
|
||||||
"sender_id": "149",
|
|
||||||
"sent_time": 1549454837,
|
|
||||||
"message_text": "Hello"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"message_id": "14",
|
|
||||||
"sender_id": "812",
|
|
||||||
"sent_time": 1549454899,
|
|
||||||
"message_text": "Hi"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("error,code,message", [
|
|
||||||
pytest.param(UnknownError, 0, "Unknown error", id="unknown_error"),
|
|
||||||
pytest.param(AuthenticationRequired, 1, "Authentication required", id="not_authenticated"),
|
|
||||||
pytest.param(BackendNotAvailable, 2, "Backend not available", id="backend_not_available"),
|
|
||||||
pytest.param(BackendTimeout, 3, "Backend timed out", id="backend_timeout"),
|
|
||||||
pytest.param(BackendError, 4, "Backend error", id="backend_error"),
|
|
||||||
pytest.param(MessageNotFound, 500, "Message not found", id="message_not_found")
|
|
||||||
])
|
|
||||||
def test_get_room_history_from_message_failure(plugin, read, write, error, code, message):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "7",
|
|
||||||
"method": "import_room_history_from_message",
|
|
||||||
"params": {
|
|
||||||
"room_id": "33",
|
|
||||||
"message_id": "88"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_room_history_from_message.coro.side_effect = error()
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_room_history_from_message.assert_called_with(room_id="33", message_id="88")
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "7",
|
|
||||||
"error": {
|
|
||||||
"code": code,
|
|
||||||
"message": message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_get_room_history_from_timestamp_success(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "7",
|
|
||||||
"method": "import_room_history_from_timestamp",
|
|
||||||
"params": {
|
|
||||||
"room_id": "12",
|
|
||||||
"from_timestamp": 1549454835
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_room_history_from_timestamp.coro.return_value = [
|
|
||||||
Message("12", "155", 1549454836, "Bye")
|
|
||||||
]
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_room_history_from_timestamp.assert_called_with(
|
|
||||||
room_id="12",
|
|
||||||
from_timestamp=1549454835
|
|
||||||
)
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "7",
|
|
||||||
"result": {
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"message_id": "12",
|
|
||||||
"sender_id": "155",
|
|
||||||
"sent_time": 1549454836,
|
|
||||||
"message_text": "Bye"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_get_room_history_from_timestamp_failure(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "3",
|
|
||||||
"method": "import_room_history_from_timestamp",
|
|
||||||
"params": {
|
|
||||||
"room_id": "10",
|
|
||||||
"from_timestamp": 1549454800
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_room_history_from_timestamp.coro.side_effect = UnknownError()
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_room_history_from_timestamp.assert_called_with(
|
|
||||||
room_id="10",
|
|
||||||
from_timestamp=1549454800
|
|
||||||
)
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "3",
|
|
||||||
"error": {
|
|
||||||
"code": 0,
|
|
||||||
"message": "Unknown error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_update_room(plugin, write):
|
|
||||||
messages = [
|
|
||||||
Message("10", "898", 1549454832, "Hi")
|
|
||||||
]
|
|
||||||
|
|
||||||
async def couritine():
|
|
||||||
plugin.update_room("14", 15, messages)
|
|
||||||
|
|
||||||
asyncio.run(couritine())
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"method": "chat_room_updated",
|
|
||||||
"params": {
|
|
||||||
"room_id": "14",
|
|
||||||
"unread_message_count": 15,
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"message_id": "10",
|
|
||||||
"sender_id": "898",
|
|
||||||
"sent_time": 1549454832,
|
|
||||||
"message_text": "Hi"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -18,28 +18,4 @@ def test_one_method_feature():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
plugin = PluginImpl(Platform.Generic, "0.1", None, None, None)
|
plugin = PluginImpl(Platform.Generic, "0.1", None, None, None)
|
||||||
assert plugin.features == [Feature.ImportOwnedGames]
|
assert plugin.features == [Feature.ImportOwnedGames]
|
||||||
|
|
||||||
def test_multiple_methods_feature_all():
|
|
||||||
class PluginImpl(Plugin): #pylint: disable=abstract-method
|
|
||||||
async def send_message(self, room_id, message):
|
|
||||||
pass
|
|
||||||
async def mark_as_read(self, room_id, last_message_id):
|
|
||||||
pass
|
|
||||||
async def get_rooms(self):
|
|
||||||
pass
|
|
||||||
async def get_room_history_from_message(self, room_id, message_id):
|
|
||||||
pass
|
|
||||||
async def get_room_history_from_timestamp(self, room_id, timestamp):
|
|
||||||
pass
|
|
||||||
|
|
||||||
plugin = PluginImpl(Platform.Generic, "0.1", None, None, None)
|
|
||||||
assert plugin.features == [Feature.Chat]
|
|
||||||
|
|
||||||
def test_multiple_methods_feature_not_all():
|
|
||||||
class PluginImpl(Plugin): #pylint: disable=abstract-method
|
|
||||||
async def send_message(self, room_id, message):
|
|
||||||
pass
|
|
||||||
|
|
||||||
plugin = PluginImpl(Platform.Generic, "0.1", None, None, None)
|
|
||||||
assert plugin.features == []
|
|
||||||
15
tests/test_shutdown_platform_client.py
Normal file
15
tests/test_shutdown_platform_client.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_success(plugin, read):
|
||||||
|
request = {
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "shutdown_platform_client"
|
||||||
|
}
|
||||||
|
|
||||||
|
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
||||||
|
plugin.shutdown_platform_client.return_value = None
|
||||||
|
await plugin.run()
|
||||||
|
plugin.shutdown_platform_client.assert_called_with()
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
import json
|
|
||||||
|
|
||||||
from galaxy.api.types import UserInfo, Presence
|
|
||||||
from galaxy.api.errors import UnknownError
|
|
||||||
from galaxy.api.consts import PresenceState
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_users_success(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "8",
|
|
||||||
"method": "import_user_infos",
|
|
||||||
"params": {
|
|
||||||
"user_id_list": ["13"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_users.coro.return_value = [
|
|
||||||
UserInfo("5", False, "Ula", "http://avatar.png", Presence(PresenceState.Offline))
|
|
||||||
]
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_users.assert_called_with(user_id_list=["13"])
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "8",
|
|
||||||
"result": {
|
|
||||||
"user_info_list": [
|
|
||||||
{
|
|
||||||
"user_id": "5",
|
|
||||||
"is_friend": False,
|
|
||||||
"user_name": "Ula",
|
|
||||||
"avatar_url": "http://avatar.png",
|
|
||||||
"presence": {
|
|
||||||
"presence_state": "offline"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_users_failure(plugin, read, write):
|
|
||||||
request = {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "12",
|
|
||||||
"method": "import_user_infos",
|
|
||||||
"params": {
|
|
||||||
"user_id_list": ["10", "11", "12"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
read.side_effect = [json.dumps(request).encode() + b"\n", b""]
|
|
||||||
plugin.get_users.coro.side_effect = UnknownError()
|
|
||||||
asyncio.run(plugin.run())
|
|
||||||
plugin.get_users.assert_called_with(user_id_list=["10", "11", "12"])
|
|
||||||
response = json.loads(write.call_args[0][0])
|
|
||||||
|
|
||||||
assert response == {
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "12",
|
|
||||||
"error": {
|
|
||||||
"code": 0,
|
|
||||||
"message": "Unknown error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user