Added chat member status changed filter, update Bot API 5.7, other small changes

This commit is contained in:
Alex Root Junior 2022-02-15 02:43:41 +02:00
parent a846acd607
commit ea7a000255
No known key found for this signature in database
GPG key ID: 074C1D455EBEA4AC
11 changed files with 273 additions and 22 deletions

View file

@ -1565,7 +1565,7 @@ class Bot(ContextInstanceMixin["Bot"]):
Source: https://core.telegram.org/bots/api#unbanchatmember
:param chat_id: Unique identifier for the target group or username of the target supergroup or channel (in the format :code:`@username`)
:param chat_id: Unique identifier for the target group or username of the target supergroup or channel (in the format :code:`@channelusername`)
:param user_id: Unique identifier of the target user
:param only_if_banned: Do nothing if the user is not banned
:param request_timeout: Request timeout
@ -2569,7 +2569,7 @@ class Bot(ContextInstanceMixin["Bot"]):
request_timeout: Optional[int] = None,
) -> Message:
"""
Use this method to send static .WEBP or `animated <https://telegram.org/blog/animated-stickers>`_ .TGS stickers. On success, the sent :class:`aiogram.types.message.Message` is returned.
Use this method to send static .WEBP, `animated <https://telegram.org/blog/animated-stickers>`_ .TGS, or `video <https://telegram.org/blog/video-stickers-better-reactions>`_ .WEBM stickers. On success, the sent :class:`aiogram.types.message.Message` is returned.
Source: https://core.telegram.org/bots/api#sendsticker
@ -2643,12 +2643,13 @@ class Bot(ContextInstanceMixin["Bot"]):
emojis: str,
png_sticker: Optional[Union[InputFile, str]] = None,
tgs_sticker: Optional[InputFile] = None,
webm_sticker: Optional[InputFile] = None,
contains_masks: Optional[bool] = None,
mask_position: Optional[MaskPosition] = None,
request_timeout: Optional[int] = None,
) -> bool:
"""
Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You **must** use exactly one of the fields *png_sticker* or *tgs_sticker*. Returns :code:`True` on success.
Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You **must** use exactly one of the fields *png_sticker*, *tgs_sticker*, or *webm_sticker*. Returns :code:`True` on success.
Source: https://core.telegram.org/bots/api#createnewstickerset
@ -2657,7 +2658,8 @@ class Bot(ContextInstanceMixin["Bot"]):
:param title: Sticker set title, 1-64 characters
:param emojis: One or more emoji corresponding to the sticker
:param png_sticker: **PNG** image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`
:param tgs_sticker: **TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_`https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_ for technical requirements
:param tgs_sticker: **TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_`https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_ for technical requirements
:param webm_sticker: **WEBM** video with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_`https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_ for technical requirements
:param contains_masks: Pass :code:`True`, if a set of mask stickers should be created
:param mask_position: A JSON-serialized object for position where the mask should be placed on faces
:param request_timeout: Request timeout
@ -2670,6 +2672,7 @@ class Bot(ContextInstanceMixin["Bot"]):
emojis=emojis,
png_sticker=png_sticker,
tgs_sticker=tgs_sticker,
webm_sticker=webm_sticker,
contains_masks=contains_masks,
mask_position=mask_position,
)
@ -2682,11 +2685,12 @@ class Bot(ContextInstanceMixin["Bot"]):
emojis: str,
png_sticker: Optional[Union[InputFile, str]] = None,
tgs_sticker: Optional[InputFile] = None,
webm_sticker: Optional[InputFile] = None,
mask_position: Optional[MaskPosition] = None,
request_timeout: Optional[int] = None,
) -> bool:
"""
Use this method to add a new sticker to a set created by the bot. You **must** use exactly one of the fields *png_sticker* or *tgs_sticker*. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns :code:`True` on success.
Use this method to add a new sticker to a set created by the bot. You **must** use exactly one of the fields *png_sticker*, *tgs_sticker*, or *webm_sticker*. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns :code:`True` on success.
Source: https://core.telegram.org/bots/api#addstickertoset
@ -2694,7 +2698,8 @@ class Bot(ContextInstanceMixin["Bot"]):
:param name: Sticker set name
:param emojis: One or more emoji corresponding to the sticker
:param png_sticker: **PNG** image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`
:param tgs_sticker: **TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_`https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_ for technical requirements
:param tgs_sticker: **TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_`https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_ for technical requirements
:param webm_sticker: **WEBM** video with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_`https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_ for technical requirements
:param mask_position: A JSON-serialized object for position where the mask should be placed on faces
:param request_timeout: Request timeout
:return: Returns True on success.
@ -2705,6 +2710,7 @@ class Bot(ContextInstanceMixin["Bot"]):
emojis=emojis,
png_sticker=png_sticker,
tgs_sticker=tgs_sticker,
webm_sticker=webm_sticker,
mask_position=mask_position,
)
return await self(call, request_timeout=request_timeout)
@ -2758,13 +2764,13 @@ class Bot(ContextInstanceMixin["Bot"]):
request_timeout: Optional[int] = None,
) -> bool:
"""
Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns :code:`True` on success.
Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Video thumbnails can be set only for video sticker sets only. Returns :code:`True` on success.
Source: https://core.telegram.org/bots/api#setstickersetthumb
:param name: Sticker set name
:param user_id: User identifier of the sticker set owner
:param thumb: A **PNG** image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a **TGS** animation with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_`https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_ for animated sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`. Animated sticker set thumbnail can't be uploaded via HTTP URL.
:param thumb: A **PNG** image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a **TGS** animation with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_`https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_ for animated sticker technical requirements, or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_`https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`. Animated sticker set thumbnails can't be uploaded via HTTP URL.
:param request_timeout: Request timeout
:return: Returns True on success.
"""

View file

@ -1,6 +1,21 @@
from typing import Dict, Tuple, Type
from .base import BaseFilter
from .chat_member import (
ADMINISTRATOR,
CREATOR,
IS_ADMIN,
IS_MEMBER,
IS_NOT_MEMBER,
JOIN_TRANSITION,
KICKED,
LEAVE_TRANSITION,
LEFT,
MEMBER,
PROMOTED_TRANSITION,
RESTRICTED,
ChatMemberUpdatedStatus,
)
from .command import Command, CommandObject
from .content_types import ContentTypesFilter
from .exception import ExceptionMessageFilter, ExceptionTypeFilter
@ -19,6 +34,19 @@ __all__ = (
"ExceptionTypeFilter",
"StateFilter",
"MagicData",
"ChatMemberUpdatedStatus",
"CREATOR",
"ADMINISTRATOR",
"MEMBER",
"RESTRICTED",
"LEFT",
"KICKED",
"IS_MEMBER",
"IS_ADMIN",
"PROMOTED_TRANSITION",
"IS_NOT_MEMBER",
"JOIN_TRANSITION",
"LEAVE_TRANSITION",
)
_ALL_EVENTS_FILTERS: Tuple[Type[BaseFilter], ...] = (MagicData,)
@ -84,10 +112,12 @@ BUILTIN_FILTERS: Dict[str, Tuple[Type[BaseFilter], ...]] = {
"my_chat_member": (
*_ALL_EVENTS_FILTERS,
*_TELEGRAM_EVENTS_FILTERS,
ChatMemberUpdatedStatus,
),
"chat_member": (
*_ALL_EVENTS_FILTERS,
*_TELEGRAM_EVENTS_FILTERS,
ChatMemberUpdatedStatus,
),
"chat_join_request": (
*_ALL_EVENTS_FILTERS,

View file

@ -0,0 +1,155 @@
from typing import Any, Dict, Optional, TypeVar, Union
from aiogram.dispatcher.filters import BaseFilter
from aiogram.types import ChatMember, ChatMemberUpdated
MarkerT = TypeVar("MarkerT", bound="_MemberStatusMarker")
MarkerGroupT = TypeVar("MarkerGroupT", bound="_MemberStatusGroupMarker")
TransitionT = TypeVar("TransitionT", bound="_MemberStatusTransition")
class _MemberStatusMarker:
def __init__(self, name: str, *, is_member: Optional[bool] = None) -> None:
self.name = name
self.is_member = is_member
def __str__(self) -> str:
result = self.name.upper()
if self.is_member is not None:
result = ("+" if self.is_member else "-") + result
return result
def __pos__(self: MarkerT) -> MarkerT:
return type(self)(name=self.name, is_member=True)
def __neg__(self: MarkerT) -> MarkerT:
return type(self)(name=self.name, is_member=False)
def __or__(
self, other: Union["_MemberStatusMarker", "_MemberStatusGroupMarker"]
) -> "_MemberStatusGroupMarker":
if isinstance(other, _MemberStatusMarker):
return _MemberStatusGroupMarker(self, other)
if isinstance(other, _MemberStatusGroupMarker):
return other | self
raise TypeError("can't be combined")
def __rshift__(
self, other: Union["_MemberStatusMarker", "_MemberStatusGroupMarker"]
) -> "_MemberStatusTransition":
old = _MemberStatusGroupMarker(self)
if isinstance(other, _MemberStatusMarker):
return _MemberStatusTransition(old=old, new=_MemberStatusGroupMarker(other))
if isinstance(other, _MemberStatusGroupMarker):
return _MemberStatusTransition(old=old, new=other)
raise TypeError("can't be combined")
def __lshift__(
self, other: Union["_MemberStatusMarker", "_MemberStatusGroupMarker"]
) -> "_MemberStatusTransition":
new = _MemberStatusGroupMarker(self)
if isinstance(other, _MemberStatusMarker):
return _MemberStatusTransition(old=_MemberStatusGroupMarker(other), new=new)
if isinstance(other, _MemberStatusGroupMarker):
return _MemberStatusTransition(old=other, new=new)
raise TypeError("can't be combined")
def __hash__(self) -> int:
return hash((self.name, self.is_member))
def check_member(self, member: ChatMember) -> bool:
if self.is_member is not None and member.is_member != self.is_member:
return False
return self.name == member.status
class _MemberStatusGroupMarker:
def __init__(self, *statuses: _MemberStatusMarker) -> None:
self.statuses = set(statuses)
def __or__(
self: MarkerGroupT, other: Union["_MemberStatusMarker", "_MemberStatusGroupMarker"]
) -> MarkerGroupT:
if isinstance(other, _MemberStatusMarker):
return type(self)(*self.statuses, other)
elif isinstance(other, _MemberStatusGroupMarker):
return type(self)(*self.statuses, *other.statuses)
raise TypeError("can't be combined")
def __rshift__(
self, other: Union["_MemberStatusMarker", "_MemberStatusGroupMarker"]
) -> "_MemberStatusTransition":
if isinstance(other, _MemberStatusMarker):
return _MemberStatusTransition(old=self, new=_MemberStatusGroupMarker(other))
if isinstance(other, _MemberStatusGroupMarker):
return _MemberStatusTransition(old=self, new=other)
raise TypeError("can't be combined")
def __lshift__(
self, other: Union["_MemberStatusMarker", "_MemberStatusGroupMarker"]
) -> "_MemberStatusTransition":
if isinstance(other, _MemberStatusMarker):
return _MemberStatusTransition(old=_MemberStatusGroupMarker(other), new=self)
if isinstance(other, _MemberStatusGroupMarker):
return _MemberStatusTransition(old=other, new=self)
raise TypeError("can't be combined")
def __str__(self) -> str:
result = " | ".join(map(str, sorted(self.statuses, key=lambda s: (s.name, s.is_member))))
if len(self.statuses) != 1:
return f"({result})"
return result
def check_member(self, member: ChatMember) -> bool:
for status in self.statuses:
if status.check_member(member):
return True
return False
class _MemberStatusTransition:
def __init__(self, *, old: _MemberStatusGroupMarker, new: _MemberStatusGroupMarker) -> None:
self.old = old
self.new = new
def __str__(self) -> str:
return f"{self.old} >> {self.new}"
def __invert__(self: TransitionT) -> TransitionT:
return type(self)(old=self.new, new=self.old)
CREATOR = _MemberStatusMarker("creator")
ADMINISTRATOR = _MemberStatusMarker("administrator")
MEMBER = _MemberStatusMarker("member")
RESTRICTED = _MemberStatusMarker("restricted")
LEFT = _MemberStatusMarker("left")
KICKED = _MemberStatusMarker("kicked")
IS_MEMBER = CREATOR | ADMINISTRATOR | MEMBER | +RESTRICTED
IS_ADMIN = CREATOR | ADMINISTRATOR
PROMOTED_TRANSITION = (MEMBER | RESTRICTED | LEFT | KICKED) >> ADMINISTRATOR
IS_NOT_MEMBER = LEFT | KICKED | -RESTRICTED
JOIN_TRANSITION = IS_NOT_MEMBER >> IS_MEMBER
LEAVE_TRANSITION = ~JOIN_TRANSITION
class ChatMemberUpdatedStatus(BaseFilter):
member_status_changed: Union[
_MemberStatusMarker, _MemberStatusGroupMarker, _MemberStatusTransition
]
class Config:
arbitrary_types_allowed = True
async def __call__(self, member_updated: ChatMemberUpdated) -> Union[bool, Dict[str, Any]]:
old = member_updated.old_chat_member
new = member_updated.new_chat_member
rule = self.member_status_changed
if isinstance(rule, (_MemberStatusMarker, _MemberStatusGroupMarker)):
return rule.check_member(new)
if isinstance(rule, _MemberStatusTransition):
return rule.old.check_member(old) and rule.new.check_member(new)
return False

View file

@ -127,7 +127,7 @@ class RedisStorage(BaseStorage):
redis = Redis(connection_pool=pool)
return cls(redis=redis, **kwargs)
def create_isolation(self, **kwargs) -> "RedisEventIsolation":
def create_isolation(self, **kwargs: Any) -> "RedisEventIsolation":
return RedisEventIsolation(redis=self.redis, key_builder=self.key_builder, **kwargs)
async def close(self) -> None:

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING:
class AddStickerToSet(TelegramMethod[bool]):
"""
Use this method to add a new sticker to a set created by the bot. You **must** use exactly one of the fields *png_sticker* or *tgs_sticker*. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns :code:`True` on success.
Use this method to add a new sticker to a set created by the bot. You **must** use exactly one of the fields *png_sticker*, *tgs_sticker*, or *webm_sticker*. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns :code:`True` on success.
Source: https://core.telegram.org/bots/api#addstickertoset
"""
@ -27,15 +27,18 @@ class AddStickerToSet(TelegramMethod[bool]):
png_sticker: Optional[Union[InputFile, str]] = None
"""**PNG** image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`"""
tgs_sticker: Optional[InputFile] = None
"""**TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_`https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_ for technical requirements"""
"""**TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_`https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_ for technical requirements"""
webm_sticker: Optional[InputFile] = None
"""**WEBM** video with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_`https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_ for technical requirements"""
mask_position: Optional[MaskPosition] = None
"""A JSON-serialized object for position where the mask should be placed on faces"""
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker"})
data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker", "webm_sticker"})
files: Dict[str, InputFile] = {}
prepare_file(data=data, files=files, name="png_sticker", value=self.png_sticker)
prepare_file(data=data, files=files, name="tgs_sticker", value=self.tgs_sticker)
prepare_file(data=data, files=files, name="webm_sticker", value=self.webm_sticker)
return Request(method="addStickerToSet", data=data, files=files)

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING:
class CreateNewStickerSet(TelegramMethod[bool]):
"""
Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You **must** use exactly one of the fields *png_sticker* or *tgs_sticker*. Returns :code:`True` on success.
Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus created. You **must** use exactly one of the fields *png_sticker*, *tgs_sticker*, or *webm_sticker*. Returns :code:`True` on success.
Source: https://core.telegram.org/bots/api#createnewstickerset
"""
@ -29,17 +29,20 @@ class CreateNewStickerSet(TelegramMethod[bool]):
png_sticker: Optional[Union[InputFile, str]] = None
"""**PNG** image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`"""
tgs_sticker: Optional[InputFile] = None
"""**TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_`https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_ for technical requirements"""
"""**TGS** animation with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_`https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_ for technical requirements"""
webm_sticker: Optional[InputFile] = None
"""**WEBM** video with the sticker, uploaded using multipart/form-data. See `https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_`https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_ for technical requirements"""
contains_masks: Optional[bool] = None
"""Pass :code:`True`, if a set of mask stickers should be created"""
mask_position: Optional[MaskPosition] = None
"""A JSON-serialized object for position where the mask should be placed on faces"""
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker"})
data: Dict[str, Any] = self.dict(exclude={"png_sticker", "tgs_sticker", "webm_sticker"})
files: Dict[str, InputFile] = {}
prepare_file(data=data, files=files, name="png_sticker", value=self.png_sticker)
prepare_file(data=data, files=files, name="tgs_sticker", value=self.tgs_sticker)
prepare_file(data=data, files=files, name="webm_sticker", value=self.webm_sticker)
return Request(method="createNewStickerSet", data=data, files=files)

View file

@ -18,7 +18,7 @@ if TYPE_CHECKING:
class SendSticker(TelegramMethod[Message]):
"""
Use this method to send static .WEBP or `animated <https://telegram.org/blog/animated-stickers>`_ .TGS stickers. On success, the sent :class:`aiogram.types.message.Message` is returned.
Use this method to send static .WEBP, `animated <https://telegram.org/blog/animated-stickers>`_ .TGS, or `video <https://telegram.org/blog/video-stickers-better-reactions>`_ .WEBM stickers. On success, the sent :class:`aiogram.types.message.Message` is returned.
Source: https://core.telegram.org/bots/api#sendsticker
"""

View file

@ -11,7 +11,7 @@ if TYPE_CHECKING:
class SetStickerSetThumb(TelegramMethod[bool]):
"""
Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Returns :code:`True` on success.
Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only. Video thumbnails can be set only for video sticker sets only. Returns :code:`True` on success.
Source: https://core.telegram.org/bots/api#setstickersetthumb
"""
@ -23,7 +23,7 @@ class SetStickerSetThumb(TelegramMethod[bool]):
user_id: int
"""User identifier of the sticker set owner"""
thumb: Optional[Union[InputFile, str]] = None
"""A **PNG** image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a **TGS** animation with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_`https://core.telegram.org/animated_stickers#technical-requirements <https://core.telegram.org/animated_stickers#technical-requirements>`_ for animated sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`. Animated sticker set thumbnail can't be uploaded via HTTP URL."""
"""A **PNG** image with the thumbnail, must be up to 128 kilobytes in size and have width and height exactly 100px, or a **TGS** animation with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_`https://core.telegram.org/stickers#animated-sticker-requirements <https://core.telegram.org/stickers#animated-sticker-requirements>`_ for animated sticker technical requirements, or a **WEBM** video with the thumbnail up to 32 kilobytes in size; see `https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_`https://core.telegram.org/stickers#video-sticker-requirements <https://core.telegram.org/stickers#video-sticker-requirements>`_ for video sticker technical requirements. Pass a *file_id* as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. :ref:`More info on Sending Files » <sending-files>`. Animated sticker set thumbnails can't be uploaded via HTTP URL."""
def build_request(self, bot: Bot) -> Request:
data: Dict[str, Any] = self.dict(exclude={"thumb"})

