diff --git a/pybotx/bot/bot.py b/pybotx/bot/bot.py index 206724fd..884ab328 100644 --- a/pybotx/bot/bot.py +++ b/pybotx/bot/bot.py @@ -1200,7 +1200,7 @@ async def create_chat( self._bot_accounts_storage, ) - payload = BotXAPICreateChatRequestPayload( + payload = BotXAPICreateChatRequestPayload.from_domain( name=name, chat_type=chat_type, members=huids, diff --git a/pybotx/client/chats_api/create_chat.py b/pybotx/client/chats_api/create_chat.py index 7bc1cc37..b23f653b 100644 --- a/pybotx/client/chats_api/create_chat.py +++ b/pybotx/client/chats_api/create_chat.py @@ -1,13 +1,7 @@ -from typing import Any, Dict, List, Literal, Optional, Set, Union +from typing import List, Literal, Optional, Set, Union from uuid import UUID -from pydantic import ( - Field, - ConfigDict, - field_serializer, - field_validator, - model_validator, -) +from pydantic import Field, ConfigDict, field_serializer, field_validator from pybotx.client.authorized_botx_method import AuthorizedBotXMethod from pybotx.client.botx_method import response_exception_thrower @@ -36,12 +30,11 @@ class BotXAPICreateChatRequestPayload(UnverifiedPayloadBaseModel): shared_history: Missing[bool] avatar: Optional[str] = None - @model_validator(mode="before") - def _convert_chat_type(cls, values: Dict[str, Any]) -> Dict[str, Any]: - ct = values.get("chat_type") - if isinstance(ct, ChatTypes): - values["chat_type"] = convert_chat_type_from_domain(ct) - return values + @classmethod + def _convert_chat_type(cls, v: Union[APIChatTypes, ChatTypes]) -> APIChatTypes: + if isinstance(v, ChatTypes): + return convert_chat_type_from_domain(v) + return v @field_validator("avatar") def _validate_avatar(cls, v: Optional[str]) -> Optional[str]: @@ -59,6 +52,26 @@ def _validate_avatar(cls, v: Optional[str]) -> Optional[str]: def _serialize_chat_type(self, v: APIChatTypes) -> str: return v.value.lower() + @classmethod + def from_domain( + cls, + name: str, + chat_type: Union[APIChatTypes, ChatTypes], + members: List[UUID], + shared_history: Missing[bool], + description: Optional[str] = None, + avatar: Optional[str] = None, + ) -> "BotXAPICreateChatRequestPayload": + converted_chat_type = cls._convert_chat_type(chat_type) + return cls( + name=name, + chat_type=converted_chat_type, + members=members, + shared_history=shared_history, + description=description, + avatar=avatar, + ) + class BotXAPIChatIdResult(VerifiedPayloadBaseModel): model_config = ConfigDict(frozen=True) diff --git a/pybotx/models/system_events/event_edit.py b/pybotx/models/system_events/event_edit.py index fd04ba24..e4fedd54 100644 --- a/pybotx/models/system_events/event_edit.py +++ b/pybotx/models/system_events/event_edit.py @@ -37,7 +37,7 @@ class EventEdit(BotCommandBase): entities: Entities from updated message. """ - body: Optional[str] + body: str sync_id: UUID chat_id: UUID huid: UUID diff --git a/tests/client/chats_api/test_create_chat.py b/tests/client/chats_api/test_create_chat.py index 4abca1d9..5530017b 100644 --- a/tests/client/chats_api/test_create_chat.py +++ b/tests/client/chats_api/test_create_chat.py @@ -14,6 +14,7 @@ HandlerCollector, lifespan_wrapper, ) +from pybotx.missing import Undefined pytestmark = [ pytest.mark.asyncio, @@ -204,20 +205,41 @@ def test__create_chat_payload__convert_chat_type_validator() -> None: from pybotx.client.chats_api.create_chat import BotXAPICreateChatRequestPayload from pybotx.models.enums import ChatTypes, APIChatTypes - # Test with ChatTypes enum - values = {"chat_type": ChatTypes.GROUP_CHAT} - result = BotXAPICreateChatRequestPayload._convert_chat_type(values) # type: ignore[operator] - assert result["chat_type"] == APIChatTypes.GROUP_CHAT - - # Test with non-ChatTypes value (should remain unchanged) - values = {"chat_type": APIChatTypes.CHAT} # type: ignore[dict-item] - result = BotXAPICreateChatRequestPayload._convert_chat_type(values) # type: ignore[operator] - assert result["chat_type"] == APIChatTypes.CHAT + # Arrange + name = "Test Chat" + description = "Test Description" + chat_type = ChatTypes.PERSONAL_CHAT + members = [UUID("2fc83441-366a-49ba-81fc-6c39f065bb58")] + shared_history = Undefined + avatar = None + + # Act + payload = BotXAPICreateChatRequestPayload.from_domain( + name=name, + chat_type=chat_type, + members=members, + shared_history=shared_history, + description=description, + avatar=avatar, + ) - # Test with missing chat_type key - values = {"name": "test"} # type: ignore[dict-item] - result = BotXAPICreateChatRequestPayload._convert_chat_type(values) # type: ignore[operator] - assert result == {"name": "test"} + # Assert + assert payload.name == name + assert payload.description == description + assert payload.chat_type == APIChatTypes.CHAT + assert payload.members == members + + # Test with APIChatTypes + api_chat_type = APIChatTypes.CHANNEL + payload = BotXAPICreateChatRequestPayload.from_domain( + name=name, + chat_type=api_chat_type, + members=members, + shared_history=shared_history, + description=description, + avatar=avatar, + ) + assert payload.chat_type == api_chat_type async def test__create_chat__with_valid_avatar_succeed(