Skip to content
Open
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
2 changes: 1 addition & 1 deletion pybotx/bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
41 changes: 27 additions & 14 deletions pybotx/client/chats_api/create_chat.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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]:
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion pybotx/models/system_events/event_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
48 changes: 35 additions & 13 deletions tests/client/chats_api/test_create_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
HandlerCollector,
lifespan_wrapper,
)
from pybotx.missing import Undefined

pytestmark = [
pytest.mark.asyncio,
Expand Down Expand Up @@ -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(
Expand Down