View file

@ -18,7 +18,7 @@ class UnbanChatMember(TelegramMethod[bool]):
__returning__ = bool
chat_id: Union[int, str]
"""Unique identifier for the target group or username of the target supergroup or channel (in the format :code:`@username`)"""
"""Unique identifier for the target group or username of the target supergroup or channel (in the format :code:`@channelusername`)"""
user_id: int
"""Unique identifier of the target user"""
only_if_banned: Optional[bool] = None

View file

@ -1,7 +1,13 @@
from __future__ import annotations
import datetime
from typing import TYPE_CHECKING, Optional, Union
from .base import TelegramObject
if TYPE_CHECKING:
from .user import User
class ChatMember(TelegramObject):
"""
@ -16,3 +22,48 @@ class ChatMember(TelegramObject):
Source: https://core.telegram.org/bots/api#chatmember
"""
status: str
"""..."""
user: Optional[User] = None
"""*Optional*. Information about the user"""
is_anonymous: Optional[bool] = None
"""*Optional*. :code:`True`, if the user's presence in the chat is hidden"""
custom_title: Optional[str] = None
"""*Optional*. Custom title for this user"""
can_be_edited: Optional[bool] = None
"""*Optional*. :code:`True`, if the bot is allowed to edit administrator privileges of that user"""
can_manage_chat: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can access the chat event log, chat statistics, message statistics in channels, see channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other administrator privilege"""
can_delete_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can delete messages of other users"""
can_manage_voice_chats: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can manage voice chats"""
can_restrict_members: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can restrict, ban or unban chat members"""
can_promote_members: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can add new administrators with a subset of their own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by the user)"""
can_change_info: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to change the chat title, photo and other settings"""
can_invite_users: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to invite new users to the chat"""
can_post_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can post in the channel; channels only"""
can_edit_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the administrator can edit messages of other users and can pin messages; channels only"""
can_pin_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to pin messages; groups and supergroups only"""
is_member: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is a member of the chat at the moment of the request"""
can_send_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to send text messages, contacts, locations and venues"""
can_send_media_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to send audios, documents, photos, videos, video notes and voice notes"""
can_send_polls: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to send polls"""
can_send_other_messages: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to send animations, games, stickers and use inline bots"""
can_add_web_page_previews: Optional[bool] = None
"""*Optional*. :code:`True`, if the user is allowed to add web page previews to their messages"""
until_date: Optional[Union[datetime.datetime, datetime.timedelta, int]] = None
"""*Optional*. Date when restrictions will be lifted for this user; unix time. If 0, then the user is restricted forever"""

View file

@ -37,6 +37,10 @@ class ChatActionSender:
self._running = False
self._lock = Lock()
async def _wait(self, interval: float) -> None:
with suppress(asyncio.TimeoutError):
await asyncio.wait_for(self._close_event.wait(), interval)
async def _worker(self) -> None:
logger.debug(
"Started chat action %r sender in chat_id=%s via bot id=%d",
@ -46,7 +50,7 @@ class ChatActionSender:
)
try:
counter = 0
await asyncio.sleep(self.initial_sleep)
await self._wait(self.initial_sleep)
while not self._close_event.is_set():
start = time.monotonic()
logger.debug(
@ -60,8 +64,7 @@ class ChatActionSender:
counter += 1
interval = self.interval - (time.monotonic() - start)
with suppress(asyncio.TimeoutError):
await asyncio.wait_for(self._close_event.wait(), interval)
await self._wait(interval)
finally:
logger.debug(
"Finished chat action %r sender in chat_id=%s via bot id=%d",