2
0
mirror of https://github.com/pyrogram/pyrogram synced 2025-09-03 07:45:14 +00:00

Merge branch 'develop' into asyncio

# Conflicts:
#	pyrogram/client/methods/chats/promote_chat_member.py
#	pyrogram/client/methods/chats/restrict_chat_member.py
#	pyrogram/client/methods/chats/unban_chat_member.py
This commit is contained in:
Dan
2019-03-13 13:08:58 +01:00
21 changed files with 316 additions and 191 deletions

View File

@@ -47,7 +47,7 @@ from .client.types import (
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove,
Poll, PollOption, ChatPreview, StopPropagation, ContinuePropagation, Game, CallbackGame, GameHighScore,
GameHighScores
GameHighScores, ChatPermissions
)
from .client import (
Client, ChatAction, ParseMode, Emoji,

View File

@@ -549,9 +549,10 @@ class Client(Methods, BaseClient):
try:
r = await self.send(
functions.auth.SendCode(
self.phone_number,
self.api_id,
self.api_hash
phone_number=self.phone_number,
api_id=self.api_id,
api_hash=self.api_hash,
settings=types.CodeSettings()
)
)
except (PhoneMigrate, NetworkMigrate) as e:

View File

@@ -65,7 +65,7 @@ class KickChatMember(BaseClient):
functions.channels.EditBanned(
channel=chat_peer,
user_id=user_peer,
banned_rights=types.ChannelBannedRights(
banned_rights=types.ChatBannedRights(
until_date=until_date,
view_messages=True,
send_messages=True,

View File

@@ -30,11 +30,12 @@ class PromoteChatMember(BaseClient):
can_post_messages: bool = False,
can_edit_messages: bool = False,
can_delete_messages: bool = True,
can_invite_users: bool = True,
can_restrict_members: bool = True,
can_invite_users: bool = True,
can_pin_messages: bool = False,
can_promote_members: bool = False) -> bool:
"""Use this method to promote or demote a user in a supergroup or a channel.
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
Pass False for all boolean parameters to demote a user.
@@ -58,12 +59,12 @@ class PromoteChatMember(BaseClient):
can_delete_messages (``bool``, *optional*):
Pass True, if the administrator can delete messages of other users.
can_invite_users (``bool``, *optional*):
Pass True, if the administrator can invite new users to the chat.
can_restrict_members (``bool``, *optional*):
Pass True, if the administrator can restrict, ban or unban chat members.
can_invite_users (``bool``, *optional*):
Pass True, if the administrator can invite new users to the chat.
can_pin_messages (``bool``, *optional*):
Pass True, if the administrator can pin messages, supergroups only.
@@ -82,17 +83,15 @@ class PromoteChatMember(BaseClient):
functions.channels.EditAdmin(
channel=await self.resolve_peer(chat_id),
user_id=await self.resolve_peer(user_id),
admin_rights=types.ChannelAdminRights(
admin_rights=types.ChatAdminRights(
change_info=can_change_info or None,
post_messages=can_post_messages or None,
edit_messages=can_edit_messages or None,
delete_messages=can_delete_messages or None,
ban_users=can_restrict_members or None,
invite_users=can_invite_users or None,
invite_link=can_invite_users or None,
pin_messages=can_pin_messages or None,
add_admins=can_promote_members or None,
manage_call=None
)
)
)

View File

@@ -98,7 +98,7 @@ class RestrictChatMember(BaseClient):
functions.channels.EditBanned(
channel=await self.resolve_peer(chat_id),
user_id=await self.resolve_peer(user_id),
banned_rights=types.ChannelBannedRights(
banned_rights=types.ChatBannedRights(
until_date=until_date,
send_messages=send_messages,
send_media=send_media,

View File

@@ -48,7 +48,7 @@ class UnbanChatMember(BaseClient):
functions.channels.EditBanned(
channel=await self.resolve_peer(chat_id),
user_id=await self.resolve_peer(user_id),
banned_rights=types.ChannelBannedRights(
banned_rights=types.ChatBannedRights(
until_date=0
)
)

View File

@@ -33,5 +33,5 @@ from .messages_and_media import (
from .update import StopPropagation, ContinuePropagation
from .user_and_chats import (
Chat, ChatMember, ChatMembers, ChatPhoto,
Dialog, Dialogs, User, UserStatus, ChatPreview
Dialog, Dialogs, User, UserStatus, ChatPreview, ChatPermissions
)

View File

@@ -97,7 +97,7 @@ class Animation(PyrogramType):
width=getattr(video_attributes, "w", 0),
height=getattr(video_attributes, "h", 0),
duration=getattr(video_attributes, "duration", 0),
thumb=PhotoSize._parse(client, animation.thumb),
thumb=PhotoSize._parse(client, animation.thumbs),
mime_type=animation.mime_type,
file_size=animation.size,
file_name=file_name,

View File

@@ -99,7 +99,7 @@ class Audio(PyrogramType):
title=audio_attributes.title,
mime_type=audio.mime_type,
file_size=audio.size,
thumb=PhotoSize._parse(client, audio.thumb),
thumb=PhotoSize._parse(client, audio.thumbs),
file_name=file_name,
date=audio.date,
client=client

View File

@@ -78,7 +78,7 @@ class Document(PyrogramType):
document.access_hash
)
),
thumb=PhotoSize._parse(client, document.thumb),
thumb=PhotoSize._parse(client, document.thumbs),
file_name=file_name,
mime_type=document.mime_type,
file_size=document.size,

View File

@@ -61,7 +61,6 @@ class Photo(PyrogramType):
for raw_size in raw_sizes:
if isinstance(raw_size, (types.PhotoSize, types.PhotoCachedSize)):
if isinstance(raw_size, types.PhotoSize):
file_size = raw_size.size
elif isinstance(raw_size, types.PhotoCachedSize):

View File

@@ -17,6 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from struct import pack
from typing import List, Union
import pyrogram
from pyrogram.api import types
@@ -56,27 +57,30 @@ class PhotoSize(PyrogramType):
self.file_size = file_size
@staticmethod
def _parse(client, photo_size: types.PhotoSize or types.PhotoCachedSize):
if isinstance(photo_size, (types.PhotoSize, types.PhotoCachedSize)):
def _parse(client, thumbs: List) -> Union["PhotoSize", None]:
if not thumbs:
return None
if isinstance(photo_size, types.PhotoSize):
file_size = photo_size.size
elif isinstance(photo_size, types.PhotoCachedSize):
file_size = len(photo_size.bytes)
else:
file_size = 0
photo_size = thumbs[-1]
loc = photo_size.location
if not isinstance(photo_size, (types.PhotoSize, types.PhotoCachedSize, types.PhotoStrippedSize)):
return None
if isinstance(loc, types.FileLocation):
return PhotoSize(
file_id=encode(
pack(
"<iiqqqqi",
0, loc.dc_id, 0, 0,
loc.volume_id, loc.secret, loc.local_id)),
width=photo_size.w,
height=photo_size.h,
file_size=file_size,
client=client
loc = photo_size.location
if not isinstance(loc, types.FileLocation):
return None
return PhotoSize(
file_id=encode(
pack(
"<iiqqqqi",
0, loc.dc_id, 0, 0,
loc.volume_id, loc.secret, loc.local_id
)
),
width=getattr(photo_size, "w", 0),
height=getattr(photo_size, "h", 0),
file_size=getattr(photo_size, "size", len(getattr(photo_size, "bytes", b""))),
client=client
)

View File

@@ -127,7 +127,7 @@ class Sticker(PyrogramType):
),
width=image_size_attributes.w if image_size_attributes else 0,
height=image_size_attributes.h if image_size_attributes else 0,
thumb=PhotoSize._parse(client, sticker.thumb),
thumb=PhotoSize._parse(client, sticker.thumbs),
# TODO: mask_position
set_name=set_name,
emoji=sticker_attributes.alt or None,

View File

@@ -97,7 +97,7 @@ class Video(PyrogramType):
width=video_attributes.w,
height=video_attributes.h,
duration=video_attributes.duration,
thumb=PhotoSize._parse(client, video.thumb),
thumb=PhotoSize._parse(client, video.thumbs),
mime_type=video.mime_type,
file_size=video.size,
file_name=file_name,

View File

@@ -85,7 +85,7 @@ class VideoNote(PyrogramType):
),
length=video_attributes.w,
duration=video_attributes.duration,
thumb=PhotoSize._parse(client, video_note.thumb),
thumb=PhotoSize._parse(client, video_note.thumbs),
file_size=video_note.size,
mime_type=video_note.mime_type,
date=video_note.date,

View File

@@ -19,6 +19,7 @@
from .chat import Chat
from .chat_member import ChatMember
from .chat_members import ChatMembers
from .chat_permissions import ChatPermissions
from .chat_photo import ChatPhoto
from .chat_preview import ChatPreview
from .dialog import Dialog

View File

@@ -18,6 +18,7 @@
import pyrogram
from pyrogram.api import types
from .chat_permissions import ChatPermissions
from .chat_photo import ChatPhoto
from ..pyrogram_type import PyrogramType
@@ -44,9 +45,6 @@ class Chat(PyrogramType):
last_name (``str``, *optional*):
Last name of the other party in a private chat.
all_members_are_administrators (``bool``, *optional*):
True if a basic group has "All Members Are Admins" enabled.
photo (:obj:`ChatPhoto <pyrogram.ChatPhoto>`, *optional*):
Chat photo. Suitable for downloads only.
@@ -86,7 +84,6 @@ class Chat(PyrogramType):
username: str = None,
first_name: str = None,
last_name: str = None,
all_members_are_administrators: bool = None,
photo: ChatPhoto = None,
description: str = None,
invite_link: str = None,
@@ -94,7 +91,8 @@ class Chat(PyrogramType):
sticker_set_name: str = None,
can_set_sticker_set: bool = None,
members_count: int = None,
restriction_reason: str = None):
restriction_reason: str = None,
default_permissions: "pyrogram.ChatPermissions" = None):
super().__init__(client)
self.id = id
@@ -103,7 +101,6 @@ class Chat(PyrogramType):
self.username = username
self.first_name = first_name
self.last_name = last_name
self.all_members_are_administrators = all_members_are_administrators
self.photo = photo
self.description = description
self.invite_link = invite_link
@@ -112,6 +109,7 @@ class Chat(PyrogramType):
self.can_set_sticker_set = can_set_sticker_set
self.members_count = members_count
self.restriction_reason = restriction_reason
self.default_permissions = default_permissions
@staticmethod
def _parse_user_chat(client, user: types.User) -> "Chat":
@@ -128,17 +126,12 @@ class Chat(PyrogramType):
@staticmethod
def _parse_chat_chat(client, chat: types.Chat) -> "Chat":
admins_enabled = getattr(chat, "admins_enabled", None)
if admins_enabled is not None:
admins_enabled = not admins_enabled
return Chat(
id=-chat.id,
type="group",
title=chat.title,
all_members_are_administrators=admins_enabled,
photo=ChatPhoto._parse(client, getattr(chat, "photo", None)),
default_permissions=ChatPermissions._parse(chat.default_banned_rights),
client=client
)
@@ -151,6 +144,7 @@ class Chat(PyrogramType):
username=getattr(channel, "username", None),
photo=ChatPhoto._parse(client, getattr(channel, "photo", None)),
restriction_reason=getattr(channel, "restriction_reason", None),
default_permissions=ChatPermissions._parse(channel.default_banned_rights),
client=client
)
@@ -197,7 +191,7 @@ class Chat(PyrogramType):
parsed_chat.description = full_chat.about or None
# TODO: Add StickerSet type
parsed_chat.can_set_sticker_set = full_chat.can_set_stickers
parsed_chat.sticker_set_name = full_chat.stickerset
parsed_chat.sticker_set_name = getattr(full_chat.stickerset, "short_name", None)
if full_chat.pinned_msg_id:
parsed_chat.pinned_message = await client.get_messages(

View File

@@ -30,8 +30,8 @@ class ChatMember(PyrogramType):
Information about the user.
status (``str``):
The member's status in the chat. Can be "creator", "administrator", "member", "restricted",
"left" or "kicked".
The member's status in the chat.
Can be "creator", "administrator", "member", "restricted", "left" or "kicked".
date (``int``, *optional*):
Date when the user joined, unix time. Not available for creator.
@@ -46,52 +46,9 @@ class ChatMember(PyrogramType):
restricted_by (:obj:`User <pyrogram.User>`, *optional*):
Restricted and kicked only. Information about the user who restricted or kicked this member.
until_date (``int``, *optional*):
Restricted and kicked only. Date when restrictions will be lifted for this user, unix time.
can_be_edited (``bool``, *optional*):
Administrators only. True, if the bot is allowed to edit administrator privileges of that user.
can_change_info (``bool``, *optional*):
Administrators only. True, if the administrator can change the chat title, photo and other settings.
can_post_messages (``bool``, *optional*):
Administrators only. True, if the administrator can post in the channel, channels only.
can_edit_messages (``bool``, *optional*):
Administrators only. True, if the administrator can edit messages of other users and can pin messages,
channels only.
can_delete_messages (``bool``, *optional*):
Administrators only. True, if the administrator can delete messages of other users.
can_invite_users (``bool``, *optional*):
Administrators only. True, if the administrator can invite new users to the chat.
can_restrict_members (``bool``, *optional*):
Administrators only. True, if the administrator can restrict, ban or unban chat members.
can_pin_messages (``bool``, *optional*):
Administrators only. True, if the administrator can pin messages, supergroups only.
can_promote_members (``bool``, *optional*):
Administrators only. True, if the administrator can add new administrators with a subset of his
own privileges or demote administrators that he has promoted, directly or indirectly (promoted by
administrators that were appointed by the user).
can_send_messages (``bool``, *optional*):
Restricted only. True, if the user can send text messages, contacts, locations and venues.
can_send_media_messages (``bool``, *optional*):
Restricted only. True, if the user can send audios, documents, photos, videos, video notes and voice notes,
implies can_send_messages.
can_send_other_messages (``bool``, *optional*):
Restricted only. True, if the user can send animations, games, stickers and use inline bots, implies
can_send_media_messages.
can_add_web_page_previews (``bool``, *optional*):
Restricted only. True, if user may add web page previews to his messages, implies can_send_media_messages.
permissions (:obj:`ChatPermissions <pyrogram.ChatPermissions>` *optional*):
Administrators, restricted and kicked members only.
Information about the member permissions.
"""
def __init__(self,
@@ -103,20 +60,7 @@ class ChatMember(PyrogramType):
invited_by: "pyrogram.User" = None,
promoted_by: "pyrogram.User" = None,
restricted_by: "pyrogram.User" = None,
until_date: int = None,
can_be_edited: bool = None,
can_change_info: bool = None,
can_post_messages: bool = None,
can_edit_messages: bool = None,
can_delete_messages: bool = None,
can_invite_users: bool = None,
can_restrict_members: bool = None,
can_pin_messages: bool = None,
can_promote_members: bool = None,
can_send_messages: bool = None,
can_send_media_messages: bool = None,
can_send_other_messages: bool = None,
can_add_web_page_previews: bool = None):
permissions: "pyrogram.ChatPermissions" = None):
super().__init__(client)
self.user = user
@@ -125,79 +69,63 @@ class ChatMember(PyrogramType):
self.invited_by = invited_by
self.promoted_by = promoted_by
self.restricted_by = restricted_by
self.until_date = until_date
self.can_be_edited = can_be_edited
self.can_change_info = can_change_info
self.can_post_messages = can_post_messages
self.can_edit_messages = can_edit_messages
self.can_delete_messages = can_delete_messages
self.can_invite_users = can_invite_users
self.can_restrict_members = can_restrict_members
self.can_pin_messages = can_pin_messages
self.can_promote_members = can_promote_members
self.can_send_messages = can_send_messages
self.can_send_media_messages = can_send_media_messages
self.can_send_other_messages = can_send_other_messages
self.can_add_web_page_previews = can_add_web_page_previews
self.permissions = permissions
@staticmethod
def _parse(client, member, users) -> "ChatMember":
user = pyrogram.User._parse(client, users[member.user_id])
invited_by = pyrogram.User._parse(client, users[member.inviter_id]) if hasattr(member, "inviter_id") else None
invited_by = (
pyrogram.User._parse(client, users[member.inviter_id])
if getattr(member, "inviter_id", None) else None
)
if isinstance(member, (types.ChannelParticipant, types.ChannelParticipantSelf, types.ChatParticipant)):
return ChatMember(user=user, status="member", date=member.date, invited_by=invited_by, client=client)
return ChatMember(
user=user,
status="member",
date=member.date,
invited_by=invited_by,
client=client
)
if isinstance(member, (types.ChannelParticipantCreator, types.ChatParticipantCreator)):
return ChatMember(user=user, status="creator", client=client)
return ChatMember(
user=user,
status="creator",
client=client
)
if isinstance(member, types.ChatParticipantAdmin):
return ChatMember(user=user, status="administrator", date=member.date, invited_by=invited_by, client=client)
return ChatMember(
user=user,
status="administrator",
date=member.date,
invited_by=invited_by,
client=client
)
if isinstance(member, types.ChannelParticipantAdmin):
rights = member.admin_rights
return ChatMember(
user=user,
status="administrator",
date=member.date,
invited_by=invited_by,
promoted_by=pyrogram.User._parse(client, users[member.promoted_by]),
can_be_edited=member.can_edit,
can_change_info=rights.change_info,
can_post_messages=rights.post_messages,
can_edit_messages=rights.edit_messages,
can_delete_messages=rights.delete_messages,
can_invite_users=rights.invite_users or rights.invite_link,
can_restrict_members=rights.ban_users,
can_pin_messages=rights.pin_messages,
can_promote_members=rights.add_admins,
permissions=pyrogram.ChatPermissions._parse(member),
client=client
)
if isinstance(member, types.ChannelParticipantBanned):
rights = member.banned_rights
chat_member = ChatMember(
return ChatMember(
user=user,
status=(
"kicked" if rights.view_messages
"kicked" if member.banned_rights.view_messages
else "left" if member.left
else "restricted"
),
date=member.date,
restricted_by=pyrogram.User._parse(client, users[member.kicked_by]),
until_date=0 if rights.until_date == (1 << 31) - 1 else rights.until_date,
permissions=pyrogram.ChatPermissions._parse(member),
client=client
)
if chat_member.status == "restricted":
chat_member.can_send_messages = not rights.send_messages
chat_member.can_send_media_messages = not rights.send_media
chat_member.can_send_other_messages = (
not rights.send_stickers or not rights.send_gifs or
not rights.send_games or not rights.send_inline
)
chat_member.can_add_web_page_previews = not rights.embed_links
return chat_member

View File

@@ -0,0 +1,182 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union
from pyrogram.api import types
from ..pyrogram_type import PyrogramType
class ChatPermissions(PyrogramType):
"""This object represents both a chat default permissions and a single member permissions within a chat.
Some permissions make sense depending on the context: default chat permissions, restricted/kicked member or
administrators in groups or channels.
Args:
until_date (``int``, *optional*):
Applicable to restricted and kicked members only.
Date when user restrictions will be lifted, unix time.
0 means the restrictions will never be lifted (user restricted forever).
can_be_edited (``bool``, *optional*):
Applicable to administrators only.
True, if you are allowed to edit administrator privileges of the user.
can_change_info (``bool``, *optional*):
Applicable to default chat permissions in private groups and administrators in public groups only.
True, if the chat title, photo and other settings can be changed.
can_post_messages (``bool``, *optional*):
Applicable to channel administrators only.
True, if the administrator can post messages in the channel, channels only.
can_edit_messages (``bool``, *optional*):
Applicable to channel administrators only.
True, if the administrator can edit messages of other users and can pin messages, channels only.
can_delete_messages (``bool``, *optional*):
Applicable to administrators only.
True, if the administrator can delete messages of other users.
can_restrict_members (``bool``, *optional*):
Applicable to administrators only.
True, if the administrator can restrict, ban or unban chat members.
can_invite_users (``bool``, *optional*):
Applicable to default chat permissions and administrators only.
True, if new users can be invited to the chat.
can_pin_messages (``bool``, *optional*):
Applicable to default chat permissions in private groups and administrators in public groups only.
True, if messages can be pinned, supergroups only.
can_promote_members (``bool``, *optional*):
Applicable to administrators only.
True, if the administrator can add new administrators with a subset of his own privileges or demote
administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed
by the user).
can_send_messages (``bool``, *optional*):
Applicable to default chat permissions and restricted members only.
True, if text messages, contacts, locations and venues can be sent.
can_send_media_messages (``bool``, *optional*):
Applicable to default chat permissions and restricted members only.
True, if audios, documents, photos, videos, video notes and voice notes can be sent, implies
can_send_messages.
can_send_other_messages (``bool``, *optional*):
Applicable to default chat permissions and restricted members only.
True, if animations, games, stickers and inline bot results can be sent, implies can_send_media_messages.
can_add_web_page_previews (``bool``, *optional*):
Applicable to default chat permissions and restricted members only.
True, if web page previews can be attached to text messages, implies can_send_media_messages.
can_send_polls (``bool``, *optional*):
Applicable to default chat permissions and restricted members only.
True, if polls can be sent, implies can_send_media_messages.
"""
def __init__(
self,
*,
until_date: int = None,
# Admin permissions
can_be_edited: bool = None,
can_change_info: bool = None,
can_post_messages: bool = None, # Channels only
can_edit_messages: bool = None, # Channels only
can_delete_messages: bool = None,
can_restrict_members: bool = None,
can_invite_users: bool = None,
can_pin_messages: bool = None, # Supergroups only
can_promote_members: bool = None,
# Restricted user permissions
can_send_messages: bool = None, # Text, contacts, locations and venues
can_send_media_messages: bool = None, # Audios, documents, photos, videos, video notes and voice notes
can_send_other_messages: bool = None, # Animations (GIFs), games, stickers, inline bot results
can_add_web_page_previews: bool = None,
can_send_polls: bool = None
):
super().__init__(None)
self.until_date = until_date
self.can_be_edited = can_be_edited
self.can_change_info = can_change_info
self.can_post_messages = can_post_messages
self.can_edit_messages = can_edit_messages
self.can_delete_messages = can_delete_messages
self.can_restrict_members = can_restrict_members
self.can_invite_users = can_invite_users
self.can_pin_messages = can_pin_messages
self.can_promote_members = can_promote_members
self.can_send_messages = can_send_messages
self.can_send_media_messages = can_send_media_messages
self.can_send_other_messages = can_send_other_messages
self.can_add_web_page_previews = can_add_web_page_previews
self.can_send_polls = can_send_polls
@staticmethod
def _parse(
entity: Union[
types.ChannelParticipantAdmin,
types.ChannelParticipantBanned,
types.ChatBannedRights
]
) -> "ChatPermissions":
if isinstance(entity, types.ChannelParticipantAdmin):
permissions = entity.admin_rights
return ChatPermissions(
can_be_edited=entity.can_edit,
can_change_info=permissions.change_info,
can_post_messages=permissions.post_messages,
can_edit_messages=permissions.edit_messages,
can_delete_messages=permissions.delete_messages,
can_restrict_members=permissions.ban_users,
can_invite_users=permissions.invite_users,
can_pin_messages=permissions.pin_messages,
can_promote_members=permissions.add_admins
)
if isinstance(entity, (types.ChannelParticipantBanned, types.ChatBannedRights)):
if isinstance(entity, types.ChannelParticipantBanned):
denied_permissions = entity.banned_rights # type: types.ChatBannedRights
else:
denied_permissions = entity
return ChatPermissions(
until_date=0 if denied_permissions.until_date == (1 << 31) - 1 else denied_permissions.until_date,
can_send_messages=not denied_permissions.send_messages,
can_send_media_messages=not denied_permissions.send_media,
can_send_other_messages=(
not denied_permissions.send_stickers or not denied_permissions.send_gifs or
not denied_permissions.send_games or not denied_permissions.send_inline
),
can_add_web_page_previews=not denied_permissions.embed_links,
can_send_polls=not denied_permissions.send_polls,
can_change_info=not denied_permissions.change_info,
can_invite_users=not denied_permissions.invite_users,
can_pin_messages=not denied_permissions.pin_messages
)