Skip to content

Commit

Permalink
feat: change the specification of synchronous requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Maximenyuk committed Jun 21, 2024
1 parent 646825c commit 5312d07
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 184 deletions.
12 changes: 8 additions & 4 deletions pybotx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@
SmartappManifest,
SmartappManifestWebParams,
)
from pybotx.client.smartapps_api.sync_smartapp_event import (
SyncSmartAppEventResponsePayload,
)
from pybotx.client.stickers_api.exceptions import (
InvalidEmojiError,
InvalidImageError,
Expand Down Expand Up @@ -126,6 +123,11 @@
from pybotx.models.smartapps import SmartApp
from pybotx.models.status import BotMenu, StatusRecipient
from pybotx.models.stickers import Sticker, StickerPack
from pybotx.models.sync_smartapp_event import (
BotAPISyncSmartAppEventErrorResponse,
BotAPISyncSmartAppEventResponse,
BotAPISyncSmartAppEventResultResponse,
)
from pybotx.models.system_events.added_to_chat import AddedToChatEvent
from pybotx.models.system_events.chat_created import ChatCreatedEvent, ChatCreatedMember
from pybotx.models.system_events.cts_login import CTSLoginEvent
Expand All @@ -151,6 +153,9 @@
"BotAPIBotDisabledErrorData",
"BotAPIBotDisabledResponse",
"BotAPIMethodFailedCallback",
"BotAPISyncSmartAppEventErrorResponse",
"BotAPISyncSmartAppEventResponse",
"BotAPISyncSmartAppEventResultResponse",
"BotAPIUnverifiedRequestErrorData",
"BotAPIUnverifiedRequestResponse",
"BotAccount",
Expand Down Expand Up @@ -226,7 +231,6 @@
"RequestHeadersNotProvidedError",
"SmartApp",
"SmartAppEvent",
"SyncSmartAppEventResponsePayload",
"SmartappManifest",
"SmartappManifestWebLayoutChoices",
"SmartappManifestWebParams",
Expand Down
18 changes: 8 additions & 10 deletions pybotx/bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,6 @@
BotXAPISmartAppsListRequestPayload,
SmartAppsListMethod,
)
from pybotx.client.smartapps_api.sync_smartapp_event import (
SyncSmartAppEventResponsePayload,
)
from pybotx.client.smartapps_api.upload_file import (
UploadFileMethod as SmartappsUploadFileMethod,
)
Expand Down Expand Up @@ -245,10 +242,11 @@
build_bot_status_response,
)
from pybotx.models.stickers import Sticker, StickerPack, StickerPackFromList
from pybotx.models.system_events.smartapp_event import (
BotAPISmartAppEvent,
SmartAppEvent,
from pybotx.models.sync_smartapp_event import (
BotAPISyncSmartAppEvent,
BotAPISyncSmartAppEventResponse,
)
from pybotx.models.system_events.smartapp_event import SmartAppEvent
from pybotx.models.users import UserFromCSV, UserFromSearch

MissingOptionalAttachment = MissingOptional[
Expand Down Expand Up @@ -331,7 +329,7 @@ async def sync_execute_raw_smartapp_event(
verify_request: bool = True,
request_headers: Optional[Mapping[str, str]] = None,
logging_command: bool = True,
) -> SyncSmartAppEventResponsePayload:
) -> BotAPISyncSmartAppEventResponse:
if logging_command:
log_incoming_request(
raw_smartapp_event,
Expand All @@ -342,8 +340,8 @@ async def sync_execute_raw_smartapp_event(
self._verify_request(request_headers)

try:
bot_api_smartapp_event: BotAPISmartAppEvent = parse_obj_as(
BotAPISmartAppEvent,
bot_api_smartapp_event: BotAPISyncSmartAppEvent = parse_obj_as(
BotAPISyncSmartAppEvent,
raw_smartapp_event,
)
except ValidationError as validation_exc:
Expand All @@ -357,7 +355,7 @@ async def sync_execute_raw_smartapp_event(
async def sync_execute_smartapp_event(
self,
smartapp_event: SmartAppEvent,
) -> SyncSmartAppEventResponsePayload:
) -> BotAPISyncSmartAppEventResponse:
self._bot_accounts_storage.ensure_bot_id_exists(smartapp_event.bot.id)
return await self._handler_collector.handle_sync_smartapp_event(
self,
Expand Down
6 changes: 2 additions & 4 deletions pybotx/bot/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
from functools import partial
from typing import TYPE_CHECKING, Awaitable, Callable, List, Literal, TypeVar, Union

from pybotx.client.smartapps_api.sync_smartapp_event import (
SyncSmartAppEventResponsePayload,
)
from pybotx.models.commands import BotCommand
from pybotx.models.message.incoming_message import IncomingMessage
from pybotx.models.status import StatusRecipient
from pybotx.models.sync_smartapp_event import BotAPISyncSmartAppEventResponse
from pybotx.models.system_events.added_to_chat import AddedToChatEvent
from pybotx.models.system_events.chat_created import ChatCreatedEvent
from pybotx.models.system_events.cts_login import CTSLoginEvent
Expand All @@ -28,7 +26,7 @@

SyncSmartAppEventHandlerFunc = Callable[
[SmartAppEvent, "Bot"],
Awaitable[SyncSmartAppEventResponsePayload],
Awaitable[BotAPISyncSmartAppEventResponse],
]

IncomingMessageHandlerFunc = HandlerFunc[IncomingMessage]
Expand Down
6 changes: 2 additions & 4 deletions pybotx/bot/handler_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,12 @@
ExceptionMiddleware,
)
from pybotx.client.smartapps_api.exceptions import SyncSmartAppEventHandlerNotFoundError
from pybotx.client.smartapps_api.sync_smartapp_event import (
SyncSmartAppEventResponsePayload,
)
from pybotx.converters import optional_sequence_to_list
from pybotx.logger import logger
from pybotx.models.commands import BotCommand, SystemEvent
from pybotx.models.message.incoming_message import IncomingMessage
from pybotx.models.status import BotMenu, StatusRecipient
from pybotx.models.sync_smartapp_event import BotAPISyncSmartAppEventResponse
from pybotx.models.system_events.added_to_chat import AddedToChatEvent
from pybotx.models.system_events.chat_created import ChatCreatedEvent
from pybotx.models.system_events.cts_login import CTSLoginEvent
Expand Down Expand Up @@ -126,7 +124,7 @@ async def handle_sync_smartapp_event(
self,
bot: "Bot",
smartapp_event: SmartAppEvent,
) -> SyncSmartAppEventResponsePayload:
) -> BotAPISyncSmartAppEventResponse:
if not isinstance(smartapp_event, SmartAppEvent):
raise NotImplementedError(
f"Unsupported event type for sync smartapp event: `{smartapp_event}`",
Expand Down
11 changes: 3 additions & 8 deletions pybotx/client/smartapps_api/smartapp_event.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Literal, Type, TypeVar
from typing import Any, Dict, List, Literal
from uuid import UUID

from pybotx.client.authorized_botx_method import AuthorizedBotXMethod
Expand All @@ -7,11 +7,6 @@
from pybotx.models.api_base import UnverifiedPayloadBaseModel, VerifiedPayloadBaseModel
from pybotx.models.async_files import APIAsyncFile, File, convert_async_file_from_domain

TBotXAPISmartAppEventRequestPayload = TypeVar(
"TBotXAPISmartAppEventRequestPayload",
bound="BotXAPISmartAppEventRequestPayload",
)


class BotXAPISmartAppEventRequestPayload(UnverifiedPayloadBaseModel):
ref: MissingOptional[UUID]
Expand All @@ -25,15 +20,15 @@ class BotXAPISmartAppEventRequestPayload(UnverifiedPayloadBaseModel):

@classmethod
def from_domain(
cls: Type[TBotXAPISmartAppEventRequestPayload],
cls,
ref: MissingOptional[UUID],
smartapp_id: UUID,
chat_id: UUID,
data: Dict[str, Any],
opts: Missing[Dict[str, Any]],
files: Missing[List[File]],
encrypted: bool,
) -> TBotXAPISmartAppEventRequestPayload:
) -> "BotXAPISmartAppEventRequestPayload":
api_async_files: Missing[List[APIAsyncFile]] = Undefined
if files:
api_async_files = [convert_async_file_from_domain(file) for file in files]
Expand Down
7 changes: 0 additions & 7 deletions pybotx/client/smartapps_api/sync_smartapp_event.py

This file was deleted.

3 changes: 2 additions & 1 deletion pybotx/models/bot_account.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from dataclasses import dataclass
from functools import cached_property
from typing import Optional
from urllib.parse import urlparse
from uuid import UUID

Expand All @@ -9,7 +10,7 @@
@dataclass
class BotAccount:
id: UUID
host: str
host: Optional[str]


class BotAccountWithSecret(BaseModel):
Expand Down
155 changes: 155 additions & 0 deletions pybotx/models/sync_smartapp_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
from typing import Any, Dict, List, Optional, Union
from uuid import UUID

from pybotx.missing import Missing, Undefined
from pybotx.models.api_base import UnverifiedPayloadBaseModel, VerifiedPayloadBaseModel
from pybotx.models.async_files import (
APIAsyncFile,
File,
convert_async_file_from_domain,
convert_async_file_to_domain,
)
from pybotx.models.bot_account import BotAccount
from pybotx.models.chats import Chat
from pybotx.models.enums import (
BotAPIClientPlatforms,
ChatTypes,
convert_client_platform_to_domain,
)
from pybotx.models.message.incoming_message import UserDevice, UserSender
from pybotx.models.system_events.smartapp_event import SmartAppEvent


class BotAPISyncSmartAppSender(VerifiedPayloadBaseModel):
user_huid: UUID
udid: Optional[UUID]
platform: Optional[BotAPIClientPlatforms]


class BotAPISyncSmartAppPayload(VerifiedPayloadBaseModel):
ref: UUID
data: Dict[str, Any]
files: List[APIAsyncFile]


class BotAPISyncSmartAppEvent(VerifiedPayloadBaseModel):
bot_id: UUID
group_chat_id: UUID
sender_info: BotAPISyncSmartAppSender
method: str
payload: BotAPISyncSmartAppPayload

def to_domain(self, raw_smartapp_event: Dict[str, Any]) -> SmartAppEvent:
platform = (
convert_client_platform_to_domain(self.sender_info.platform)
if self.sender_info.platform
else None
)

device = UserDevice(
platform=platform,
manufacturer=None,
device_name=None,
os=None,
pushes=None,
timezone=None,
permissions=None,
platform_package_id=None,
app_version=None,
locale=None,
)

sender = UserSender(
huid=self.sender_info.user_huid,
udid=self.sender_info.udid,
device=device,
ad_login=None,
ad_domain=None,
username=None,
is_chat_admin=None,
is_chat_creator=None,
)

return SmartAppEvent(
bot=BotAccount(id=self.bot_id, host=None),
chat=Chat(
id=self.group_chat_id,
type=ChatTypes.PERSONAL_CHAT,
),
sender=sender,
data={
"method": self.method,
"type": "smartapp_rpc",
"params": self.payload.data,
},
ref=self.payload.ref,
smartapp_id=self.bot_id,
opts=None,
files=[convert_async_file_to_domain(file) for file in self.payload.files],
smartapp_api_version=None,
raw_command=raw_smartapp_event,
)


class BotAPISyncSmartAppEventResultResponse(UnverifiedPayloadBaseModel):
ref: UUID
data: Any
files: List[APIAsyncFile]

@classmethod
def from_domain(
cls,
ref: UUID,
data: Any,
files: Missing[List[File]] = Undefined,
) -> "BotAPISyncSmartAppEventResultResponse":
api_async_files: List[APIAsyncFile] = []
if files:
api_async_files = [convert_async_file_from_domain(file) for file in files]

return cls(
ref=ref,
data=data,
files=api_async_files,
)

def jsonable_dict(self) -> Dict[str, Any]:
return {
"status": "ok",
"result": {
"ref": str(self.ref),
"data": self.data,
"files": [file.jsonable_dict() for file in self.files],
},
}


class BotAPISyncSmartAppEventErrorResponse(UnverifiedPayloadBaseModel):
reason: str
errors: List[Any]
error_data: Dict[str, Any]

@classmethod
def from_domain(
cls,
reason: Missing[str] = Undefined,
errors: Missing[List[Any]] = Undefined,
error_data: Missing[Dict[str, Any]] = Undefined,
) -> "BotAPISyncSmartAppEventErrorResponse":
return cls(
reason="smartapp_error" if reason is Undefined else reason,
errors=[] if errors is Undefined else errors,
error_data={} if error_data is Undefined else error_data,
)

def jsonable_dict(self) -> Dict[str, Any]:
return {
"status": "error",
**self.dict(),
}


BotAPISyncSmartAppEventResponse = Union[
BotAPISyncSmartAppEventResultResponse,
BotAPISyncSmartAppEventErrorResponse,
]
6 changes: 3 additions & 3 deletions pybotx/models/system_events/smartapp_event.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass
from typing import Any, Dict, List, Literal
from typing import Any, Dict, List, Literal, Optional
from uuid import UUID

from pydantic import Field
Expand Down Expand Up @@ -40,8 +40,8 @@ class SmartAppEvent(BotCommandBase):
ref: UUID
smartapp_id: UUID
data: Dict[str, Any] # noqa: WPS110
opts: Dict[str, Any]
smartapp_api_version: int
opts: Optional[Dict[str, Any]]
smartapp_api_version: Optional[int]
files: List[File]
chat: Chat
sender: UserSender
Expand Down
Loading

0 comments on commit 5312d07

Please sign in to comment.