diff --git a/aiogram/client/bot.py b/aiogram/client/bot.py index 96890b1f..7a4b9392 100644 --- a/aiogram/client/bot.py +++ b/aiogram/client/bot.py @@ -20,7 +20,8 @@ import aiofiles from aiogram.utils.mixins import ContextInstanceMixin from aiogram.utils.token import extract_bot_id, validate_token - +from .session.aiohttp import AiohttpSession +from .session.base import BaseSession from ..methods import ( AddStickerToSet, AnswerCallbackQuery, @@ -102,7 +103,7 @@ from ..methods import ( UnbanChatMember, UnpinAllChatMessages, UnpinChatMessage, - UploadStickerFile, + UploadStickerFile, ApproveChatJoinRequest, DeclineChatJoinRequest, ) from ..types import ( UNSET, @@ -145,8 +146,6 @@ from ..types import ( UserProfilePhotos, WebhookInfo, ) -from .session.aiohttp import AiohttpSession -from .session.base import BaseSession T = TypeVar("T") @@ -1753,6 +1752,50 @@ class Bot(ContextInstanceMixin["Bot"]): ) return await self(call, request_timeout=request_timeout) + async def approve_chat_join_request( + self, + chat_id: Union[int, str], + user_id: int, + request_timeout: Optional[int] = None, + ) -> bool: + """ + Use this method to approve a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns :code:`True` on success. + + Source: https://core.telegram.org/bots/api#approvechatjoinrequest + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`) + :param user_id: Unique identifier of the target user + :param request_timeout: Request timeout + :return: Returns True on success. + """ + call = ApproveChatJoinRequest( + chat_id=chat_id, + user_id=user_id + ) + return await self(call, request_timeout=request_timeout) + + async def decline_chat_join_request( + self, + chat_id: Union[int, str], + user_id: int, + request_timeout: Optional[int] = None, + ) -> bool: + """ + Use this method to decline a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns :code:`True` on success. + + Source: https://core.telegram.org/bots/api#declinechatjoinrequest + + :param chat_id: Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`) + :param user_id: Unique identifier of the target user + :param request_timeout: Request timeout + :return: Returns True on success. + """ + call = DeclineChatJoinRequest( + chat_id=chat_id, + user_id=user_id + ) + return await self(call, request_timeout=request_timeout) + async def set_chat_photo( self, chat_id: Union[int, str], diff --git a/aiogram/dispatcher/router.py b/aiogram/dispatcher/router.py index 8f2df80b..9f2c1371 100644 --- a/aiogram/dispatcher/router.py +++ b/aiogram/dispatcher/router.py @@ -3,13 +3,13 @@ from __future__ import annotations import warnings from typing import Any, Dict, Generator, List, Optional, Set, Union -from ..types import TelegramObject -from ..utils.imports import import_module -from ..utils.warnings import CodeHasNoEffect from .event.bases import REJECTED, UNHANDLED from .event.event import EventObserver from .event.telegram import TelegramEventObserver from .filters import BUILTIN_FILTERS +from ..types import TelegramObject +from ..utils.imports import import_module +from ..utils.warnings import CodeHasNoEffect INTERNAL_UPDATE_TYPES = frozenset({"update", "error"}) @@ -58,6 +58,8 @@ 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 +80,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/methods/__init__.py b/aiogram/methods/__init__.py index 54b59e74..dcf3672a 100644 --- a/aiogram/methods/__init__.py +++ b/aiogram/methods/__init__.py @@ -3,12 +3,14 @@ from .answer_callback_query import AnswerCallbackQuery from .answer_inline_query import AnswerInlineQuery from .answer_pre_checkout_query import AnswerPreCheckoutQuery from .answer_shipping_query import AnswerShippingQuery +from .approve_chat_join_request import ApproveChatJoinRequest from .ban_chat_member import BanChatMember from .base import Request, Response, TelegramMethod from .close import Close from .copy_message import CopyMessage from .create_chat_invite_link import CreateChatInviteLink from .create_new_sticker_set import CreateNewStickerSet +from .decline_chat_join_request import DeclineChatJoinRequest from .delete_chat_photo import DeleteChatPhoto from .delete_chat_sticker_set import DeleteChatStickerSet from .delete_message import DeleteMessage @@ -164,4 +166,6 @@ __all__ = ( "SendGame", "SetGameScore", "GetGameHighScores", + "ApproveChatJoinRequest", + "DeclineChatJoinRequest", ) diff --git a/aiogram/methods/approve_chat_join_request.py b/aiogram/methods/approve_chat_join_request.py new file mode 100644 index 00000000..ce267c12 --- /dev/null +++ b/aiogram/methods/approve_chat_join_request.py @@ -0,0 +1,26 @@ +from typing import Union, TYPE_CHECKING, Dict, Any + +from .base import Request, TelegramMethod + +if TYPE_CHECKING: + from ..client.bot import Bot + + +class ApproveChatJoinRequest(TelegramMethod[bool]): + """ + Use this method to approve a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns :code:`True` on success. + + Source: https://core.telegram.org/bots/api#approvechatjoinrequest + """ + + __returning__ = bool + + chat_id: Union[str, int] + """Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`)""" + user_id: int + """Unique identifier of the target user""" + + def build_request(self, bot: Bot) -> Request: + data: Dict[str, Any] = self.dict() + + return Request(method="approveChatJoinRequest", data=data) diff --git a/aiogram/methods/create_chat_invite_link.py b/aiogram/methods/create_chat_invite_link.py index af152444..b6a17c40 100644 --- a/aiogram/methods/create_chat_invite_link.py +++ b/aiogram/methods/create_chat_invite_link.py @@ -2,8 +2,8 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, Dict, Optional, Union -from ..types import ChatInviteLink from .base import Request, TelegramMethod +from ..types import ChatInviteLink if TYPE_CHECKING: from ..client.bot import Bot @@ -20,10 +20,14 @@ class CreateChatInviteLink(TelegramMethod[ChatInviteLink]): chat_id: Union[int, str] """Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`)""" + name: Optional[str] = None + """Invite link name; 0-32 characters""" expire_date: Optional[int] = None """Point in time (Unix timestamp) when the link will expire""" member_limit: Optional[int] = None """Maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; 1-99999""" + creates_join_request: Optional[bool] = None + """*True*, if users joining the chat via the link need to be approved by chat administrators. If *True*, *member_limit* can't be specified""" def build_request(self, bot: Bot) -> Request: data: Dict[str, Any] = self.dict() diff --git a/aiogram/methods/decline_chat_join_request.py b/aiogram/methods/decline_chat_join_request.py new file mode 100644 index 00000000..4b31e978 --- /dev/null +++ b/aiogram/methods/decline_chat_join_request.py @@ -0,0 +1,26 @@ +from typing import Union, TYPE_CHECKING, Dict, Any + +from .base import Request, TelegramMethod + +if TYPE_CHECKING: + from ..client.bot import Bot + + +class DeclineChatJoinRequest(TelegramMethod[bool]): + """ + Use this method to decline a chat join request. The bot must be an administrator in the chat for this to work and must have the can_invite_users administrator right. Returns :code:`True` on success. + + Source: https://core.telegram.org/bots/api#declinechatjoinrequest + """ + + __returning__ = bool + + chat_id: Union[str, int] + """Unique identifier for the target chat or username of the target channel (in the format :code:`@channelusername`)""" + user_id: int + """Unique identifier of the target user""" + + def build_request(self, bot: Bot) -> Request: + data: Dict[str, Any] = self.dict() + + return Request(method="declineChatJoinRequest", data=data) diff --git a/aiogram/types/chat_invite_link.py b/aiogram/types/chat_invite_link.py index 0d610424..7c47837b 100644 --- a/aiogram/types/chat_invite_link.py +++ b/aiogram/types/chat_invite_link.py @@ -19,11 +19,17 @@ class ChatInviteLink(TelegramObject): """The invite link. If the link was created by another chat administrator, then the second part of the link will be replaced with '…'.""" creator: User """Creator of the link""" + creates_join_request: bool + """True, if users joining the chat via the link need to be approved by chat administrators""" is_primary: bool """True, if the link is primary""" is_revoked: bool """True, if the link is revoked""" + name: Optional[str] = None + """*Optional*. Invite link name""" expire_date: Optional[int] = None """*Optional*. Point in time (Unix timestamp) when the link will expire or has been expired""" member_limit: Optional[int] = None """*Optional*. Maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; 1-99999""" + pending_join_request_count: Optional[int] = None + """*Optional*. Number of pending join requests created using this link"""