diff --git a/aiogram/dispatcher/filters/__init__.py b/aiogram/dispatcher/filters/__init__.py index 9795697a..74f175ac 100644 --- a/aiogram/dispatcher/filters/__init__.py +++ b/aiogram/dispatcher/filters/__init__.py @@ -89,6 +89,10 @@ BUILTIN_FILTERS: Dict[str, Tuple[Type[BaseFilter], ...]] = { *_ALL_EVENTS_FILTERS, *_TELEGRAM_EVENTS_FILTERS, ), + "chat_join_request": ( + *_ALL_EVENTS_FILTERS, + *_TELEGRAM_EVENTS_FILTERS, + ), "error": ( ExceptionMessageFilter, ExceptionTypeFilter, diff --git a/aiogram/dispatcher/router.py b/aiogram/dispatcher/router.py index 8f2df80b..ae83c1c7 100644 --- a/aiogram/dispatcher/router.py +++ b/aiogram/dispatcher/router.py @@ -58,6 +58,7 @@ class Router: self.poll_answer = TelegramEventObserver(router=self, event_name="poll_answer") self.my_chat_member = TelegramEventObserver(router=self, event_name="my_chat_member") self.chat_member = TelegramEventObserver(router=self, event_name="chat_member") + self.chat_join_request = TelegramEventObserver(router=self, event_name="chat_join_request") self.errors = TelegramEventObserver(router=self, event_name="error") @@ -78,6 +79,7 @@ class Router: "poll_answer": self.poll_answer, "my_chat_member": self.my_chat_member, "chat_member": self.chat_member, + "chat_join_request": self.chat_join_request, "error": self.errors, } diff --git a/aiogram/types/chat_join_request.py b/aiogram/types/chat_join_request.py index fd411ba4..607ff702 100644 --- a/aiogram/types/chat_join_request.py +++ b/aiogram/types/chat_join_request.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Optional from pydantic import Field +from ..methods import ApproveChatJoinRequest, DeclineChatJoinRequest from .base import TelegramObject if TYPE_CHECKING: @@ -30,3 +31,22 @@ class ChatJoinRequest(TelegramObject): """*Optional*. Bio of the user.""" invite_link: Optional[ChatInviteLink] = None """*Optional*. Chat invite link that was used by the user to send the join request""" + + def approve(self) -> ApproveChatJoinRequest: + """ + Use this method to approve a chat join request. + """ + + return ApproveChatJoinRequest( + chat_id=self.chat.id, + user_id=self.from_user.id, + ) + + def decline(self) -> DeclineChatJoinRequest: + """ + Use this method to decline a chat join request. + """ + return DeclineChatJoinRequest( + chat_id=self.chat.id, + user_id=self.from_user.id, + ) diff --git a/aiogram/types/update.py b/aiogram/types/update.py index 47894366..493d95d5 100644 --- a/aiogram/types/update.py +++ b/aiogram/types/update.py @@ -96,6 +96,8 @@ class Update(TelegramObject): return "my_chat_member" if self.chat_member: return "chat_member" + if self.chat_join_request: + return "chat_join_request" raise UpdateTypeLookupError("Update does not contain any known event type.") diff --git a/tests/test_api/test_methods/test_approve_chat_join_request.py b/tests/test_api/test_methods/test_approve_chat_join_request.py new file mode 100644 index 00000000..1b9fa8f6 --- /dev/null +++ b/tests/test_api/test_methods/test_approve_chat_join_request.py @@ -0,0 +1,33 @@ +import pytest + +from aiogram.api.methods import ApproveChatJoinRequest, Request +from tests.mocked_bot import MockedBot + + +@pytest.mark.skip +class TestApproveChatJoinRequest: + @pytest.mark.asyncio + async def test_method(self, bot: MockedBot): + prepare_result = bot.add_result_for(ApproveChatJoinRequest, ok=True, result=None) + + response: bool = await ApproveChatJoinRequest( + chat_id=..., + user_id=..., + ) + request: Request = bot.get_request() + assert request.method == "approveChatJoinRequest" + # assert request.data == {} + assert response == prepare_result.result + + @pytest.mark.asyncio + async def test_bot_method(self, bot: MockedBot): + prepare_result = bot.add_result_for(ApproveChatJoinRequest, ok=True, result=None) + + response: bool = await bot.approve_chat_join_request( + chat_id=..., + user_id=..., + ) + request: Request = bot.get_request() + assert request.method == "approveChatJoinRequest" + # assert request.data == {} + assert response == prepare_result.result diff --git a/tests/test_api/test_methods/test_decline_chat_join_request.py b/tests/test_api/test_methods/test_decline_chat_join_request.py new file mode 100644 index 00000000..adb9b80c --- /dev/null +++ b/tests/test_api/test_methods/test_decline_chat_join_request.py @@ -0,0 +1,33 @@ +import pytest + +from aiogram.api.methods import DeclineChatJoinRequest, Request +from tests.mocked_bot import MockedBot + + +@pytest.mark.skip +class TestDeclineChatJoinRequest: + @pytest.mark.asyncio + async def test_method(self, bot: MockedBot): + prepare_result = bot.add_result_for(DeclineChatJoinRequest, ok=True, result=None) + + response: bool = await DeclineChatJoinRequest( + chat_id=..., + user_id=..., + ) + request: Request = bot.get_request() + assert request.method == "declineChatJoinRequest" + # assert request.data == {} + assert response == prepare_result.result + + @pytest.mark.asyncio + async def test_bot_method(self, bot: MockedBot): + prepare_result = bot.add_result_for(DeclineChatJoinRequest, ok=True, result=None) + + response: bool = await bot.decline_chat_join_request( + chat_id=..., + user_id=..., + ) + request: Request = bot.get_request() + assert request.method == "declineChatJoinRequest" + # assert request.data == {} + assert response == prepare_result.result