diff --git a/pybotx/__init__.py b/pybotx/__init__.py index 6dc75987..5ac50d3f 100644 --- a/pybotx/__init__.py +++ b/pybotx/__init__.py @@ -39,6 +39,7 @@ ChatCreationError, ChatCreationProhibitedError, InvalidUsersListError, + ThreadAlreadyExistsError, ThreadCreationError, ThreadCreationProhibitedError, ) @@ -264,8 +265,8 @@ "SyncSmartAppEventHandlerFunc", "SyncSmartAppEventHandlerNotFoundError", "SyncSourceTypes", + "ThreadAlreadyExistsError", "ThreadCreationError", - "ThreadCreationEventNotFoundError", "ThreadCreationProhibitedError", "UnknownBotAccountError", "UnknownSystemEventError", diff --git a/pybotx/client/chats_api/create_thread.py b/pybotx/client/chats_api/create_thread.py index f7370b41..d1c42146 100644 --- a/pybotx/client/chats_api/create_thread.py +++ b/pybotx/client/chats_api/create_thread.py @@ -1,9 +1,12 @@ -from typing import Literal +from typing import Literal, NoReturn from uuid import UUID +import httpx + from pybotx.client.authorized_botx_method import AuthorizedBotXMethod from pybotx.client.botx_method import response_exception_thrower from pybotx.client.exceptions.chats import ( + ThreadAlreadyExistsError, ThreadCreationError, ThreadCreationProhibitedError, ) @@ -31,12 +34,21 @@ def to_domain(self) -> UUID: return self.result.thread_id +def conflict_error_handler(response: httpx.Response) -> NoReturn: + reason = response.json().get("reason") + + if reason == "thread_already_created": + raise ThreadAlreadyExistsError.from_response(response) + + raise ThreadCreationError.from_response(response) + + class CreateThreadMethod(AuthorizedBotXMethod): status_handlers = { **AuthorizedBotXMethod.status_handlers, 403: response_exception_thrower(ThreadCreationProhibitedError), 404: response_exception_thrower(EventNotFoundError), - 422: response_exception_thrower(ThreadCreationError), + 409: conflict_error_handler, } async def execute( diff --git a/pybotx/client/exceptions/chats.py b/pybotx/client/exceptions/chats.py index 50a2d3a1..e0b0480e 100644 --- a/pybotx/client/exceptions/chats.py +++ b/pybotx/client/exceptions/chats.py @@ -17,8 +17,12 @@ class ChatCreationError(BaseClientError): """Error while chat creation.""" +class ThreadAlreadyExistsError(BaseClientError): + """Thread is already exists.""" + + class ThreadCreationError(BaseClientError): - """Error while thread creation (invalid scheme).""" + """Creating a thread for a deleted message.""" class ThreadCreationProhibitedError(BaseClientError): @@ -26,13 +30,11 @@ class ThreadCreationProhibitedError(BaseClientError): Error while permission checks. 1. Bot has no permissions to create thread - 2. Threads are not allowed for that message + 2. Threads are not allowed for this chat 3. Bot is not a chat member where message is located 4. Message is located in personal chat 5. Usupported event type 6. Unsuppoerted chat type - 7. Thread is already created - 8. No access for message - 9. Message in stealth mode - 10. Message is deleted + 7. No access for message + 8. Message in stealth mode """ diff --git a/pyproject.toml b/pyproject.toml index 3f77e707..e6a744fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pybotx" -version = "0.75.4" +version = "0.75.5" description = "A python library for interacting with eXpress BotX API" authors = [ "Sidnev Nikolay ", diff --git a/tests/client/chats_api/test_create_thread.py b/tests/client/chats_api/test_create_thread.py index bfb56fbd..5c719596 100644 --- a/tests/client/chats_api/test_create_thread.py +++ b/tests/client/chats_api/test_create_thread.py @@ -1,5 +1,6 @@ +from collections.abc import Callable from http import HTTPStatus -from typing import Any, Callable +from typing import Any from uuid import UUID import httpx @@ -12,6 +13,7 @@ BotAccountWithSecret, EventNotFoundError, HandlerCollector, + ThreadAlreadyExistsError, ThreadCreationError, ThreadCreationProhibitedError, lifespan_wrapper, @@ -57,11 +59,10 @@ async def test__create_thread__succeed( bot_account: BotAccountWithSecret, ) -> None: # - Arrange - - thread_id = "2a8c0d1e-c4d1-4308-b024-6e1a9f4a4b6d" endpoint = create_mocked_endpoint( { "status": "ok", - "result": {"thread_id": thread_id}, + "result": {"thread_id": sync_id}, }, HTTPStatus.OK, ) @@ -76,7 +77,7 @@ async def test__create_thread__succeed( ) # - Assert - - assert str(created_thread_id) == thread_id + assert str(created_thread_id) == sync_id assert endpoint.called @@ -143,16 +144,6 @@ async def test__create_thread__succeed( HTTPStatus.FORBIDDEN, ThreadCreationProhibitedError, ), - ( - { - "status": "error", - "reason": "thread_already_created", - "errors": ["Thread already created"], - "error_data": {"bot_id": "24348246-6791-4ac0-9d86-b948cd6a0e46"}, - }, - HTTPStatus.FORBIDDEN, - ThreadCreationProhibitedError, - ), ( { "status": "error", @@ -176,32 +167,32 @@ async def test__create_thread__succeed( ( { "status": "error", - "reason": "event_already_deleted", - "errors": ["This event already deleted"], + "reason": "event_not_found", + "errors": ["Event not found"], "error_data": {"bot_id": "24348246-6791-4ac0-9d86-b948cd6a0e46"}, }, - HTTPStatus.FORBIDDEN, - ThreadCreationProhibitedError, + HTTPStatus.NOT_FOUND, + EventNotFoundError, ), ( { "status": "error", - "reason": "event_not_found", - "errors": ["Event not found"], + "reason": "event_already_deleted", + "errors": ["This event already deleted"], "error_data": {"bot_id": "24348246-6791-4ac0-9d86-b948cd6a0e46"}, }, - HTTPStatus.NOT_FOUND, - EventNotFoundError, + HTTPStatus.CONFLICT, + ThreadCreationError, ), ( { "status": "error", - "reason": "|specified reason|", - "errors": ["|specified errors|"], - "error_data": {}, + "reason": "thread_already_created", + "errors": ["Thread already created"], + "error_data": {"bot_id": "24348246-6791-4ac0-9d86-b948cd6a0e46"}, }, - HTTPStatus.UNPROCESSABLE_ENTITY, - ThreadCreationError, + HTTPStatus.CONFLICT, + ThreadAlreadyExistsError, ), ( {