Skip to content

Commit

Permalink
feat: Add edit system event (#442)
Browse files Browse the repository at this point in the history
  • Loading branch information
depostnykh authored Jan 12, 2024
1 parent b7f87f5 commit c5e44c9
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 1 deletion.
2 changes: 2 additions & 0 deletions pybotx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
from pybotx.models.system_events.cts_login import CTSLoginEvent
from pybotx.models.system_events.cts_logout import CTSLogoutEvent
from pybotx.models.system_events.deleted_from_chat import DeletedFromChatEvent
from pybotx.models.system_events.event_edit import EventEdit
from pybotx.models.system_events.internal_bot_notification import (
InternalBotNotificationEvent,
)
Expand Down Expand Up @@ -142,6 +143,7 @@
"ButtonTextAlign",
"CTSLoginEvent",
"CTSLogoutEvent",
"EventEdit",
"CallbackNotReceivedError",
"CallbackRepoProto",
"CantUpdatePersonalChatError",
Expand Down
2 changes: 2 additions & 0 deletions pybotx/bot/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pybotx.models.system_events.cts_login import CTSLoginEvent
from pybotx.models.system_events.cts_logout import CTSLogoutEvent
from pybotx.models.system_events.deleted_from_chat import DeletedFromChatEvent
from pybotx.models.system_events.event_edit import EventEdit
from pybotx.models.system_events.internal_bot_notification import (
InternalBotNotificationEvent,
)
Expand All @@ -32,6 +33,7 @@
HandlerFunc[CTSLogoutEvent],
HandlerFunc[InternalBotNotificationEvent],
HandlerFunc[SmartAppEvent],
HandlerFunc[EventEdit],
]

VisibleFunc = Callable[[StatusRecipient, "Bot"], Awaitable[bool]]
Expand Down
11 changes: 11 additions & 0 deletions pybotx/bot/handler_collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from pybotx.models.system_events.cts_login import CTSLoginEvent
from pybotx.models.system_events.cts_logout import CTSLogoutEvent
from pybotx.models.system_events.deleted_from_chat import DeletedFromChatEvent
from pybotx.models.system_events.event_edit import EventEdit
from pybotx.models.system_events.internal_bot_notification import (
InternalBotNotificationEvent,
)
Expand Down Expand Up @@ -270,6 +271,16 @@ def cts_logout(

return handler_func

def event_edit(
self,
handler_func: HandlerFunc[EventEdit],
) -> HandlerFunc[EventEdit]:
"""Decorate `event edit` event handler."""

self._system_event(EventEdit, handler_func)

return handler_func

def smartapp_event(
self,
handler_func: HandlerFunc[SmartAppEvent],
Expand Down
3 changes: 3 additions & 0 deletions pybotx/models/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
BotAPIDeletedFromChat,
DeletedFromChatEvent,
)
from pybotx.models.system_events.event_edit import BotAPIEventEdit, EventEdit
from pybotx.models.system_events.internal_bot_notification import (
BotAPIInternalBotNotification,
InternalBotNotificationEvent,
Expand All @@ -38,6 +39,7 @@
BotAPILeftFromChat,
BotAPICTSLogin,
BotAPICTSLogout,
BotAPIEventEdit,
]
BotAPICommand = Union[BotAPIIncomingMessage, BotAPISystemEvent]

Expand All @@ -51,5 +53,6 @@
LeftFromChatEvent,
CTSLoginEvent,
CTSLogoutEvent,
EventEdit,
]
BotCommand = Union[IncomingMessage, SystemEvent]
1 change: 1 addition & 0 deletions pybotx/models/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class BotAPISystemEventTypes(StrEnum):
INTERNAL_BOT_NOTIFICATION = "system:internal_bot_notification"
LEFT_FROM_CHAT = "system:left_from_chat"
SMARTAPP_EVENT = "system:smartapp_event"
EVENT_EDIT = "system:event_edit"


class BotAPIClientPlatforms(Enum):
Expand Down
49 changes: 49 additions & 0 deletions pybotx/models/system_events/event_edit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from dataclasses import dataclass
from typing import Any, Dict, Literal, Optional

from pydantic import Field

from pybotx.models.api_base import VerifiedPayloadBaseModel
from pybotx.models.base_command import (
BaseBotAPIContext,
BotAPIBaseCommand,
BotAPIBaseSystemEventPayload,
BotCommandBase,
)
from pybotx.models.bot_account import BotAccount
from pybotx.models.enums import BotAPISystemEventTypes


@dataclass
class EventEdit(BotCommandBase):
"""Event `system:event_edit`.
Attributes:
body: updated message body.
"""

body: Optional[str]


class BotAPIEventEditData(VerifiedPayloadBaseModel):
body: Optional[str]


class BotAPIEventEditPayload(BotAPIBaseSystemEventPayload):
body: Literal[BotAPISystemEventTypes.EVENT_EDIT]
data: BotAPIEventEditData


class BotAPIEventEdit(BotAPIBaseCommand):
payload: BotAPIEventEditPayload = Field(..., alias="command")
sender: BaseBotAPIContext = Field(..., alias="from")

def to_domain(self, raw_command: Dict[str, Any]) -> EventEdit:
return EventEdit(
bot=BotAccount(
id=self.bot_id,
host=self.sender.host,
),
raw_command=raw_command,
body=self.payload.data.body,
)
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.61.2"
version = "0.61.3"
description = "A python library for interacting with eXpress BotX API"
authors = [
"Sidnev Nikolay <[email protected]>",
Expand Down
85 changes: 85 additions & 0 deletions tests/system_events/test_event_edit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from typing import Optional
from uuid import UUID

import pytest

from pybotx import (
Bot,
BotAccount,
BotAccountWithSecret,
EventEdit,
HandlerCollector,
lifespan_wrapper,
)

pytestmark = [
pytest.mark.asyncio,
pytest.mark.mock_authorization,
pytest.mark.usefixtures("respx_mock"),
]


async def test__event_edit__succeed(
bot_account: BotAccountWithSecret,
) -> None:
# - Arrange -
payload = {
"sync_id": "a465f0f3-1354-491c-8f11-f400164295cb",
"command": {
"body": "system:event_edit",
"data": {"body": "Edited"},
"command_type": "system",
"metadata": {},
},
"async_files": [],
"attachments": [],
"entities": [],
"from": {
"user_huid": None,
"group_chat_id": None,
"ad_login": None,
"ad_domain": None,
"username": None,
"chat_type": None,
"manufacturer": None,
"device": None,
"device_software": None,
"device_meta": {},
"platform": None,
"platform_package_id": None,
"is_admin": None,
"is_creator": None,
"app_version": None,
"locale": "en",
"host": "cts.example.com",
},
"bot_id": "24348246-6791-4ac0-9d86-b948cd6a0e46",
"proto_version": 4,
"source_sync_id": None,
}

collector = HandlerCollector()
event_edit: Optional[EventEdit] = None

@collector.event_edit
async def event_edit_handler(event: EventEdit, bot: Bot) -> None:
nonlocal event_edit
event_edit = event
# Drop `raw_command` from asserting
event_edit.raw_command = None

built_bot = Bot(collectors=[collector], bot_accounts=[bot_account])

# - Act -
async with lifespan_wrapper(built_bot) as bot:
bot.async_execute_raw_bot_command(payload)

# - Assert -
assert event_edit == EventEdit(
bot=BotAccount(
id=UUID("24348246-6791-4ac0-9d86-b948cd6a0e46"),
host="cts.example.com",
),
raw_command=None,
body="Edited",
)

0 comments on commit c5e44c9

Please sign in to comment.