Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: subscribe to unread counter in sending manifest #486

Merged
merged 3 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pybotx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
from pybotx.client.smartapps_api.exceptions import SyncSmartAppEventHandlerNotFoundError
from pybotx.client.smartapps_api.smartapp_manifest import (
SmartappManifest,
SmartappManifestAndroidParams,
SmartappManifestIosParams,
SmartappManifestUnreadCounterParams,
SmartappManifestWebParams,
)
from pybotx.client.stickers_api.exceptions import (
Expand Down Expand Up @@ -234,6 +237,9 @@
"SmartApp",
"SmartAppEvent",
"SmartappManifest",
"SmartappManifestAndroidParams",
"SmartappManifestIosParams",
"SmartappManifestUnreadCounterParams",
"SmartappManifestWebLayoutChoices",
"SmartappManifestWebParams",
"StatusRecipient",
Expand Down
27 changes: 16 additions & 11 deletions pybotx/bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@
from pybotx.client.smartapps_api.smartapp_manifest import (
BotXAPISmartAppManifestRequestPayload,
SmartappManifest,
SmartappManifestAndroidParams,
SmartappManifestIosParams,
SmartAppManifestMethod,
SmartappManifestUnreadCounterParams,
SmartappManifestWebParams,
)
from pybotx.client.smartapps_api.smartapp_notification import (
BotXAPISmartAppNotificationRequestPayload,
Expand Down Expand Up @@ -231,7 +235,6 @@
from pybotx.models.chats import ChatInfo, ChatListItem
from pybotx.models.commands import BotAPICommand, BotCommand
from pybotx.models.enums import ChatTypes
from pybotx.models.enums import SmartappManifestWebLayoutChoices as WebLayoutChoices
from pybotx.models.message.edit_message import EditMessage
from pybotx.models.message.markup import BubbleMarkup, KeyboardMarkup
from pybotx.models.message.message_status import MessageStatus
Expand Down Expand Up @@ -1551,17 +1554,18 @@ async def send_smartapp_manifest(
self,
*,
bot_id: UUID,
web_default_layout: WebLayoutChoices = WebLayoutChoices.minimal,
web_expanded_layout: WebLayoutChoices = WebLayoutChoices.half,
web_always_pinned: bool = False,
ios: Missing[SmartappManifestIosParams] = Undefined,
android: Missing[SmartappManifestAndroidParams] = Undefined,
web_layout: Missing[SmartappManifestWebParams] = Undefined,
unread_counter: Missing[SmartappManifestUnreadCounterParams] = Undefined,
) -> SmartappManifest:
"""Send smartapp manifest with given parameters.

:param bot_id: Bot which should perform the request.
:param web_default_layout: default smartapp layout for web clients.
:param web_expanded_layout: expanded smartapp layout for web clients.
:param web_always_pinned: True if smartapp icon should be always pinned
in the web clients sidebar.
:param ios: Smartapp layout for ios clients.
:param android: Smartapp layout for android clients.
:param web_layout: Smartapp layout for web clients.
:param unread_counter: Entities that can be subscribed to in the unread counter.

:return: Smartapp manifest with the set parameters received from BotX.
"""
Expand All @@ -1572,9 +1576,10 @@ async def send_smartapp_manifest(
self._bot_accounts_storage,
)
payload = BotXAPISmartAppManifestRequestPayload.from_domain(
web_default_layout=web_default_layout,
web_expanded_layout=web_expanded_layout,
web_always_pinned=web_always_pinned,
ios=ios,
android=android,
web_layout=web_layout,
unread_counter=unread_counter,
)
smartapp_manifest_response = await method.execute(payload)
return smartapp_manifest_response.to_domain()
Expand Down
57 changes: 44 additions & 13 deletions pybotx/client/smartapps_api/smartapp_manifest.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,68 @@
from typing import Literal
from typing import List, Literal
from uuid import UUID

from pydantic import Field

from pybotx.client.authorized_botx_method import AuthorizedBotXMethod
from pybotx.models.api_base import VerifiedPayloadBaseModel
from pybotx.missing import Missing, Undefined
from pybotx.models.api_base import UnverifiedPayloadBaseModel, VerifiedPayloadBaseModel
from pybotx.models.enums import SmartappManifestWebLayoutChoices as WebLayoutChoices


class SmartappManifestIosParams(VerifiedPayloadBaseModel):
fullscreen_layout: bool = False


class SmartappManifestAndroidParams(VerifiedPayloadBaseModel):
fullscreen_layout: bool = False


class SmartappManifestWebParams(VerifiedPayloadBaseModel):
default_layout: WebLayoutChoices = WebLayoutChoices.minimal
expanded_layout: WebLayoutChoices = WebLayoutChoices.half
always_pinned: bool = False


class SmartappManifestUnreadCounterParams(VerifiedPayloadBaseModel):
user_huid: List[UUID] = Field(default_factory=list)
group_chat_id: List[UUID] = Field(default_factory=list)
app_id: List[str] = Field(default_factory=list)


class SmartappManifest(VerifiedPayloadBaseModel):
ios: SmartappManifestIosParams
android: SmartappManifestAndroidParams
web: SmartappManifestWebParams
unread_counter_link: SmartappManifestUnreadCounterParams


class SmartappManifestPayload(UnverifiedPayloadBaseModel):
ios: Missing[SmartappManifestIosParams] = Undefined
android: Missing[SmartappManifestAndroidParams] = Undefined
web: Missing[SmartappManifestWebParams] = Undefined
unread_counter_link: Missing[SmartappManifestUnreadCounterParams] = Undefined

class BotXAPISmartAppManifestRequestPayload(VerifiedPayloadBaseModel):
manifest: SmartappManifest

class BotXAPISmartAppManifestRequestPayload(UnverifiedPayloadBaseModel):
manifest: SmartappManifestPayload

@classmethod
def from_domain(
cls,
web_default_layout: WebLayoutChoices = WebLayoutChoices.minimal,
web_expanded_layout: WebLayoutChoices = WebLayoutChoices.half,
web_always_pinned: bool = False,
ios: Missing[SmartappManifestIosParams] = Undefined,
android: Missing[SmartappManifestAndroidParams] = Undefined,
web_layout: Missing[SmartappManifestWebParams] = Undefined,
unread_counter: Missing[SmartappManifestUnreadCounterParams] = Undefined,
) -> "BotXAPISmartAppManifestRequestPayload":
if web_layout is Undefined and unread_counter is Undefined:
return cls(manifest={})

return cls(
manifest=SmartappManifest(
web=SmartappManifestWebParams(
default_layout=web_default_layout,
expanded_layout=web_expanded_layout,
always_pinned=web_always_pinned,
),
manifest=SmartappManifestPayload(
ios=ios,
android=android,
web=web_layout,
unread_counter_link=unread_counter,
),
)

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "pybotx"
version = "0.71.0"
version = "0.72.0"
description = "A python library for interacting with eXpress BotX API"
authors = [
"Sidnev Nikolay <[email protected]>",
Expand Down
87 changes: 77 additions & 10 deletions tests/client/smartapps_api/test_smartapp_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
SmartappManifestWebParams,
lifespan_wrapper,
)
from pybotx.client.smartapps_api.smartapp_manifest import (
SmartappManifestAndroidParams,
SmartappManifestIosParams,
SmartappManifestUnreadCounterParams,
)

pytestmark = [
pytest.mark.asyncio,
Expand All @@ -34,23 +39,45 @@ async def test__send_smartapp_manifest__all_params_provided__succeed(
headers={"Authorization": "Bearer token", "Content-Type": "application/json"},
json={
"manifest": {
"ios": {
"fullscreen_layout": False,
},
"android": {
"fullscreen_layout": False,
},
"web": {
"always_pinned": True,
"default_layout": "full",
"expanded_layout": "full",
},
"unread_counter_link": {
"user_huid": ["e3568b81-0446-4030-9210-1725841bf8f0"],
"group_chat_id": ["adc03af8-9193-4d3b-b913-7a023cdb4029"],
"app_id": ["test_app"],
},
},
},
).mock(
return_value=httpx.Response(
HTTPStatus.ACCEPTED,
json={
"result": {
"ios": {
"fullscreen_layout": False,
},
"android": {
"fullscreen_layout": False,
},
"web": {
"always_pinned": True,
"default_layout": "full",
"expanded_layout": "full",
},
"unread_counter_link": {
"user_huid": ["e3568b81-0446-4030-9210-1725841bf8f0"],
"group_chat_id": ["adc03af8-9193-4d3b-b913-7a023cdb4029"],
"app_id": ["test_app"],
},
},
"status": "ok",
},
Expand All @@ -63,19 +90,43 @@ async def test__send_smartapp_manifest__all_params_provided__succeed(
async with lifespan_wrapper(built_bot) as bot:
smartapp_manifest = await bot.send_smartapp_manifest(
bot_id=bot_id,
web_default_layout=SmartappManifestWebLayoutChoices.full,
web_expanded_layout=SmartappManifestWebLayoutChoices.full,
web_always_pinned=True,
ios=SmartappManifestIosParams(
fullscreen_layout=False,
),
android=SmartappManifestAndroidParams(
fullscreen_layout=False,
),
web_layout=SmartappManifestWebParams(
default_layout=SmartappManifestWebLayoutChoices.full,
expanded_layout=SmartappManifestWebLayoutChoices.full,
always_pinned=True,
),
unread_counter=SmartappManifestUnreadCounterParams(
user_huid=[UUID("e3568b81-0446-4030-9210-1725841bf8f0")],
group_chat_id=[UUID("adc03af8-9193-4d3b-b913-7a023cdb4029")],
app_id=["test_app"],
),
)

# - Assert -
assert endpoint.called
assert smartapp_manifest == SmartappManifest(
ios=SmartappManifestIosParams(
fullscreen_layout=False,
),
android=SmartappManifestAndroidParams(
fullscreen_layout=False,
),
web=SmartappManifestWebParams(
default_layout=SmartappManifestWebLayoutChoices.full,
expanded_layout=SmartappManifestWebLayoutChoices.full,
always_pinned=True,
),
unread_counter_link=SmartappManifestUnreadCounterParams(
user_huid=[UUID("e3568b81-0446-4030-9210-1725841bf8f0")],
group_chat_id=[UUID("adc03af8-9193-4d3b-b913-7a023cdb4029")],
app_id=["test_app"],
),
)


Expand All @@ -90,24 +141,29 @@ async def test__send_smartapp_manifest__only_default_params_provided__succeed(
f"https://{host}/api/v1/botx/smartapps/manifest",
headers={"Authorization": "Bearer token", "Content-Type": "application/json"},
json={
"manifest": {
"web": {
"always_pinned": False,
"default_layout": "minimal",
"expanded_layout": "half",
},
},
"manifest": {},
},
).mock(
return_value=httpx.Response(
HTTPStatus.ACCEPTED,
json={
"result": {
"ios": {
"fullscreen_layout": False,
},
"android": {
"fullscreen_layout": False,
},
"web": {
"always_pinned": False,
"default_layout": "minimal",
"expanded_layout": "half",
},
"unread_counter_link": {
"app_id": [],
"group_chat_id": [],
"user_huid": [],
},
},
"status": "ok",
},
Expand All @@ -123,9 +179,20 @@ async def test__send_smartapp_manifest__only_default_params_provided__succeed(
# - Assert -
assert endpoint.called
assert smartapp_manifest == SmartappManifest(
ios=SmartappManifestIosParams(
fullscreen_layout=False,
),
android=SmartappManifestAndroidParams(
fullscreen_layout=False,
),
web=SmartappManifestWebParams(
default_layout=SmartappManifestWebLayoutChoices.minimal,
expanded_layout=SmartappManifestWebLayoutChoices.half,
always_pinned=False,
),
unread_counter_link=SmartappManifestUnreadCounterParams(
user_huid=[],
group_chat_id=[],
app_id=[],
),
)
Loading