mirror of
https://github.com/pyrogram/pyrogram
synced 2025-08-29 05:18:10 +00:00
Merge branch 'develop' into session_storage
# Conflicts: # pyrogram/client/client.py # pyrogram/client/ext/base_client.py # pyrogram/client/ext/syncer.py # pyrogram/client/style/html.py # pyrogram/client/style/markdown.py
This commit is contained in:
commit
952f0627f1
@ -32,7 +32,7 @@ Features
|
|||||||
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
||||||
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
|
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
|
||||||
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
||||||
- **Updated**, to the latest Telegram API version, currently Layer 91 on top of `MTProto 2.0`_.
|
- **Updated**, to the latest Telegram API version, currently Layer 97 on top of `MTProto 2.0`_.
|
||||||
- **Pluggable**: The Smart Plugin system allows to write components with minimal boilerplate code.
|
- **Pluggable**: The Smart Plugin system allows to write components with minimal boilerplate code.
|
||||||
- **Comprehensive**: Execute any advanced action an official client is able to do, and even more.
|
- **Comprehensive**: Execute any advanced action an official client is able to do, and even more.
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ Copyright & License
|
|||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<a href="compiler/api/source/main_api.tl">
|
<a href="compiler/api/source/main_api.tl">
|
||||||
<img src="https://img.shields.io/badge/schema-layer%2091-eda738.svg?longCache=true&colorA=262b30"
|
<img src="https://img.shields.io/badge/schema-layer%2097-eda738.svg?longCache=true&colorA=262b30"
|
||||||
alt="Schema Layer">
|
alt="Schema Layer">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/pyrogram/tgcrypto">
|
<a href="https://github.com/pyrogram/tgcrypto">
|
||||||
@ -122,7 +122,7 @@ Copyright & License
|
|||||||
|
|
||||||
.. |description| replace:: **Telegram MTProto API Framework for Python**
|
.. |description| replace:: **Telegram MTProto API Framework for Python**
|
||||||
|
|
||||||
.. |schema| image:: https://img.shields.io/badge/schema-layer%2091-eda738.svg?longCache=true&colorA=262b30
|
.. |schema| image:: https://img.shields.io/badge/schema-layer%2097-eda738.svg?longCache=true&colorA=262b30
|
||||||
:target: compiler/api/source/main_api.tl
|
:target: compiler/api/source/main_api.tl
|
||||||
:alt: Schema Layer
|
:alt: Schema Layer
|
||||||
|
|
||||||
|
@ -287,9 +287,11 @@ def start():
|
|||||||
|
|
||||||
sorted_args = sort_args(c.args)
|
sorted_args = sort_args(c.args)
|
||||||
|
|
||||||
arguments = ", " + ", ".join(
|
arguments = (
|
||||||
[get_argument_type(i) for i in sorted_args if i != ("flags", "#")]
|
", "
|
||||||
) if c.args else ""
|
+ ("*, " if c.args else "")
|
||||||
|
+ (", ".join([get_argument_type(i) for i in sorted_args if i != ("flags", "#")]) if c.args else "")
|
||||||
|
)
|
||||||
|
|
||||||
fields = "\n ".join(
|
fields = "\n ".join(
|
||||||
["self.{0} = {0} # {1}".format(i[0], i[1]) for i in c.args if i != ("flags", "#")]
|
["self.{0} = {0} # {1}".format(i[0], i[1]) for i in c.args if i != ("flags", "#")]
|
||||||
@ -333,7 +335,7 @@ def start():
|
|||||||
docstring_args = "Attributes:\n ID: ``{}``\n\n ".format(c.id) + docstring_args
|
docstring_args = "Attributes:\n ID: ``{}``\n\n ".format(c.id) + docstring_args
|
||||||
|
|
||||||
if c.section == "functions":
|
if c.section == "functions":
|
||||||
docstring_args += "\n\n Raises:\n :obj:`Error <pyrogram.Error>`"
|
docstring_args += "\n\n Raises:\n :obj:`RPCError <pyrogram.RPCError>`"
|
||||||
docstring_args += "\n\n Returns:\n " + get_docstring_arg_type(c.return_type)
|
docstring_args += "\n\n Returns:\n " + get_docstring_arg_type(c.return_type)
|
||||||
else:
|
else:
|
||||||
references = get_references(".".join(filter(None, [c.namespace, c.name])))
|
references = get_references(".".join(filter(None, [c.namespace, c.name])))
|
||||||
@ -456,7 +458,11 @@ def start():
|
|||||||
fields=fields,
|
fields=fields,
|
||||||
read_types=read_types,
|
read_types=read_types,
|
||||||
write_types=write_types,
|
write_types=write_types,
|
||||||
return_arguments=", ".join([i[0] for i in sorted_args if i != ("flags", "#")])
|
return_arguments=", ".join(
|
||||||
|
["{0}={0}".format(i[0]) for i in sorted_args if i != ("flags", "#")]
|
||||||
|
),
|
||||||
|
slots=", ".join(['"{}"'.format(i[0]) for i in sorted_args if i != ("flags", "#")]),
|
||||||
|
qualname="{}{}".format("{}.".format(c.namespace) if c.namespace else "", c.name)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileL
|
|||||||
fileLocation#91d11eb dc_id:int volume_id:long local_id:int secret:long file_reference:bytes = FileLocation;
|
fileLocation#91d11eb dc_id:int volume_id:long local_id:int secret:long file_reference:bytes = FileLocation;
|
||||||
|
|
||||||
userEmpty#200250ba id:int = User;
|
userEmpty#200250ba id:int = User;
|
||||||
user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
user#2e13f4c3 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?string bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
||||||
|
|
||||||
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
||||||
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
|
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
|
||||||
@ -96,12 +96,12 @@ userStatusLastWeek#7bf09fc = UserStatus;
|
|||||||
userStatusLastMonth#77ebc742 = UserStatus;
|
userStatusLastMonth#77ebc742 = UserStatus;
|
||||||
|
|
||||||
chatEmpty#9ba2d800 id:int = Chat;
|
chatEmpty#9ba2d800 id:int = Chat;
|
||||||
chat#d91cdd54 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true admins_enabled:flags.3?true admin:flags.4?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel = Chat;
|
chat#3bda1bde flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true id:int title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
|
||||||
chatForbidden#7328bdb id:int title:string = Chat;
|
chatForbidden#7328bdb id:int title:string = Chat;
|
||||||
channel#c88974ac flags:# creator:flags.0?true left:flags.2?true editor:flags.3?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true democracy:flags.10?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChannelAdminRights banned_rights:flags.15?ChannelBannedRights participants_count:flags.17?int = Chat;
|
channel#4df30834 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?string admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||||
|
|
||||||
chatFull#edd2a791 flags:# id:int participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int = ChatFull;
|
chatFull#22a235da flags:# can_set_username:flags.7?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int = ChatFull;
|
||||||
channelFull#1c87a71a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;
|
channelFull#1c87a71a flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_view_stats:flags.12?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int = ChatFull;
|
||||||
|
|
||||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||||
@ -163,6 +163,7 @@ photo#9c477dd8 flags:# has_stickers:flags.0?true id:long access_hash:long file_r
|
|||||||
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
photoSizeEmpty#e17e23c type:string = PhotoSize;
|
||||||
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
|
||||||
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
|
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
|
||||||
|
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
|
||||||
|
|
||||||
geoPointEmpty#1117dd5f = GeoPoint;
|
geoPointEmpty#1117dd5f = GeoPoint;
|
||||||
geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
|
geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
|
||||||
@ -186,8 +187,7 @@ peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bo
|
|||||||
|
|
||||||
peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings;
|
peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings;
|
||||||
|
|
||||||
wallPaper#ccb03657 id:int title:string sizes:Vector<PhotoSize> color:int = WallPaper;
|
wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
|
||||||
wallPaperSolid#63117f24 id:int title:string bg_color:int color:int = WallPaper;
|
|
||||||
|
|
||||||
inputReportReasonSpam#58dbcab8 = ReportReason;
|
inputReportReasonSpam#58dbcab8 = ReportReason;
|
||||||
inputReportReasonViolence#1e22c78d = ReportReason;
|
inputReportReasonViolence#1e22c78d = ReportReason;
|
||||||
@ -221,7 +221,7 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
|
|||||||
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
|
||||||
|
|
||||||
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||||
messages.messagesSlice#b446ae3 count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
messages.messagesSlice#a6c47aaa flags:# inexact:flags.1?true count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||||
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
|
||||||
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
messages.messagesNotModified#74535f21 count:int = messages.Messages;
|
||||||
|
|
||||||
@ -281,7 +281,6 @@ updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
|
|||||||
updateReadChannelInbox#4214f37f channel_id:int max_id:int = Update;
|
updateReadChannelInbox#4214f37f channel_id:int max_id:int = Update;
|
||||||
updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
updateDeleteChannelMessages#c37521c9 channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update;
|
updateChannelMessageViews#98a12b4b channel_id:int id:int views:int = Update;
|
||||||
updateChatAdmins#6e947941 chat_id:int enabled:Bool version:int = Update;
|
|
||||||
updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update;
|
updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update;
|
||||||
updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update;
|
updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update;
|
||||||
updateStickerSetsOrder#bb2d201 flags:# masks:flags.0?true order:Vector<long> = Update;
|
updateStickerSetsOrder#bb2d201 flags:# masks:flags.0?true order:Vector<long> = Update;
|
||||||
@ -316,8 +315,9 @@ updateContactsReset#7084a7be = Update;
|
|||||||
updateChannelAvailableMessages#70db6837 channel_id:int available_min_id:int = Update;
|
updateChannelAvailableMessages#70db6837 channel_id:int available_min_id:int = Update;
|
||||||
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
|
||||||
updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
|
updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
|
||||||
updateChatPinnedMessage#22893b26 chat_id:int id:int = Update;
|
updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
|
||||||
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
|
||||||
|
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
|
||||||
|
|
||||||
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ inputDocumentEmpty#72f0eaae = InputDocument;
|
|||||||
inputDocument#1abfb575 id:long access_hash:long file_reference:bytes = InputDocument;
|
inputDocument#1abfb575 id:long access_hash:long file_reference:bytes = InputDocument;
|
||||||
|
|
||||||
documentEmpty#36f8c871 id:long = Document;
|
documentEmpty#36f8c871 id:long = Document;
|
||||||
document#59534e4c id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = Document;
|
document#9ba29cc1 flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document;
|
||||||
|
|
||||||
help.support#17c6b5f6 phone_number:string user:User = help.Support;
|
help.support#17c6b5f6 phone_number:string user:User = help.Support;
|
||||||
|
|
||||||
@ -411,11 +411,15 @@ inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
|
|||||||
inputPrivacyKeyChatInvite#bdfb0426 = InputPrivacyKey;
|
inputPrivacyKeyChatInvite#bdfb0426 = InputPrivacyKey;
|
||||||
inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
|
inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
|
||||||
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
|
||||||
|
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
|
||||||
|
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
|
||||||
|
|
||||||
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
|
||||||
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
privacyKeyChatInvite#500e6dfa = PrivacyKey;
|
||||||
privacyKeyPhoneCall#3d662b7b = PrivacyKey;
|
privacyKeyPhoneCall#3d662b7b = PrivacyKey;
|
||||||
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
|
||||||
|
privacyKeyForwards#69ec56a3 = PrivacyKey;
|
||||||
|
privacyKeyProfilePhoto#96151fed = PrivacyKey;
|
||||||
|
|
||||||
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
|
||||||
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
|
||||||
@ -487,7 +491,7 @@ inputStickerSetEmpty#ffb62b95 = InputStickerSet;
|
|||||||
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
|
||||||
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
||||||
|
|
||||||
stickerSet#5585a139 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string count:int hash:int = StickerSet;
|
stickerSet#6a90bcb7 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize count:int hash:int = StickerSet;
|
||||||
|
|
||||||
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
||||||
|
|
||||||
@ -544,8 +548,8 @@ channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:
|
|||||||
channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant;
|
channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant;
|
||||||
channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant;
|
channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant;
|
||||||
channelParticipantCreator#e3e2e1f9 user_id:int = ChannelParticipant;
|
channelParticipantCreator#e3e2e1f9 user_id:int = ChannelParticipant;
|
||||||
channelParticipantAdmin#a82fa898 flags:# can_edit:flags.0?true user_id:int inviter_id:int promoted_by:int date:int admin_rights:ChannelAdminRights = ChannelParticipant;
|
channelParticipantAdmin#5daa6e23 flags:# can_edit:flags.0?true self:flags.1?true user_id:int inviter_id:flags.1?int promoted_by:int date:int admin_rights:ChatAdminRights = ChannelParticipant;
|
||||||
channelParticipantBanned#222c1886 flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChannelBannedRights = ChannelParticipant;
|
channelParticipantBanned#1c0facaf flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant;
|
||||||
|
|
||||||
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
|
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
|
||||||
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
|
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
|
||||||
@ -553,6 +557,7 @@ channelParticipantsKicked#a3b54985 q:string = ChannelParticipantsFilter;
|
|||||||
channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
|
channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
|
||||||
channelParticipantsBanned#1427a5e1 q:string = ChannelParticipantsFilter;
|
channelParticipantsBanned#1427a5e1 q:string = ChannelParticipantsFilter;
|
||||||
channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
|
channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
|
||||||
|
channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter;
|
||||||
|
|
||||||
channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParticipant> users:Vector<User> = channels.ChannelParticipants;
|
channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParticipant> users:Vector<User> = channels.ChannelParticipants;
|
||||||
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
|
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
|
||||||
@ -594,7 +599,7 @@ messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_off
|
|||||||
|
|
||||||
exportedMessageLink#5dab1af4 link:string html:string = ExportedMessageLink;
|
exportedMessageLink#5dab1af4 link:string html:string = ExportedMessageLink;
|
||||||
|
|
||||||
messageFwdHeader#559ebe6d flags:# from_id:flags.0?int date:int channel_id:flags.1?int channel_post:flags.2?int post_author:flags.3?string saved_from_peer:flags.4?Peer saved_from_msg_id:flags.4?int = MessageFwdHeader;
|
messageFwdHeader#ec338270 flags:# from_id:flags.0?int from_name:flags.5?string date:int channel_id:flags.1?int channel_post:flags.2?int post_author:flags.3?string saved_from_peer:flags.4?Peer saved_from_msg_id:flags.4?int = MessageFwdHeader;
|
||||||
|
|
||||||
auth.codeTypeSms#72a3158c = auth.CodeType;
|
auth.codeTypeSms#72a3158c = auth.CodeType;
|
||||||
auth.codeTypeCall#741cd3e3 = auth.CodeType;
|
auth.codeTypeCall#741cd3e3 = auth.CodeType;
|
||||||
@ -789,10 +794,6 @@ langPackDifference#f385c1f6 lang_code:string from_version:int version:int string
|
|||||||
|
|
||||||
langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:flags.3?true name:string native_name:string lang_code:string base_lang_code:flags.1?string plural_code:string strings_count:int translated_count:int translations_url:string = LangPackLanguage;
|
langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:flags.3?true name:string native_name:string lang_code:string base_lang_code:flags.1?string plural_code:string strings_count:int translated_count:int translations_url:string = LangPackLanguage;
|
||||||
|
|
||||||
channelAdminRights#5d7ceba5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true invite_link:flags.6?true pin_messages:flags.7?true add_admins:flags.9?true manage_call:flags.10?true = ChannelAdminRights;
|
|
||||||
|
|
||||||
channelBannedRights#58cf4249 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true until_date:int = ChannelBannedRights;
|
|
||||||
|
|
||||||
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
|
||||||
@ -809,6 +810,8 @@ channelAdminLogEventActionParticipantToggleBan#e6d83d7e prev_participant:Channel
|
|||||||
channelAdminLogEventActionParticipantToggleAdmin#d5676710 prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
|
channelAdminLogEventActionParticipantToggleAdmin#d5676710 prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = ChannelAdminLogEventAction;
|
channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = ChannelAdminLogEventAction;
|
||||||
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
|
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
|
||||||
|
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
|
||||||
|
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
|
||||||
|
|
||||||
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
|
||||||
|
|
||||||
@ -972,6 +975,31 @@ chatOnlines#f041e250 onlines:int = ChatOnlines;
|
|||||||
|
|
||||||
statsURL#47a971e0 url:string = StatsURL;
|
statsURL#47a971e0 url:string = StatsURL;
|
||||||
|
|
||||||
|
chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true = ChatAdminRights;
|
||||||
|
|
||||||
|
chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true until_date:int = ChatBannedRights;
|
||||||
|
|
||||||
|
inputWallPaper#e630b979 id:long access_hash:long = InputWallPaper;
|
||||||
|
inputWallPaperSlug#72091c80 slug:string = InputWallPaper;
|
||||||
|
|
||||||
|
account.wallPapersNotModified#1c199183 = account.WallPapers;
|
||||||
|
account.wallPapers#702b65a9 hash:int wallpapers:Vector<WallPaper> = account.WallPapers;
|
||||||
|
|
||||||
|
codeSettings#302f59f3 flags:# allow_flashcall:flags.0?true current_number:flags.1?true app_hash_persistent:flags.2?true app_hash:flags.3?string = CodeSettings;
|
||||||
|
|
||||||
|
wallPaperSettings#a12f40b8 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int intensity:flags.3?int = WallPaperSettings;
|
||||||
|
|
||||||
|
autoDownloadSettings#d246fd47 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:int file_size_max:int = AutoDownloadSettings;
|
||||||
|
|
||||||
|
account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;
|
||||||
|
|
||||||
|
emojiKeyword#d5b3b9f9 keyword:string emoticons:Vector<string> = EmojiKeyword;
|
||||||
|
emojiKeywordDeleted#236df622 keyword:string emoticons:Vector<string> = EmojiKeyword;
|
||||||
|
|
||||||
|
emojiKeywordsDifference#5cc761bd lang_code:string from_version:int version:int keywords:Vector<EmojiKeyword> = EmojiKeywordsDifference;
|
||||||
|
|
||||||
|
emojiURL#a575739d url:string = EmojiURL;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
@ -982,7 +1010,7 @@ invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
|
|||||||
invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange query:!X = X;
|
invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange query:!X = X;
|
||||||
invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;
|
invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;
|
||||||
|
|
||||||
auth.sendCode#86aef0ec flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool api_id:int api_hash:string = auth.SentCode;
|
auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode;
|
||||||
auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization;
|
auth.signUp#1b067634 phone_number:string phone_code_hash:string phone_code:string first_name:string last_name:string = auth.Authorization;
|
||||||
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
|
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
|
||||||
auth.logOut#5717da40 = Bool;
|
auth.logOut#5717da40 = Bool;
|
||||||
@ -1005,7 +1033,7 @@ account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
|
|||||||
account.resetNotifySettings#db7e1747 = Bool;
|
account.resetNotifySettings#db7e1747 = Bool;
|
||||||
account.updateProfile#78515775 flags:# first_name:flags.0?string last_name:flags.1?string about:flags.2?string = User;
|
account.updateProfile#78515775 flags:# first_name:flags.0?string last_name:flags.1?string about:flags.2?string = User;
|
||||||
account.updateStatus#6628562c offline:Bool = Bool;
|
account.updateStatus#6628562c offline:Bool = Bool;
|
||||||
account.getWallPapers#c04cfac2 = Vector<WallPaper>;
|
account.getWallPapers#aabb1763 hash:int = account.WallPapers;
|
||||||
account.reportPeer#ae189d5f peer:InputPeer reason:ReportReason = Bool;
|
account.reportPeer#ae189d5f peer:InputPeer reason:ReportReason = Bool;
|
||||||
account.checkUsername#2714d86c username:string = Bool;
|
account.checkUsername#2714d86c username:string = Bool;
|
||||||
account.updateUsername#3e0bdd7c username:string = User;
|
account.updateUsername#3e0bdd7c username:string = User;
|
||||||
@ -1014,7 +1042,7 @@ account.setPrivacy#c9f81ce8 key:InputPrivacyKey rules:Vector<InputPrivacyRule> =
|
|||||||
account.deleteAccount#418d4e0b reason:string = Bool;
|
account.deleteAccount#418d4e0b reason:string = Bool;
|
||||||
account.getAccountTTL#8fc711d = AccountDaysTTL;
|
account.getAccountTTL#8fc711d = AccountDaysTTL;
|
||||||
account.setAccountTTL#2442485e ttl:AccountDaysTTL = Bool;
|
account.setAccountTTL#2442485e ttl:AccountDaysTTL = Bool;
|
||||||
account.sendChangePhoneCode#8e57deb flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool = auth.SentCode;
|
account.sendChangePhoneCode#82574ae5 phone_number:string settings:CodeSettings = auth.SentCode;
|
||||||
account.changePhone#70c32edb phone_number:string phone_code_hash:string phone_code:string = User;
|
account.changePhone#70c32edb phone_number:string phone_code_hash:string phone_code:string = User;
|
||||||
account.updateDeviceLocked#38df3532 period:int = Bool;
|
account.updateDeviceLocked#38df3532 period:int = Bool;
|
||||||
account.getAuthorizations#e320c158 = account.Authorizations;
|
account.getAuthorizations#e320c158 = account.Authorizations;
|
||||||
@ -1022,7 +1050,7 @@ account.resetAuthorization#df77f3bc hash:long = Bool;
|
|||||||
account.getPassword#548a30f5 = account.Password;
|
account.getPassword#548a30f5 = account.Password;
|
||||||
account.getPasswordSettings#9cd4eaf9 password:InputCheckPasswordSRP = account.PasswordSettings;
|
account.getPasswordSettings#9cd4eaf9 password:InputCheckPasswordSRP = account.PasswordSettings;
|
||||||
account.updatePasswordSettings#a59b102f password:InputCheckPasswordSRP new_settings:account.PasswordInputSettings = Bool;
|
account.updatePasswordSettings#a59b102f password:InputCheckPasswordSRP new_settings:account.PasswordInputSettings = Bool;
|
||||||
account.sendConfirmPhoneCode#1516d7bd flags:# allow_flashcall:flags.0?true hash:string current_number:flags.0?Bool = auth.SentCode;
|
account.sendConfirmPhoneCode#1b3faa88 hash:string settings:CodeSettings = auth.SentCode;
|
||||||
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
|
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
|
||||||
account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
|
account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
|
||||||
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
|
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
|
||||||
@ -1034,7 +1062,7 @@ account.saveSecureValue#899fe31d value:InputSecureValue secure_secret_id:long =
|
|||||||
account.deleteSecureValue#b880bc4b types:Vector<SecureValueType> = Bool;
|
account.deleteSecureValue#b880bc4b types:Vector<SecureValueType> = Bool;
|
||||||
account.getAuthorizationForm#b86ba8e1 bot_id:int scope:string public_key:string = account.AuthorizationForm;
|
account.getAuthorizationForm#b86ba8e1 bot_id:int scope:string public_key:string = account.AuthorizationForm;
|
||||||
account.acceptAuthorization#e7027c94 bot_id:int scope:string public_key:string value_hashes:Vector<SecureValueHash> credentials:SecureCredentialsEncrypted = Bool;
|
account.acceptAuthorization#e7027c94 bot_id:int scope:string public_key:string value_hashes:Vector<SecureValueHash> credentials:SecureCredentialsEncrypted = Bool;
|
||||||
account.sendVerifyPhoneCode#823380b4 flags:# allow_flashcall:flags.0?true phone_number:string current_number:flags.0?Bool = auth.SentCode;
|
account.sendVerifyPhoneCode#a5a356f9 phone_number:string settings:CodeSettings = auth.SentCode;
|
||||||
account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
|
account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
|
||||||
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
|
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
|
||||||
account.verifyEmail#ecba39db email:string code:string = Bool;
|
account.verifyEmail#ecba39db email:string code:string = Bool;
|
||||||
@ -1046,6 +1074,13 @@ account.cancelPasswordEmail#c1cbd5b6 = Bool;
|
|||||||
account.getContactSignUpNotification#9f07c728 = Bool;
|
account.getContactSignUpNotification#9f07c728 = Bool;
|
||||||
account.setContactSignUpNotification#cff43f61 silent:Bool = Bool;
|
account.setContactSignUpNotification#cff43f61 silent:Bool = Bool;
|
||||||
account.getNotifyExceptions#53577479 flags:# compare_sound:flags.1?true peer:flags.0?InputNotifyPeer = Updates;
|
account.getNotifyExceptions#53577479 flags:# compare_sound:flags.1?true peer:flags.0?InputNotifyPeer = Updates;
|
||||||
|
account.getWallPaper#fc8ddbea wallpaper:InputWallPaper = WallPaper;
|
||||||
|
account.uploadWallPaper#dd853661 file:InputFile mime_type:string settings:WallPaperSettings = WallPaper;
|
||||||
|
account.saveWallPaper#6c5a5b37 wallpaper:InputWallPaper unsave:Bool settings:WallPaperSettings = Bool;
|
||||||
|
account.installWallPaper#feed5769 wallpaper:InputWallPaper settings:WallPaperSettings = Bool;
|
||||||
|
account.resetWallPapers#bb3b9804 = Bool;
|
||||||
|
account.getAutoDownloadSettings#56da0b3f = account.AutoDownloadSettings;
|
||||||
|
account.saveAutoDownloadSettings#76f36233 flags:# low:flags.0?true high:flags.1?true settings:AutoDownloadSettings = Bool;
|
||||||
|
|
||||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||||
@ -1074,7 +1109,7 @@ messages.getDialogs#b098aee6 flags:# exclude_pinned:flags.0?true offset_date:int
|
|||||||
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||||
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
|
||||||
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
||||||
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true peer:InputPeer max_id:int = messages.AffectedHistory;
|
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int = messages.AffectedHistory;
|
||||||
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
|
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
|
||||||
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
||||||
messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool;
|
messages.setTyping#a3825e50 peer:InputPeer action:SendMessageAction = Bool;
|
||||||
@ -1107,7 +1142,7 @@ messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages
|
|||||||
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
||||||
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
||||||
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
||||||
messages.exportChatInvite#7d885289 chat_id:int = ExportedChatInvite;
|
messages.exportChatInvite#df7534c peer:InputPeer = ExportedChatInvite;
|
||||||
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
|
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
|
||||||
messages.importChatInvite#6c50051c hash:string = Updates;
|
messages.importChatInvite#6c50051c hash:string = Updates;
|
||||||
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
|
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
|
||||||
@ -1115,7 +1150,6 @@ messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = m
|
|||||||
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
|
||||||
messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates;
|
messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates;
|
||||||
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
|
||||||
messages.toggleChatAdmins#ec8bd9e1 chat_id:int enabled:Bool = Updates;
|
|
||||||
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
|
||||||
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
messages.migrateChat#15a3b8e3 chat_id:int = Updates;
|
||||||
messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
messages.searchGlobal#9e3cacb0 q:string offset_date:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
|
||||||
@ -1173,7 +1207,12 @@ messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true peer:InputPeer
|
|||||||
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
|
||||||
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
|
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
|
||||||
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
|
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
|
||||||
messages.getStatsURL#83f6c0cd peer:InputPeer = StatsURL;
|
messages.getStatsURL#812c2ae6 flags:# dark:flags.0?true peer:InputPeer params:string = StatsURL;
|
||||||
|
messages.editChatAbout#def60797 peer:InputPeer about:string = Bool;
|
||||||
|
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
|
||||||
|
messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
|
||||||
|
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
|
||||||
|
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
||||||
|
|
||||||
updates.getState#edd4882a = updates.State;
|
updates.getState#edd4882a = updates.State;
|
||||||
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
|
||||||
@ -1223,8 +1262,7 @@ channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channe
|
|||||||
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
||||||
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
||||||
channels.createChannel#f4893d7f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string = Updates;
|
channels.createChannel#f4893d7f flags:# broadcast:flags.0?true megagroup:flags.1?true title:string about:string = Updates;
|
||||||
channels.editAbout#13e27f1e channel:InputChannel about:string = Bool;
|
channels.editAdmin#70f893ba channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights = Updates;
|
||||||
channels.editAdmin#20b88214 channel:InputChannel user_id:InputUser admin_rights:ChannelAdminRights = Updates;
|
|
||||||
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
|
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
|
||||||
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
|
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
|
||||||
channels.checkUsername#10e6bd2c channel:InputChannel username:string = Bool;
|
channels.checkUsername#10e6bd2c channel:InputChannel username:string = Bool;
|
||||||
@ -1232,13 +1270,11 @@ channels.updateUsername#3514b3de channel:InputChannel username:string = Bool;
|
|||||||
channels.joinChannel#24b524c5 channel:InputChannel = Updates;
|
channels.joinChannel#24b524c5 channel:InputChannel = Updates;
|
||||||
channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
|
channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
|
||||||
channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> = Updates;
|
channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> = Updates;
|
||||||
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
|
|
||||||
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
||||||
channels.toggleInvites#49609307 channel:InputChannel enabled:Bool = Updates;
|
|
||||||
channels.exportMessageLink#ceb77163 channel:InputChannel id:int grouped:Bool = ExportedMessageLink;
|
channels.exportMessageLink#ceb77163 channel:InputChannel id:int grouped:Bool = ExportedMessageLink;
|
||||||
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
|
channels.getAdminedPublicChannels#8d8d82d7 = messages.Chats;
|
||||||
channels.editBanned#bfd915cd channel:InputChannel user_id:InputUser banned_rights:ChannelBannedRights = Updates;
|
channels.editBanned#72796912 channel:InputChannel user_id:InputUser banned_rights:ChatBannedRights = Updates;
|
||||||
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
||||||
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
|
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
|
||||||
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
|
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
|
||||||
@ -1267,13 +1303,13 @@ phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtoc
|
|||||||
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
|
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
|
||||||
phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool;
|
phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool;
|
||||||
phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
|
phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
|
||||||
phone.setCallRating#1c536a34 peer:InputPhoneCall rating:int comment:string = Updates;
|
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
||||||
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
||||||
|
|
||||||
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
|
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
|
||||||
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
||||||
langpack.getDifference#9d51e814 lang_code:string from_version:int = LangPackDifference;
|
langpack.getDifference#cd984aa5 lang_pack:string lang_code:string from_version:int = LangPackDifference;
|
||||||
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
|
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
|
||||||
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
|
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
|
||||||
|
|
||||||
// LAYER 91
|
// LAYER 97
|
||||||
|
@ -9,7 +9,10 @@ class {class_name}(Object):
|
|||||||
"""{docstring_args}
|
"""{docstring_args}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__slots__ = [{slots}]
|
||||||
|
|
||||||
ID = {object_id}
|
ID = {object_id}
|
||||||
|
QUALNAME = "{qualname}"
|
||||||
|
|
||||||
def __init__(self{arguments}):
|
def __init__(self{arguments}):
|
||||||
{fields}
|
{fields}
|
||||||
|
@ -22,7 +22,7 @@ import re
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
HOME = "compiler/error"
|
HOME = "compiler/error"
|
||||||
DEST = "pyrogram/api/errors/exceptions"
|
DEST = "pyrogram/errors/exceptions"
|
||||||
NOTICE_PATH = "NOTICE"
|
NOTICE_PATH = "NOTICE"
|
||||||
|
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ def start():
|
|||||||
|
|
||||||
if "__main__" == __name__:
|
if "__main__" == __name__:
|
||||||
HOME = "."
|
HOME = "."
|
||||||
DEST = "../../pyrogram/api/errors/exceptions"
|
DEST = "../../pyrogram/errors/exceptions"
|
||||||
NOTICE_PATH = "../../NOTICE"
|
NOTICE_PATH = "../../NOTICE"
|
||||||
|
|
||||||
start()
|
start()
|
||||||
|
@ -88,5 +88,12 @@ MEDIA_INVALID The media is invalid
|
|||||||
BOT_SCORE_NOT_MODIFIED The bot score was not modified
|
BOT_SCORE_NOT_MODIFIED The bot score was not modified
|
||||||
USER_BOT_REQUIRED The method can be used by bots only
|
USER_BOT_REQUIRED The method can be used by bots only
|
||||||
IMAGE_PROCESS_FAILED The server failed to process your image
|
IMAGE_PROCESS_FAILED The server failed to process your image
|
||||||
|
USERNAME_NOT_MODIFIED The username was not modified
|
||||||
CALL_ALREADY_ACCEPTED The call is already accepted
|
CALL_ALREADY_ACCEPTED The call is already accepted
|
||||||
CALL_ALREADY_DECLINED The call is already declined
|
CALL_ALREADY_DECLINED The call is already declined
|
||||||
|
PHOTO_EXT_INVALID The photo extension is invalid
|
||||||
|
EXTERNAL_URL_INVALID The external media URL is invalid
|
||||||
|
CHAT_NOT_MODIFIED The chat settings were not modified
|
||||||
|
RESULTS_TOO_MUCH The result contains too many items
|
||||||
|
RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
|
||||||
|
ACCESS_TOKEN_INVALID The bot access token is invalid
|
|
@ -1,12 +1,12 @@
|
|||||||
{notice}
|
{notice}
|
||||||
|
|
||||||
from ..error import Error
|
from ..rpc_error import RPCError
|
||||||
|
|
||||||
|
|
||||||
class {super_class}(Error):
|
class {super_class}(RPCError):
|
||||||
{docstring}
|
{docstring}
|
||||||
CODE = {code}
|
CODE = {code}
|
||||||
"""``int``: Error Code"""
|
"""``int``: RPC Error Code"""
|
||||||
NAME = __doc__
|
NAME = __doc__
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
class {sub_class}({super_class}):
|
class {sub_class}({super_class}):
|
||||||
{docstring}
|
{docstring}
|
||||||
ID = {id}
|
ID = {id}
|
||||||
"""``str``: Error ID"""
|
"""``str``: RPC Error ID"""
|
||||||
MESSAGE = __doc__
|
MESSAGE = __doc__
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +25,10 @@ sys.path.insert(0, os.path.abspath('../..'))
|
|||||||
# Import after sys.path.insert() to avoid issues
|
# Import after sys.path.insert() to avoid issues
|
||||||
from pyrogram import __version__
|
from pyrogram import __version__
|
||||||
|
|
||||||
|
from pygments.styles.friendly import FriendlyStyle
|
||||||
|
|
||||||
|
FriendlyStyle.background_color = "#f3f2f1"
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
@ -60,7 +64,7 @@ master_doc = 'index'
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = 'Pyrogram'
|
project = 'Pyrogram'
|
||||||
copyright = '2017-2018, Dan Tès'
|
copyright = '2017-2019, Dan Tès'
|
||||||
author = 'Dan Tès'
|
author = 'Dan Tès'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
@ -85,7 +89,7 @@ language = None
|
|||||||
exclude_patterns = []
|
exclude_patterns = []
|
||||||
|
|
||||||
# The name of the Pygments (syntax highlighting) style to use.
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
pygments_style = 'tango'
|
pygments_style = 'friendly'
|
||||||
|
|
||||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
todo_include_todos = False
|
todo_include_todos = False
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
400 - Bad Request
|
400 - Bad Request
|
||||||
=================
|
=================
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.BadRequest
|
.. module:: pyrogram.errors.BadRequest
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.bad_request_400
|
.. automodule:: pyrogram.errors.exceptions.bad_request_400
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
420 - Flood
|
420 - Flood
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.Flood
|
.. module:: pyrogram.errors.Flood
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.flood_420
|
.. automodule:: pyrogram.errors.exceptions.flood_420
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
403 - Forbidden
|
403 - Forbidden
|
||||||
===============
|
===============
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.Forbidden
|
.. module:: pyrogram.errors.Forbidden
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.forbidden_403
|
.. automodule:: pyrogram.errors.exceptions.forbidden_403
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
500 - Internal Server Error
|
500 - Internal Server Error
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.InternalServerError
|
.. module:: pyrogram.errors.InternalServerError
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.internal_server_error_500
|
.. automodule:: pyrogram.errors.exceptions.internal_server_error_500
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
406 - Not Acceptable
|
406 - Not Acceptable
|
||||||
====================
|
====================
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.NotAcceptable
|
.. module:: pyrogram.errors.NotAcceptable
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.not_acceptable_406
|
.. automodule:: pyrogram.errors.exceptions.not_acceptable_406
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
303 - See Other
|
303 - See Other
|
||||||
===============
|
===============
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.SeeOther
|
.. module:: pyrogram.errors.SeeOther
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.see_other_303
|
.. automodule:: pyrogram.errors.exceptions.see_other_303
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
401 - Unauthorized
|
401 - Unauthorized
|
||||||
==================
|
==================
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.Unauthorized
|
.. module:: pyrogram.errors.Unauthorized
|
||||||
|
|
||||||
.. automodule:: pyrogram.api.errors.exceptions.unauthorized_401
|
.. automodule:: pyrogram.errors.exceptions.unauthorized_401
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
520 - Unknown Error
|
520 - Unknown Error
|
||||||
===================
|
===================
|
||||||
|
|
||||||
.. module:: pyrogram.api.errors.UnknownError
|
.. module:: pyrogram.errors.UnknownError
|
||||||
|
|
||||||
.. autoexception:: pyrogram.api.errors.error.UnknownError
|
.. autoexception:: pyrogram.errors.rpc_error.UnknownError
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
@ -26,7 +26,7 @@ Welcome to Pyrogram
|
|||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<a href="compiler/api/source/main_api.tl">
|
<a href="compiler/api/source/main_api.tl">
|
||||||
<img src="https://img.shields.io/badge/schema-layer%2091-eda738.svg?longCache=true&colorA=262b30"
|
<img src="https://img.shields.io/badge/schema-layer%2097-eda738.svg?longCache=true&colorA=262b30"
|
||||||
alt="Schema Layer">
|
alt="Schema Layer">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/pyrogram/tgcrypto">
|
<a href="https://github.com/pyrogram/tgcrypto">
|
||||||
@ -67,7 +67,7 @@ Features
|
|||||||
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
||||||
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
|
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
|
||||||
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
|
||||||
- **Updated**, to the latest Telegram API version, currently Layer 91 on top of `MTProto 2.0`_.
|
- **Updated**, to the latest Telegram API version, currently Layer 97 on top of `MTProto 2.0`_.
|
||||||
- **Pluggable**: The Smart Plugin system allows to write components with minimal boilerplate code.
|
- **Pluggable**: The Smart Plugin system allows to write components with minimal boilerplate code.
|
||||||
- **Comprehensive**: Execute any advanced action an official client is able to do, and even more.
|
- **Comprehensive**: Execute any advanced action an official client is able to do, and even more.
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ To get started, press the Next button.
|
|||||||
functions/index
|
functions/index
|
||||||
types/index
|
types/index
|
||||||
|
|
||||||
.. _`Telegram`: https://telegram.org/
|
.. _`Telegram`: https://telegram.org
|
||||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto/
|
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
||||||
.. _`MTProto API`: https://core.telegram.org/api#telegram-api
|
.. _`MTProto API`: https://core.telegram.org/api#telegram-api
|
||||||
.. _`MTProto 2.0`: https://core.telegram.org/mtproto
|
.. _`MTProto 2.0`: https://core.telegram.org/mtproto
|
@ -31,6 +31,7 @@ Decorators
|
|||||||
|
|
||||||
on_message
|
on_message
|
||||||
on_callback_query
|
on_callback_query
|
||||||
|
on_inline_query
|
||||||
on_deleted_messages
|
on_deleted_messages
|
||||||
on_user_status
|
on_user_status
|
||||||
on_disconnect
|
on_disconnect
|
||||||
@ -56,6 +57,7 @@ Messages
|
|||||||
send_location
|
send_location
|
||||||
send_venue
|
send_venue
|
||||||
send_contact
|
send_contact
|
||||||
|
send_cached_media
|
||||||
send_chat_action
|
send_chat_action
|
||||||
edit_message_text
|
edit_message_text
|
||||||
edit_message_caption
|
edit_message_caption
|
||||||
@ -67,6 +69,7 @@ Messages
|
|||||||
iter_history
|
iter_history
|
||||||
send_poll
|
send_poll
|
||||||
vote_poll
|
vote_poll
|
||||||
|
close_poll
|
||||||
retract_vote
|
retract_vote
|
||||||
download_media
|
download_media
|
||||||
|
|
||||||
@ -97,6 +100,8 @@ Chats
|
|||||||
iter_chat_members
|
iter_chat_members
|
||||||
get_dialogs
|
get_dialogs
|
||||||
iter_dialogs
|
iter_dialogs
|
||||||
|
restrict_chat
|
||||||
|
update_chat_username
|
||||||
|
|
||||||
Users
|
Users
|
||||||
-----
|
-----
|
||||||
@ -109,6 +114,7 @@ Users
|
|||||||
get_user_profile_photos
|
get_user_profile_photos
|
||||||
set_user_profile_photo
|
set_user_profile_photo
|
||||||
delete_user_profile_photos
|
delete_user_profile_photos
|
||||||
|
update_username
|
||||||
|
|
||||||
Contacts
|
Contacts
|
||||||
--------
|
--------
|
||||||
@ -139,10 +145,12 @@ Bots
|
|||||||
get_inline_bot_results
|
get_inline_bot_results
|
||||||
send_inline_bot_result
|
send_inline_bot_result
|
||||||
answer_callback_query
|
answer_callback_query
|
||||||
|
answer_inline_query
|
||||||
request_callback_answer
|
request_callback_answer
|
||||||
send_game
|
send_game
|
||||||
set_game_score
|
set_game_score
|
||||||
get_game_high_scores
|
get_game_high_scores
|
||||||
|
answer_inline_query
|
||||||
|
|
||||||
|
|
||||||
.. autoclass:: pyrogram.Client
|
.. autoclass:: pyrogram.Client
|
||||||
|
@ -9,6 +9,7 @@ Handlers
|
|||||||
MessageHandler
|
MessageHandler
|
||||||
DeletedMessagesHandler
|
DeletedMessagesHandler
|
||||||
CallbackQueryHandler
|
CallbackQueryHandler
|
||||||
|
InlineQueryHandler
|
||||||
UserStatusHandler
|
UserStatusHandler
|
||||||
DisconnectHandler
|
DisconnectHandler
|
||||||
RawUpdateHandler
|
RawUpdateHandler
|
||||||
@ -22,6 +23,9 @@ Handlers
|
|||||||
.. autoclass:: CallbackQueryHandler
|
.. autoclass:: CallbackQueryHandler
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: InlineQueryHandler
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: UserStatusHandler
|
.. autoclass:: UserStatusHandler
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
Error
|
RPCError
|
||||||
=====
|
========
|
||||||
|
|
||||||
.. autoexception:: pyrogram.Error
|
.. autoexception:: pyrogram.RPCError
|
||||||
:members:
|
:members:
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
../errors/SeeOther
|
../errors/SeeOther
|
@ -16,6 +16,7 @@ Users & Chats
|
|||||||
ChatPhoto
|
ChatPhoto
|
||||||
ChatMember
|
ChatMember
|
||||||
ChatMembers
|
ChatMembers
|
||||||
|
ChatPermissions
|
||||||
Dialog
|
Dialog
|
||||||
Dialogs
|
Dialogs
|
||||||
|
|
||||||
@ -65,6 +66,7 @@ Input Media
|
|||||||
.. autosummary::
|
.. autosummary::
|
||||||
:nosignatures:
|
:nosignatures:
|
||||||
|
|
||||||
|
InputMedia
|
||||||
InputMediaPhoto
|
InputMediaPhoto
|
||||||
InputMediaVideo
|
InputMediaVideo
|
||||||
InputMediaAudio
|
InputMediaAudio
|
||||||
@ -72,6 +74,25 @@ Input Media
|
|||||||
InputMediaDocument
|
InputMediaDocument
|
||||||
InputPhoneContact
|
InputPhoneContact
|
||||||
|
|
||||||
|
Inline Mode
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
InlineQuery
|
||||||
|
InlineQueryResult
|
||||||
|
InlineQueryResultArticle
|
||||||
|
|
||||||
|
InputMessageContent
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
|
||||||
|
InputMessageContent
|
||||||
|
InputTextMessageContent
|
||||||
|
|
||||||
.. User & Chats
|
.. User & Chats
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@ -96,6 +117,9 @@ Input Media
|
|||||||
.. autoclass:: ChatMembers
|
.. autoclass:: ChatMembers
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: ChatPermissions
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: Dialog
|
.. autoclass:: Dialog
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@ -195,6 +219,9 @@ Input Media
|
|||||||
.. Input Media
|
.. Input Media
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
.. autoclass:: InputMedia
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: InputMediaPhoto
|
.. autoclass:: InputMediaPhoto
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
@ -212,3 +239,25 @@ Input Media
|
|||||||
|
|
||||||
.. autoclass:: InputPhoneContact
|
.. autoclass:: InputPhoneContact
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
.. Inline Mode
|
||||||
|
-----------
|
||||||
|
|
||||||
|
.. autoclass:: InlineQuery
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: InlineQueryResult
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: InlineQueryResultArticle
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. InputMessageContent
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. autoclass:: InputMessageContent
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: InputTextMessageContent
|
||||||
|
:members:
|
||||||
|
@ -15,6 +15,6 @@ after the well established `Telegram Bot API`_ methods, thus offering a familiar
|
|||||||
Filters
|
Filters
|
||||||
ChatAction
|
ChatAction
|
||||||
ParseMode
|
ParseMode
|
||||||
Error
|
RPCError
|
||||||
|
|
||||||
.. _Telegram Bot API: https://core.telegram.org/bots/api#available-methods
|
.. _Telegram Bot API: https://core.telegram.org/bots/api#available-methods
|
||||||
|
@ -1,40 +1,102 @@
|
|||||||
Advanced Usage
|
Advanced Usage
|
||||||
==============
|
==============
|
||||||
|
|
||||||
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main Telegram
|
Pyrogram's API, which consists of well documented convenience methods_ and facade types_, exists to provide a much
|
||||||
API with its raw functions and types.
|
easier interface to the undocumented and often confusing Telegram API.
|
||||||
|
|
||||||
|
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
|
||||||
|
Telegram API with its functions and types.
|
||||||
|
|
||||||
Telegram Raw API
|
Telegram Raw API
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
|
If you can't find a high-level method for your needs or if you want complete, low-level access to the whole
|
||||||
Telegram API, you have to use the raw :mod:`functions <pyrogram.api.functions>` and :mod:`types <pyrogram.api.types>`
|
Telegram API, you have to use the raw :mod:`functions <pyrogram.api.functions>` and :mod:`types <pyrogram.api.types>`.
|
||||||
exposed by the ``pyrogram.api`` package and call any Telegram API method you wish using the
|
|
||||||
:meth:`send() <pyrogram.Client.send>` method provided by the Client class.
|
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
|
||||||
|
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
|
||||||
|
some pitfalls to take into consideration when working with the raw API.
|
||||||
|
|
||||||
.. hint::
|
.. hint::
|
||||||
|
|
||||||
Every available high-level method mentioned in the previous page is built on top of these raw functions.
|
Every available high-level methods in Pyrogram is built on top of these raw functions.
|
||||||
|
|
||||||
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
|
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
|
||||||
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API.
|
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API (yet much more
|
||||||
|
powerful).
|
||||||
|
|
||||||
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
|
||||||
|
|
||||||
Caveats
|
Invoking Functions
|
||||||
-------
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
As hinted before, raw functions and types can be confusing, mainly because people don't realize they must accept
|
Unlike the methods_ found in Pyrogram's API, which can be called in the usual simple way, functions to be invoked from
|
||||||
*exactly* the right values, but also because most of them don't have enough Python experience to fully grasp how things
|
the raw Telegram API have a different way of usage and are more complex.
|
||||||
work.
|
|
||||||
|
|
||||||
This section will therefore explain some pitfalls to take into consideration when working with the raw API.
|
First of all, both `raw functions`_ and `raw types`_ live in their respective packages (and sub-packages):
|
||||||
|
``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python classes, meaning you need to create an
|
||||||
|
instance of each every time you need them and fill them in with the correct values using named arguments.
|
||||||
|
|
||||||
|
Next, to actually invoke the raw function you have to use the :meth:`send() <pyrogram.Client.send>` method provided by
|
||||||
|
the Client class and pass the function object you created.
|
||||||
|
|
||||||
|
Here's some examples:
|
||||||
|
|
||||||
|
- Update first name, last name and bio:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
from pyrogram.api import functions
|
||||||
|
|
||||||
|
with Client("my_account") as app:
|
||||||
|
app.send(
|
||||||
|
functions.account.UpdateProfile(
|
||||||
|
first_name="Dan", last_name="Tès",
|
||||||
|
about="Bio written from Pyrogram"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
- Disable links to your account when someone forwards your messages:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
|
||||||
|
with Client("my_account") as app:
|
||||||
|
app.send(
|
||||||
|
functions.account.SetPrivacy(
|
||||||
|
key=types.PrivacyKeyForwards(),
|
||||||
|
rules=[types.InputPrivacyValueDisallowAll()]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
- Invite users to your channel/supergroup:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
|
||||||
|
with Client("my_account") as app:
|
||||||
|
app.send(
|
||||||
|
functions.channels.InviteToChannel(
|
||||||
|
channel=app.resolve_peer(123456789), # ID or Username
|
||||||
|
users=[ # The users you want to invite
|
||||||
|
app.resolve_peer(23456789), # By ID
|
||||||
|
app.resolve_peer("username"), # By username
|
||||||
|
app.resolve_peer("+393281234567"), # By phone number
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
Chat IDs
|
Chat IDs
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
The way Telegram works makes it impossible to directly send a message to a user or a chat by using their IDs only.
|
The way Telegram works makes it impossible to directly send a message to a user or a chat by using their IDs only.
|
||||||
Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed.
|
Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed. Pyrogram allows
|
||||||
|
sending messages with IDs only thanks to cached access hashes.
|
||||||
|
|
||||||
There are three different InputPeer types, one for each kind of Telegram entity.
|
There are three different InputPeer types, one for each kind of Telegram entity.
|
||||||
Whenever an InputPeer is needed you must pass one of these:
|
Whenever an InputPeer is needed you must pass one of these:
|
||||||
@ -56,66 +118,19 @@ kind of ID.
|
|||||||
|
|
||||||
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:
|
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:
|
||||||
|
|
||||||
- ``+ID`` - User: *123456789*
|
- ``+ID`` User: *123456789*
|
||||||
- ``-ID`` - Chat: *-123456789*
|
- ``-ID`` Chat: *-123456789*
|
||||||
- ``-100ID`` - Channel (and Supergroup): *-100123456789*
|
- ``-100ID`` Channel (and Supergroup): *-100123456789*
|
||||||
|
|
||||||
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
|
So, every time you take a raw ID, make sure to translate it into the correct ID when you want to use it with an
|
||||||
high-level method.
|
high-level method.
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
- Update first name, last name and bio:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from pyrogram import Client
|
|
||||||
from pyrogram.api import functions
|
|
||||||
|
|
||||||
with Client("my_account") as app:
|
|
||||||
app.send(
|
|
||||||
functions.account.UpdateProfile(
|
|
||||||
first_name="Dan", last_name="Tès",
|
|
||||||
about="Bio written from Pyrogram"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
- Share your Last Seen time only with your contacts:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from pyrogram import Client
|
|
||||||
from pyrogram.api import functions, types
|
|
||||||
|
|
||||||
with Client("my_account") as app:
|
|
||||||
app.send(
|
|
||||||
functions.account.SetPrivacy(
|
|
||||||
key=types.InputPrivacyKeyStatusTimestamp(),
|
|
||||||
rules=[types.InputPrivacyValueAllowContacts()]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
- Invite users to your channel/supergroup:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from pyrogram import Client
|
|
||||||
from pyrogram.api import functions, types
|
|
||||||
|
|
||||||
with Client("my_account") as app:
|
|
||||||
app.send(
|
|
||||||
functions.channels.InviteToChannel(
|
|
||||||
channel=app.resolve_peer(123456789), # ID or Username
|
|
||||||
users=[ # The users you want to invite
|
|
||||||
app.resolve_peer(23456789), # By ID
|
|
||||||
app.resolve_peer("username"), # By username
|
|
||||||
app.resolve_peer("393281234567"), # By phone number
|
|
||||||
]
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.. _methods: ../pyrogram/Client.html#messages
|
||||||
|
.. _types: ../pyrogram/Types.html
|
||||||
.. _plenty of them: ../pyrogram/Client.html#messages
|
.. _plenty of them: ../pyrogram/Client.html#messages
|
||||||
.. _Raw Functions: Usage.html#using-raw-functions
|
.. _raw functions: ../pyrogram/functions
|
||||||
|
.. _raw types: ../pyrogram/types
|
||||||
.. _Community: https://t.me/PyrogramChat
|
.. _Community: https://t.me/PyrogramChat
|
@ -1,13 +1,13 @@
|
|||||||
Configuration File
|
Configuration File
|
||||||
==================
|
==================
|
||||||
|
|
||||||
As already mentioned in previous sections, Pyrogram can also be configured by the use of an INI file.
|
As already mentioned in previous sections, Pyrogram can be configured by the use of an INI file.
|
||||||
This page explains how this file is structured in Pyrogram, how to use it and why.
|
This page explains how this file is structured in Pyrogram, how to use it and why.
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
||||||
The idea behind using a configuration file is to help keeping your code free of settings (private) information such as
|
The idea behind using a configuration file is to help keeping your code free of private settings information such as
|
||||||
the API Key and Proxy without having you to even deal with how to load such settings. The configuration file, usually
|
the API Key and Proxy without having you to even deal with how to load such settings. The configuration file, usually
|
||||||
referred as ``config.ini`` file, is automatically loaded from the root of your working directory; all you need to do is
|
referred as ``config.ini`` file, is automatically loaded from the root of your working directory; all you need to do is
|
||||||
fill in the necessary parts.
|
fill in the necessary parts.
|
||||||
@ -46,7 +46,7 @@ These are all the sections Pyrogram uses in its configuration file:
|
|||||||
Pyrogram
|
Pyrogram
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
The ``[pyrogram]`` section contains your Telegram API credentials *api_id* and *api_hash*.
|
The ``[pyrogram]`` section contains your Telegram API credentials: *api_id* and *api_hash*.
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
Customize Sessions
|
Customize Sessions
|
||||||
==================
|
==================
|
||||||
|
|
||||||
As you may probably know, Telegram allows Users (and Bots) having more than one session (authorizations) registered
|
As you may probably know, Telegram allows users (and bots) having more than one session (authorizations) registered
|
||||||
in the system at the same time.
|
in the system at the same time.
|
||||||
|
|
||||||
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
|
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
|
||||||
app (or by invoking `GetAuthorizations <../functions/account/GetAuthorizations.html>`_ with Pyrogram) and store some useful
|
app (or by invoking `GetAuthorizations <../functions/account/GetAuthorizations.html>`_ with Pyrogram). They store some
|
||||||
information about the client who generated them.
|
useful information such as the client who's using them and from which country and IP address.
|
||||||
|
|
||||||
|
|
||||||
.. figure:: https://i.imgur.com/lzGPCdZ.png
|
.. figure:: https://i.imgur.com/lzGPCdZ.png
|
||||||
:width: 70%
|
:width: 70%
|
||||||
:align: center
|
:align: center
|
||||||
|
|
||||||
A Pyrogram session running on Linux, Python 3.6.
|
**A Pyrogram session running on Linux, Python 3.6.**
|
||||||
|
|
||||||
That's how a session looks like on the Android app, showing the three main pieces of information.
|
That's how a session looks like on the Android app, showing the three main pieces of information.
|
||||||
|
|
||||||
|
@ -4,18 +4,18 @@ Error Handling
|
|||||||
Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks.
|
Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks.
|
||||||
|
|
||||||
There are many errors that Telegram could return, but they all fall in one of these categories
|
There are many errors that Telegram could return, but they all fall in one of these categories
|
||||||
(which are in turn children of the :obj:`pyrogram.Error` superclass)
|
(which are in turn children of the :obj:`RPCError <pyrogram.RPCError>` superclass):
|
||||||
|
|
||||||
- :obj:`303 - See Other <pyrogram.api.errors.SeeOther>`
|
- :obj:`303 - See Other <pyrogram.errors.SeeOther>`
|
||||||
- :obj:`400 - Bad Request <pyrogram.api.errors.BadRequest>`
|
- :obj:`400 - Bad Request <pyrogram.errors.BadRequest>`
|
||||||
- :obj:`401 - Unauthorized <pyrogram.api.errors.Unauthorized>`
|
- :obj:`401 - Unauthorized <pyrogram.errors.Unauthorized>`
|
||||||
- :obj:`403 - Forbidden <pyrogram.api.errors.Forbidden>`
|
- :obj:`403 - Forbidden <pyrogram.errors.Forbidden>`
|
||||||
- :obj:`406 - Not Acceptable <pyrogram.api.errors.NotAcceptable>`
|
- :obj:`406 - Not Acceptable <pyrogram.errors.NotAcceptable>`
|
||||||
- :obj:`420 - Flood <pyrogram.api.errors.Flood>`
|
- :obj:`420 - Flood <pyrogram.errors.Flood>`
|
||||||
- :obj:`500 - Internal Server Error <pyrogram.api.errors.InternalServerError>`
|
- :obj:`500 - Internal Server Error <pyrogram.errors.InternalServerError>`
|
||||||
|
|
||||||
As stated above, there are really many (too many) errors, and in case Pyrogram does not know anything yet about a
|
As stated above, there are really many (too many) errors, and in case Pyrogram does not know anything yet about a
|
||||||
specific one, it raises a special :obj:`520 Unknown Error <pyrogram.api.errors.UnknownError>` exception and logs it
|
specific one, it raises a special :obj:`520 Unknown Error <pyrogram.errors.UnknownError>` exception and logs it
|
||||||
in the ``unknown_errors.txt`` file. Users are invited to report these unknown errors; in later versions of Pyrogram
|
in the ``unknown_errors.txt`` file. Users are invited to report these unknown errors; in later versions of Pyrogram
|
||||||
some kind of automatic error reporting module might be implemented.
|
some kind of automatic error reporting module might be implemented.
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ Examples
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from pyrogram.api.errors import (
|
from pyrogram.errors import (
|
||||||
BadRequest, Flood, InternalServerError,
|
BadRequest, Flood, InternalServerError,
|
||||||
SeeOther, Unauthorized, UnknownError
|
SeeOther, Unauthorized, UnknownError
|
||||||
)
|
)
|
||||||
@ -45,13 +45,13 @@ Examples
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
Exception objects may also contain some informative values.
|
Exception objects may also contain some informative values.
|
||||||
E.g.: :obj:`FloodWait <pyrogram.api.errors.exceptions.flood_420.FloodWait>` holds the amount of seconds you have to wait
|
E.g.: :obj:`FloodWait <pyrogram.errors.exceptions.flood_420.FloodWait>` holds the amount of seconds you have to wait
|
||||||
before you can try again. The value is always stored in the ``x`` field of the returned exception object:
|
before you can try again. The value is always stored in the ``x`` field of the returned exception object:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
import time
|
import time
|
||||||
from pyrogram.api.errors import FloodWait
|
from pyrogram.errors import FloodWait
|
||||||
|
|
||||||
try:
|
try:
|
||||||
...
|
...
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
More on Updates
|
More on Updates
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Here we'll show some advanced usages when working with updates.
|
Here we'll show some advanced usages when working with `update handlers`_ and `filters`_.
|
||||||
|
|
||||||
.. note::
|
|
||||||
This page makes use of Handlers and Filters to show you how to handle updates.
|
|
||||||
Learn more at `Update Handling <UpdateHandling.html>`_ and `Using Filters <UsingFilters.html>`_.
|
|
||||||
|
|
||||||
Handler Groups
|
Handler Groups
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
If you register handlers with overlapping filters, only the first one is executed and any other handler will be ignored.
|
If you register handlers with overlapping (conflicting) filters, only the first one is executed and any other handler
|
||||||
|
will be ignored. This is intended by design.
|
||||||
|
|
||||||
In order to process the same update more than once, you can register your handler in a different group.
|
In order to handle the very same update more than once, you have to register your handler in a different dispatching
|
||||||
Groups are identified by a number (number 0 being the default) and are sorted, that is, a lower group number has a
|
group. Dispatching groups hold one or more handlers and are processed sequentially, they are identified by a number
|
||||||
higher priority.
|
(number 0 being the default) and sorted, that is, a lower group number has a higher priority:
|
||||||
|
|
||||||
For example, in:
|
For example, take these two handlers:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 1, 6
|
||||||
|
|
||||||
@app.on_message(Filters.text | Filters.sticker)
|
@app.on_message(Filters.text | Filters.sticker)
|
||||||
def text_or_sticker(client, message):
|
def text_or_sticker(client, message):
|
||||||
@ -29,8 +27,8 @@ For example, in:
|
|||||||
def just_text(client, message):
|
def just_text(client, message):
|
||||||
print("Just Text")
|
print("Just Text")
|
||||||
|
|
||||||
``just_text`` is never executed because ``text_or_sticker`` already handles texts. To enable it, simply register the
|
Here, ``just_text`` is never executed because ``text_or_sticker``, which has been registered first, already handles
|
||||||
function using a different group:
|
texts (``Filters.text`` is shared and conflicting). To enable it, register the function using a different group:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -69,7 +67,7 @@ continue to propagate the same update to the next groups until all the handlers
|
|||||||
|
|
||||||
@app.on_message(Filters.private, group=1)
|
@app.on_message(Filters.private, group=1)
|
||||||
def _(client, message):
|
def _(client, message):
|
||||||
print(1 / 0) # Unhandled exception: ZeroDivisionError
|
raise Exception("Unhandled exception!") # Simulate an unhandled exception
|
||||||
|
|
||||||
|
|
||||||
@app.on_message(Filters.private, group=2)
|
@app.on_message(Filters.private, group=2)
|
||||||
@ -82,7 +80,7 @@ The output for each incoming update will therefore be:
|
|||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
0
|
0
|
||||||
ZeroDivisionError: division by zero
|
Exception: Unhandled exception!
|
||||||
2
|
2
|
||||||
|
|
||||||
Stop Propagation
|
Stop Propagation
|
||||||
@ -153,9 +151,9 @@ Continue Propagation
|
|||||||
|
|
||||||
As opposed to `stopping the update propagation <#stop-propagation>`_ and also as an alternative to the
|
As opposed to `stopping the update propagation <#stop-propagation>`_ and also as an alternative to the
|
||||||
`handler groups <#handler-groups>`_, you can signal the internal dispatcher to continue the update propagation within
|
`handler groups <#handler-groups>`_, you can signal the internal dispatcher to continue the update propagation within
|
||||||
the group regardless of the next handler's filters. This allows you to register multiple handlers with overlapping
|
**the same group** regardless of the next handler's filters. This allows you to register multiple handlers with
|
||||||
filters in the same group; to let the dispatcher process the next handler you can do *one* of the following in each
|
overlapping filters in the same group; to let the dispatcher process the next handler you can do *one* of the following
|
||||||
handler you want to grant permission to continue:
|
in each handler you want to grant permission to continue:
|
||||||
|
|
||||||
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
|
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
|
||||||
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
|
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
|
||||||
@ -219,3 +217,6 @@ The output of both (equivalent) examples will be:
|
|||||||
0
|
0
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
|
|
||||||
|
.. _`update handlers`: UpdateHandling.html
|
||||||
|
.. _`filters`: UsingFilters.html
|
@ -13,8 +13,8 @@ Introduction
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
Prior to the Smart Plugin system, pluggable handlers were already possible. For example, if you wanted to modularize
|
Prior to the Smart Plugin system, pluggable handlers were already possible. For example, if you wanted to modularize
|
||||||
your applications, you had to put your function definitions in separate files and register them inside your main script,
|
your applications, you had to put your function definitions in separate files and register them inside your main script
|
||||||
like this:
|
after importing your modules, like this:
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ functions. So, what if you could? Smart Plugins solve this issue by taking care
|
|||||||
Using Smart Plugins
|
Using Smart Plugins
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Setting up your Pyrogram project to accommodate Smart Plugins is straightforward:
|
Setting up your Pyrogram project to accommodate Smart Plugins is pretty straightforward:
|
||||||
|
|
||||||
#. Create a new folder to store all the plugins (e.g.: "plugins", "handlers", ...).
|
#. Create a new folder to store all the plugins (e.g.: "plugins", "handlers", ...).
|
||||||
#. Put your python files full of plugins inside. Organize them as you wish.
|
#. Put your python files full of plugins inside. Organize them as you wish.
|
||||||
@ -129,18 +129,17 @@ Setting up your Pyrogram project to accommodate Smart Plugins is straightforward
|
|||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
plugins = dict(
|
plugins = dict(root="plugins")
|
||||||
root="plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
Client("my_account", plugins=plugins).run()
|
Client("my_account", plugins=plugins).run()
|
||||||
|
|
||||||
|
|
||||||
The first important thing to note is the new ``plugins`` folder. You can put *any python file* in *any subfolder* and
|
The first important thing to note is the new ``plugins`` folder. You can put *any python file* in *any subfolder* and
|
||||||
each file can contain *any decorated function* (handlers) with one limitation: within a single module (file) you must
|
each file can contain *any decorated function* (handlers) with one limitation: within a single module (file) you must
|
||||||
use different names for each decorated function.
|
use different names for each decorated function.
|
||||||
|
|
||||||
The second thing is telling Pyrogram where to look for your plugins: you can either use the *config.ini* file or
|
The second thing is telling Pyrogram where to look for your plugins: you can either use the *config.ini* file or
|
||||||
the Client parameter "plugins"; the *root* value must match the name of your plugins folder. Your Pyrogram Client
|
the Client parameter "plugins"; the *root* value must match the name of your plugins root folder. Your Pyrogram Client
|
||||||
instance will **automatically** scan the folder upon starting to search for valid handlers and register them for you.
|
instance will **automatically** scan the folder upon starting to search for valid handlers and register them for you.
|
||||||
|
|
||||||
Then you'll notice you can now use decorators. That's right, you can apply the usual decorators to your callback
|
Then you'll notice you can now use decorators. That's right, you can apply the usual decorators to your callback
|
||||||
@ -161,7 +160,7 @@ found inside each module will be, instead, loaded in the order they are defined,
|
|||||||
|
|
||||||
This default loading behaviour is usually enough, but sometimes you want to have more control on what to include (or
|
This default loading behaviour is usually enough, but sometimes you want to have more control on what to include (or
|
||||||
exclude) and in which exact order to load plugins. The way to do this is to make use of ``include`` and ``exclude``
|
exclude) and in which exact order to load plugins. The way to do this is to make use of ``include`` and ``exclude``
|
||||||
keys, either in the *config.ini* file or in the dictionary passed as Client argument. Here's how they work:
|
directives, either in the *config.ini* file or in the dictionary passed as Client argument. Here's how they work:
|
||||||
|
|
||||||
- If both ``include`` and ``exclude`` are omitted, all plugins are loaded as described above.
|
- If both ``include`` and ``exclude`` are omitted, all plugins are loaded as described above.
|
||||||
- If ``include`` is given, only the specified plugins will be loaded, in the order they are passed.
|
- If ``include`` is given, only the specified plugins will be loaded, in the order they are passed.
|
||||||
@ -214,9 +213,7 @@ also organized in subfolders:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
plugins = dict(
|
plugins = dict(root="plugins")
|
||||||
root="plugins"
|
|
||||||
)
|
|
||||||
|
|
||||||
Client("my_account", plugins=plugins).run()
|
Client("my_account", plugins=plugins).run()
|
||||||
|
|
||||||
@ -293,7 +290,7 @@ Load/Unload Plugins at Runtime
|
|||||||
|
|
||||||
In the `previous section <#specifying-the-plugins-to-include>`_ we've explained how to specify which plugins to load and
|
In the `previous section <#specifying-the-plugins-to-include>`_ we've explained how to specify which plugins to load and
|
||||||
which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously
|
which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously
|
||||||
registered plugins at runtime.
|
registered plugin at runtime.
|
||||||
|
|
||||||
Each function decorated with the usual ``on_message`` decorator (or any other decorator that deals with Telegram updates
|
Each function decorated with the usual ``on_message`` decorator (or any other decorator that deals with Telegram updates
|
||||||
) will be modified in such a way that, when you reference them later on, they will be actually pointing to a tuple of
|
) will be modified in such a way that, when you reference them later on, they will be actually pointing to a tuple of
|
||||||
@ -314,14 +311,14 @@ attribute. Here's an example:
|
|||||||
|
|
||||||
- Printing ``echo`` will show something like ``(<MessageHandler object at 0x10e3abc50>, 0)``.
|
- Printing ``echo`` will show something like ``(<MessageHandler object at 0x10e3abc50>, 0)``.
|
||||||
|
|
||||||
- Printing ``echo[0].callback``, that is, the *callback* attribute of the first eleent of the tuple, which is an
|
- Printing ``echo[0].callback``, that is, the *callback* attribute of the first element of the tuple, which is an
|
||||||
Handler, will reveal the actual callback ``<function echo at 0x10e3b6598>``.
|
Handler, will reveal the actual callback ``<function echo at 0x10e3b6598>``.
|
||||||
|
|
||||||
Unloading
|
Unloading
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it (by importing the
|
In order to unload a plugin, or any other handler, all you need to do is obtain a reference to it by importing the
|
||||||
relevant module) and call :meth:`remove_handler <pyrogram.Client.remove_handler>` Client's method with your function
|
relevant module and call :meth:`remove_handler() <pyrogram.Client.remove_handler>` Client's method with your function
|
||||||
name preceded by the star ``*`` operator as argument. Example:
|
name preceded by the star ``*`` operator as argument. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``main.py``
|
||||||
@ -346,7 +343,7 @@ Loading
|
|||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
||||||
Similarly to the unloading process, in order to load again a previously unloaded plugin you do the same, but this time
|
Similarly to the unloading process, in order to load again a previously unloaded plugin you do the same, but this time
|
||||||
using :meth:`add_handler <pyrogram.Client.add_handler>` instead. Example:
|
using :meth:`add_handler() <pyrogram.Client.add_handler>` instead. Example:
|
||||||
|
|
||||||
- ``main.py``
|
- ``main.py``
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
Update Handling
|
Update Handling
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
Let's now dive right into the core of the framework.
|
||||||
and can be handled by registering one or more callback functions in your app by using `Handlers <../pyrogram/Handlers.html>`_.
|
|
||||||
|
|
||||||
To put it simply, whenever an update is received from Telegram it will be dispatched and your previously defined callback
|
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
||||||
function(s) matching it will be called back with the update itself as argument.
|
and are handled by registering one or more callback functions in your app using `Handlers <../pyrogram/Handlers.html>`_.
|
||||||
|
|
||||||
|
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
|
||||||
|
function will be called.
|
||||||
|
|
||||||
Registering an Handler
|
Registering an Handler
|
||||||
----------------------
|
----------------------
|
||||||
@ -15,13 +17,34 @@ To explain how handlers work let's have a look at the most used one, the
|
|||||||
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
||||||
settings them up once you learn from this section.
|
settings them up once you learn from this section.
|
||||||
|
|
||||||
|
Using add_handler()
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The :meth:`add_handler() <pyrogram.Client.add_handler>` method takes any handler instance that wraps around your defined
|
||||||
|
callback function and registers it in your Client. Here's a full example that prints out the content of a message as
|
||||||
|
soon as it arrives:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client, MessageHandler
|
||||||
|
|
||||||
|
|
||||||
|
def my_function(client, message):
|
||||||
|
print(message)
|
||||||
|
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
my_handler = MessageHandler(my_function)
|
||||||
|
app.add_handler(my_handler)
|
||||||
|
|
||||||
|
app.run()
|
||||||
|
|
||||||
Using Decorators
|
Using Decorators
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
The easiest and nicest way to register a MessageHandler is by decorating your function with the
|
A much nicer way to register a MessageHandler is by decorating your callback function with the
|
||||||
:meth:`on_message() <pyrogram.Client.on_message>` decorator. Here's a full example that prints out the content
|
:meth:`on_message() <pyrogram.Client.on_message>` decorator, which will still make use of add_handler() under the hood.
|
||||||
of a message as soon as it arrives.
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -37,23 +60,13 @@ of a message as soon as it arrives.
|
|||||||
|
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
Using add_handler()
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
If you prefer not to use decorators for any reason, there is an alternative way for registering Handlers.
|
.. note::
|
||||||
This is useful, for example, when you want to keep your callback functions in separate files.
|
|
||||||
|
|
||||||
.. code-block:: python
|
Due to how these decorators work in Pyrogram, they will wrap your defined callback function in a tuple consisting of
|
||||||
|
``(handler, group)``; this will be the value held by your function identifier (e.g.: *my_function* from the example
|
||||||
|
above).
|
||||||
|
|
||||||
from pyrogram import Client, MessageHandler
|
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
|
||||||
|
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
|
||||||
|
tuple.
|
||||||
def my_handler(client, message):
|
|
||||||
print(message)
|
|
||||||
|
|
||||||
|
|
||||||
app = Client("my_account")
|
|
||||||
|
|
||||||
app.add_handler(MessageHandler(my_handler))
|
|
||||||
|
|
||||||
app.run()
|
|
@ -1,17 +1,19 @@
|
|||||||
Using Filters
|
Using Filters
|
||||||
=============
|
=============
|
||||||
|
|
||||||
For a finer grained control over what kind of messages will be allowed or not in your callback functions, you can use
|
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
|
||||||
:class:`Filters <pyrogram.Filters>`.
|
but there's much more than that to come.
|
||||||
|
|
||||||
.. note::
|
Here we'll discuss about :class:`Filters <pyrogram.Filters>`. Filters enable a fine-grain control over what kind of
|
||||||
This page makes use of Handlers to show you how to handle updates.
|
updates are allowed or not to be passed in your callback functions, based on their inner details.
|
||||||
Learn more at `Update Handling <UpdateHandling.html>`_.
|
|
||||||
|
Let's start right away with a simple example:
|
||||||
|
|
||||||
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
|
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
|
||||||
ignore any other message:
|
ignore any other message. Filters are passed as the first argument of the decorator:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 4
|
||||||
|
|
||||||
from pyrogram import Filters
|
from pyrogram import Filters
|
||||||
|
|
||||||
@ -20,9 +22,10 @@ For a finer grained control over what kind of messages will be allowed or not in
|
|||||||
def my_handler(client, message):
|
def my_handler(client, message):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
- or, without decorators:
|
- or, without decorators. Here filters are passed as the second argument of the handler constructor:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 8
|
||||||
|
|
||||||
from pyrogram import Filters, MessageHandler
|
from pyrogram import Filters, MessageHandler
|
||||||
|
|
||||||
@ -37,7 +40,7 @@ Combining Filters
|
|||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
|
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
|
||||||
operators:
|
operators ``~``, ``&`` and ``|``:
|
||||||
|
|
||||||
- Use ``~`` to invert a filter (behaves like the ``not`` operator).
|
- Use ``~`` to invert a filter (behaves like the ``not`` operator).
|
||||||
- Use ``&`` and ``|`` to merge two filters (behave like ``and``, ``or`` operators respectively).
|
- Use ``&`` and ``|`` to merge two filters (behave like ``and``, ``or`` operators respectively).
|
||||||
@ -74,7 +77,7 @@ can also accept arguments:
|
|||||||
def my_handler(client, message):
|
def my_handler(client, message):
|
||||||
print(message)
|
print(message)
|
||||||
|
|
||||||
- Message is a **text** message matching the given **regex** pattern.
|
- Message is a **text** message or a media **caption** matching the given **regex** pattern.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -104,17 +107,17 @@ Custom Filters
|
|||||||
--------------
|
--------------
|
||||||
|
|
||||||
Pyrogram already provides lots of built-in :class:`Filters <pyrogram.Filters>` to work with, but in case you can't find
|
Pyrogram already provides lots of built-in :class:`Filters <pyrogram.Filters>` to work with, but in case you can't find
|
||||||
a specific one for your needs or want to build a custom filter by yourself (to be used in a different handler, for
|
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
|
||||||
example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
for example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
|
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
|
||||||
only.
|
only.
|
||||||
|
|
||||||
An example to demonstrate how custom filters work is to show how to create and use one for the
|
An example to demonstrate how custom filters work is to show how to create and use one for the
|
||||||
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by Bots;
|
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by
|
||||||
create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline keyboard to
|
bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline
|
||||||
yourself. This allows you to test your filter by pressing the inline button:
|
keyboard to yourself. This allows you to test your filter by pressing the inline button:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -133,26 +136,27 @@ Basic Filters
|
|||||||
|
|
||||||
For this basic filter we will be using only the first two parameters of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
For this basic filter we will be using only the first two parameters of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||||
|
|
||||||
The code below creates a simple filter for hardcoded callback data. This filter will only allow callback queries
|
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
|
||||||
containing "pyrogram" as data:
|
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
|
||||||
|
equals to ``b"Pyrogram"``.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
hardcoded_data = Filters.create(
|
static_data = Filters.create(
|
||||||
name="HardcodedData",
|
name="StaticdData",
|
||||||
func=lambda filter, callback_query: callback_query.data == b"pyrogram"
|
func=lambda flt, callback_query: callback_query.data == b"Pyrogram"
|
||||||
)
|
)
|
||||||
|
|
||||||
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
|
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
|
||||||
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter itself:
|
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
def func(filter, callback_query):
|
def func(flt, callback_query):
|
||||||
return callback_query.data == b"pyrogram"
|
return callback_query.data == b"Pyrogram"
|
||||||
|
|
||||||
hardcoded_data = Filters.create(
|
static_data = Filters.create(
|
||||||
name="HardcodedData",
|
name="StaticData",
|
||||||
func=func
|
func=func
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -160,14 +164,14 @@ The filter usage remains the same:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@app.on_callback_query(hardcoded_data)
|
@app.on_callback_query(static_data)
|
||||||
def pyrogram_data(client, callback_query):
|
def pyrogram_data(client, callback_query):
|
||||||
client.answer_callback_query(callback_query.id, "it works!")
|
client.answer_callback_query(callback_query.id, "it works!")
|
||||||
|
|
||||||
Filters with Arguments
|
Filters with Arguments
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
A much cooler filter would be one that accepts "pyrogram" or any other data as argument at usage time.
|
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
|
||||||
A dynamic filter like this will make use of the third parameter of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
A dynamic filter like this will make use of the third parameter of :meth:`Filters.create() <pyrogram.Filters.create>`.
|
||||||
|
|
||||||
This is how a dynamic custom filter looks like:
|
This is how a dynamic custom filter looks like:
|
||||||
@ -177,7 +181,7 @@ This is how a dynamic custom filter looks like:
|
|||||||
def dynamic_data(data):
|
def dynamic_data(data):
|
||||||
return Filters.create(
|
return Filters.create(
|
||||||
name="DynamicData",
|
name="DynamicData",
|
||||||
func=lambda filter, callback_query: filter.data == callback_query.data,
|
func=lambda flt, callback_query: flt.data == callback_query.data,
|
||||||
data=data # "data" kwarg is accessed with "filter.data"
|
data=data # "data" kwarg is accessed with "filter.data"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -185,6 +189,6 @@ And its usage:
|
|||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@app.on_callback_query(dynamic_data(b"pyrogram"))
|
@app.on_callback_query(dynamic_data(b"Pyrogram"))
|
||||||
def pyrogram_data(client, callback_query):
|
def pyrogram_data(client, callback_query):
|
||||||
client.answer_callback_query(callback_query.id, "it works!")
|
client.answer_callback_query(callback_query.id, "it works!")
|
@ -1,11 +1,11 @@
|
|||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
Being a Python library, Pyrogram requires Python to be installed in your system.
|
Being a Python library, **Pyrogram** requires Python to be installed in your system.
|
||||||
We recommend using the latest version of Python 3 and pip.
|
We recommend using the latest version of Python 3 and pip.
|
||||||
|
|
||||||
Get Python 3 from https://www.python.org/downloads/ (or with your package manager) and pip
|
- Get **Python 3** from https://www.python.org/downloads/ (or with your package manager)
|
||||||
by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
- Get **pip** by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
@ -29,8 +29,12 @@ Install Pyrogram
|
|||||||
Bleeding Edge
|
Bleeding Edge
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
If you want the latest development version of Pyrogram, you can install it straight from the develop_
|
Things are constantly evolving in Pyrogram, although new releases are published only when enough changes are added,
|
||||||
branch using this command (note "develop.zip" in the link):
|
but this doesn't mean you can't try new features right now!
|
||||||
|
|
||||||
|
In case you would like to try out the latest Pyrogram features and additions, the `GitHub repo`_ is always kept updated
|
||||||
|
with new changes; you can install the development version straight from the ``develop`` branch using this command
|
||||||
|
(note "develop.zip" in the link):
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@ -39,10 +43,10 @@ branch using this command (note "develop.zip" in the link):
|
|||||||
Asynchronous
|
Asynchronous
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging client library after all), and here's
|
Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging framework after all), and here's
|
||||||
where asyncio shines the most by providing extra performance while running on a single OS-level thread only.
|
where asyncio shines the most by providing extra performance while running on a single OS-level thread only.
|
||||||
|
|
||||||
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5+ required).
|
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5.3+ required).
|
||||||
Use this command to install (note "asyncio.zip" in the link):
|
Use this command to install (note "asyncio.zip" in the link):
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
@ -82,7 +86,7 @@ If no error shows up you are good to go.
|
|||||||
|
|
||||||
>>> import pyrogram
|
>>> import pyrogram
|
||||||
>>> pyrogram.__version__
|
>>> pyrogram.__version__
|
||||||
'0.11.0'
|
'0.12.0'
|
||||||
|
|
||||||
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
|
||||||
.. _develop: http://github.com/pyrogram/pyrogram
|
.. _`Github repo`: http://github.com/pyrogram/pyrogram
|
||||||
|
@ -15,23 +15,22 @@ If you already have one you can skip this step, otherwise:
|
|||||||
#. Fill out the form to register a new Telegram application.
|
#. Fill out the form to register a new Telegram application.
|
||||||
#. Done. The API key consists of two parts: **App api_id** and **App api_hash**.
|
#. Done. The API key consists of two parts: **App api_id** and **App api_hash**.
|
||||||
|
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
This API key is personal and should be kept secret.
|
This API key is personal and must be kept secret.
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
The API key obtained in the `previous step <#api-keys>`_ defines a token for your application allowing you to access
|
The API key obtained in the `previous step <#api-keys>`_ defines a token for your application allowing you to access
|
||||||
the Telegram database using the MTProto API — **it is therefore required for all authorizations of both Users and Bots**.
|
the Telegram database using the MTProto API — **it is therefore required for all authorizations of both users and bots**.
|
||||||
|
|
||||||
Having it handy, it's time to configure your Pyrogram project. There are two ways to do so, and you can choose what
|
Having it handy, it's time to configure your Pyrogram project. There are two ways to do so, and you can choose what
|
||||||
fits better for you:
|
fits better for you:
|
||||||
|
|
||||||
- Create a new ``config.ini`` file at the root of your working directory, copy-paste the following and replace the
|
- Create a new ``config.ini`` file at the root of your working directory, copy-paste the following and replace the
|
||||||
**api_id** and **api_hash** values with your own. This is the preferred method because allows you
|
**api_id** and **api_hash** values with your own. This is the preferred method because allows you to keep your
|
||||||
to keep your credentials out of your code without having to deal with how to load them:
|
credentials out of your code without having to deal with how to load them:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
@ -39,8 +38,8 @@ fits better for you:
|
|||||||
api_id = 12345
|
api_id = 12345
|
||||||
api_hash = 0123456789abcdef0123456789abcdef
|
api_hash = 0123456789abcdef0123456789abcdef
|
||||||
|
|
||||||
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash*
|
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash* parameters of the
|
||||||
parameters of the Client class. This way you can have full control on how to store and load your credentials:
|
Client class. This way you can have full control on how to store and load your credentials:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -54,16 +53,16 @@ fits better for you:
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The examples below assume you have created a ``config.ini`` file, thus they won't show the *api_id*
|
From now on, the code snippets assume you are using the ``config.ini`` file, thus they won't show the *api_id* and
|
||||||
and *api_hash* parameters usage.
|
*api_hash* parameters usage to keep them as clean as possible.
|
||||||
|
|
||||||
User Authorization
|
User Authorization
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
In order to use the API, Telegram requires that Users be authorized via their phone numbers.
|
In order to use the API, Telegram requires that users be authorized via their phone numbers.
|
||||||
Pyrogram automatically manages this access, all you need to do is create an instance of
|
Pyrogram automatically manages this access, all you need to do is create an instance of the
|
||||||
the :class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice
|
:class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
|
||||||
(e.g.: "my_account") and call the :meth:`run() <pyrogram.Client.run>` method:
|
the :meth:`run() <pyrogram.Client.run>` method:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
@ -80,30 +79,40 @@ and the **phone code** you will receive:
|
|||||||
Enter phone number: +39**********
|
Enter phone number: +39**********
|
||||||
Is "+39**********" correct? (y/n): y
|
Is "+39**********" correct? (y/n): y
|
||||||
Enter phone code: 32768
|
Enter phone code: 32768
|
||||||
|
Logged in successfully as Dan
|
||||||
|
|
||||||
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing
|
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram
|
||||||
Pyrogram executing API calls with your identity. This file will be loaded again when you restart your app,
|
executing API calls with your identity. This file will be loaded again when you restart your app, and as long as you
|
||||||
and as long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
||||||
|
|
||||||
.. important::
|
.. important::
|
||||||
|
|
||||||
Your ``*.session`` files are personal and must be kept secret.
|
Your ``*.session`` files are personal and must be kept secret.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
The code above does nothing except asking for credentials and keeping the client online, hit ``CTRL+C`` now to stop
|
||||||
|
your application and keep reading.
|
||||||
|
|
||||||
Bot Authorization
|
Bot Authorization
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Bots are a special kind of users and are authorized via their tokens (instead of phone numbers), which are created by
|
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
|
||||||
BotFather_. Bot tokens replace the Users' phone numbers only — you still need to
|
BotFather_. Bot tokens replace the users' phone numbers only — you still need to
|
||||||
`configure a Telegram API key <#configuration>`_ with Pyrogram, even when using Bots.
|
`configure a Telegram API key <#configuration>`_ with Pyrogram, even when using bots.
|
||||||
|
|
||||||
The authorization process is automatically managed. All you need to do is pass the bot token as ``session_name``.
|
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
|
||||||
The session file will be named after the Bot user_id, which is ``123456.session`` for the example below.
|
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
|
||||||
|
after the session name, which will be ``pyrogrambot.session`` for the example below.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
app = Client(
|
||||||
|
"pyrogrambot",
|
||||||
|
bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||||
|
)
|
||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
.. _installed Pyrogram: Installation.html
|
.. _installed Pyrogram: Installation.html
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Having your `project set up`_ and your account authorized_, it's time to play with the API. Let's start!
|
Having your `project set up`_ and your account authorized_, it's time to start playing with the API. Let's start!
|
||||||
|
|
||||||
High-level API
|
High-level API
|
||||||
--------------
|
--------------
|
||||||
@ -22,6 +22,7 @@ Here's a simple example:
|
|||||||
print(app.get_me())
|
print(app.get_me())
|
||||||
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||||
app.send_location("me", 51.500729, -0.124583)
|
app.send_location("me", 51.500729, -0.124583)
|
||||||
|
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||||
|
|
||||||
app.stop()
|
app.stop()
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ exceptions in your code:
|
|||||||
print(app.get_me())
|
print(app.get_me())
|
||||||
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||||
app.send_location("me", 51.500729, -0.124583)
|
app.send_location("me", 51.500729, -0.124583)
|
||||||
|
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
|
||||||
|
|
||||||
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
||||||
|
|
||||||
|
@ -10,13 +10,14 @@ can be freely used as basic building blocks for your own applications without wo
|
|||||||
|
|
||||||
Example | Description
|
Example | Description
|
||||||
---: | :---
|
---: | :---
|
||||||
[**hello**](hello.py) | Demonstration of basic API usage
|
[**hello_world**](hello_world.py) | Demonstration of basic API usage
|
||||||
[**echo**](echo.py) | Reply to every private text message
|
[**echobot**](echobot.py) | Echo every private text message
|
||||||
[**welcome**](welcome.py) | The Welcome Bot in [@PyrogramChat](https://t.me/pyrogramchat)
|
[**welcome**](welcome.py) | The Welcome Bot in [@PyrogramChat](https://t.me/pyrogramchat)
|
||||||
[**history**](history.py) | Get the full message history of a chat
|
[**history**](history.py) | Get the full message history of a chat
|
||||||
[**chat_members**](chat_members.py) | Get all the members of a chat
|
[**chat_members**](chat_members.py) | Get all the members of a chat
|
||||||
[**dialogs**](dialogs.py) | Get all of your dialog chats
|
[**dialogs**](dialogs.py) | Get all of your dialog chats
|
||||||
[**inline_bots**](inline_bots.py) | Query an inline bot and send a result to a chat
|
[**using_inline_bots**](using_inline_bots.py) | Query an inline bot (as user) and send a result to a chat
|
||||||
[**keyboards**](keyboards.py) | Send normal and inline keyboards using regular bots
|
[**keyboards**](keyboards.py) | Send normal and inline keyboards using regular bots
|
||||||
[**callback_queries**](callback_queries.py) | Handle queries coming from inline button presses
|
[**callback_queries**](callback_queries.py) | Handle queries coming from inline button presses
|
||||||
|
[**inline_queries**](inline_queries.py) | Handle inline queries
|
||||||
[**raw_updates**](raw_updates.py) | Handle raw updates (old, should be avoided)
|
[**raw_updates**](raw_updates.py) | Handle raw updates (old, should be avoided)
|
||||||
|
@ -5,12 +5,12 @@ It uses the @on_callback_query decorator to register a CallbackQueryHandler.
|
|||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||||
|
|
||||||
|
|
||||||
@app.on_callback_query()
|
@app.on_callback_query()
|
||||||
def answer(client, callback_query):
|
def answer(client, callback_query):
|
||||||
callback_query.answer('Button contains: "{}"'.format(callback_query.data), show_alert=True)
|
callback_query.answer("Button contains: '{}'".format(callback_query.data), show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
app.run() # Automatically start() and idle()
|
app.run() # Automatically start() and idle()
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
|
|
||||||
app = Client("my_count")
|
app = Client("my_account")
|
||||||
target = "pyrogramchat" # Target channel/supergroup
|
target = "pyrogramchat" # Target channel/supergroup
|
||||||
|
|
||||||
with app:
|
with app:
|
||||||
|
54
examples/inline_queries.py
Normal file
54
examples/inline_queries.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
"""This example shows how to handle inline queries.
|
||||||
|
Two results are generated when users invoke the bot inline mode, e.g.: @pyrogrambot hi.
|
||||||
|
It uses the @on_inline_query decorator to register an InlineQueryHandler.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
from pyrogram import (
|
||||||
|
Client, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
)
|
||||||
|
|
||||||
|
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_inline_query()
|
||||||
|
def answer(client, inline_query):
|
||||||
|
inline_query.answer(
|
||||||
|
results=[
|
||||||
|
InlineQueryResultArticle(
|
||||||
|
id=uuid4(),
|
||||||
|
title="Installation",
|
||||||
|
input_message_content=InputTextMessageContent(
|
||||||
|
"Here's how to install **Pyrogram**"
|
||||||
|
),
|
||||||
|
url="https://docs.pyrogram.ml/start/Installation",
|
||||||
|
description="How to install Pyrogram",
|
||||||
|
thumb_url="https://i.imgur.com/JyxrStE.png",
|
||||||
|
reply_markup=InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.ml/start/Installation")]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
InlineQueryResultArticle(
|
||||||
|
id=uuid4(),
|
||||||
|
title="Usage",
|
||||||
|
input_message_content=InputTextMessageContent(
|
||||||
|
"Here's how to use **Pyrogram**"
|
||||||
|
),
|
||||||
|
url="https://docs.pyrogram.ml/start/Usage",
|
||||||
|
description="How to use Pyrogram",
|
||||||
|
thumb_url="https://i.imgur.com/JyxrStE.png",
|
||||||
|
reply_markup=InlineKeyboardMarkup(
|
||||||
|
[
|
||||||
|
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.ml/start/Usage")]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
cache_time=1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app.run() # Automatically start() and idle()
|
@ -10,7 +10,7 @@ like send_audio(), send_document(), send_location(), etc...
|
|||||||
from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
|
from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
# Create a client using your bot token
|
# Create a client using your bot token
|
||||||
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
|
||||||
|
|
||||||
with app:
|
with app:
|
||||||
app.send_message(
|
app.send_message(
|
||||||
@ -33,19 +33,17 @@ with app:
|
|||||||
reply_markup=InlineKeyboardMarkup(
|
reply_markup=InlineKeyboardMarkup(
|
||||||
[
|
[
|
||||||
[ # First row
|
[ # First row
|
||||||
|
|
||||||
InlineKeyboardButton( # Generates a callback query when pressed
|
InlineKeyboardButton( # Generates a callback query when pressed
|
||||||
"Button",
|
"Button",
|
||||||
callback_data=b"data"
|
callback_data=b"data" # Note how callback_data must be bytes
|
||||||
), # Note how callback_data must be bytes
|
),
|
||||||
InlineKeyboardButton( # Opens a web URL
|
InlineKeyboardButton( # Opens a web URL
|
||||||
"URL",
|
"URL",
|
||||||
url="https://docs.pyrogram.ml"
|
url="https://docs.pyrogram.ml"
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
[ # Second row
|
[ # Second row
|
||||||
# Opens the inline interface
|
InlineKeyboardButton( # Opens the inline interface
|
||||||
InlineKeyboardButton(
|
|
||||||
"Choose chat",
|
"Choose chat",
|
||||||
switch_inline_query="pyrogram"
|
switch_inline_query="pyrogram"
|
||||||
),
|
),
|
||||||
|
@ -24,25 +24,13 @@ if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
|
|||||||
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
|
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
|
||||||
sys.modules["typing"] = typing
|
sys.modules["typing"] = typing
|
||||||
|
|
||||||
__copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>".replace(
|
__version__ = "0.12.0"
|
||||||
"\xe8",
|
|
||||||
"e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
|
|
||||||
)
|
|
||||||
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
|
||||||
__version__ = "0.11.1.develop"
|
__copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>".replace(
|
||||||
|
"\xe8", "e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
|
||||||
|
)
|
||||||
|
|
||||||
from .api.errors import Error
|
from .errors import RPCError
|
||||||
from .client.types import (
|
from .client import *
|
||||||
Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
|
from .client.handlers import *
|
||||||
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
|
from .client.types import *
|
||||||
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus,
|
|
||||||
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
|
|
||||||
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove,
|
|
||||||
Poll, PollOption, ChatPreview, StopPropagation, ContinuePropagation, Game, CallbackGame, GameHighScore,
|
|
||||||
GameHighScores
|
|
||||||
)
|
|
||||||
from .client import (
|
|
||||||
Client, ChatAction, ParseMode, Emoji,
|
|
||||||
MessageHandler, DeletedMessagesHandler, CallbackQueryHandler,
|
|
||||||
RawUpdateHandler, DisconnectHandler, UserStatusHandler, Filters
|
|
||||||
)
|
|
||||||
|
@ -26,6 +26,10 @@ from .primitives import Int, Long
|
|||||||
class FutureSalt(Object):
|
class FutureSalt(Object):
|
||||||
ID = 0x0949d9dc
|
ID = 0x0949d9dc
|
||||||
|
|
||||||
|
__slots__ = ["valid_since", "valid_until", "salt"]
|
||||||
|
|
||||||
|
QUALNAME = "FutureSalt"
|
||||||
|
|
||||||
def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int):
|
def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int):
|
||||||
self.valid_since = valid_since
|
self.valid_since = valid_since
|
||||||
self.valid_until = valid_until
|
self.valid_until = valid_until
|
||||||
|
@ -27,6 +27,10 @@ from .primitives import Int, Long
|
|||||||
class FutureSalts(Object):
|
class FutureSalts(Object):
|
||||||
ID = 0xae500895
|
ID = 0xae500895
|
||||||
|
|
||||||
|
__slots__ = ["req_msg_id", "now", "salts"]
|
||||||
|
|
||||||
|
QUALNAME = "FutureSalts"
|
||||||
|
|
||||||
def __init__(self, req_msg_id: int, now: int or datetime, salts: list):
|
def __init__(self, req_msg_id: int, now: int or datetime, salts: list):
|
||||||
self.req_msg_id = req_msg_id
|
self.req_msg_id = req_msg_id
|
||||||
self.now = now
|
self.now = now
|
||||||
|
@ -26,6 +26,10 @@ from .primitives import Int, Bytes
|
|||||||
class GzipPacked(Object):
|
class GzipPacked(Object):
|
||||||
ID = 0x3072cfa1
|
ID = 0x3072cfa1
|
||||||
|
|
||||||
|
__slots__ = ["packed_data"]
|
||||||
|
|
||||||
|
QUALNAME = "GzipPacked"
|
||||||
|
|
||||||
def __init__(self, packed_data: Object):
|
def __init__(self, packed_data: Object):
|
||||||
self.packed_data = packed_data
|
self.packed_data = packed_data
|
||||||
|
|
||||||
|
@ -25,6 +25,10 @@ from .primitives import Int, Long
|
|||||||
class Message(Object):
|
class Message(Object):
|
||||||
ID = 0x5bb8e511 # hex(crc32(b"message msg_id:long seqno:int bytes:int body:Object = Message"))
|
ID = 0x5bb8e511 # hex(crc32(b"message msg_id:long seqno:int bytes:int body:Object = Message"))
|
||||||
|
|
||||||
|
__slots__ = ["msg_id", "seq_no", "length", "body"]
|
||||||
|
|
||||||
|
QUALNAME = "Message"
|
||||||
|
|
||||||
def __init__(self, body: Object, msg_id: int, seq_no: int, length: int):
|
def __init__(self, body: Object, msg_id: int, seq_no: int, length: int):
|
||||||
self.msg_id = msg_id
|
self.msg_id = msg_id
|
||||||
self.seq_no = seq_no
|
self.seq_no = seq_no
|
||||||
|
@ -26,6 +26,10 @@ from .primitives import Int
|
|||||||
class MsgContainer(Object):
|
class MsgContainer(Object):
|
||||||
ID = 0x73f1f8dc
|
ID = 0x73f1f8dc
|
||||||
|
|
||||||
|
__slots__ = ["messages"]
|
||||||
|
|
||||||
|
QUALNAME = "MsgContainer"
|
||||||
|
|
||||||
def __init__(self, messages: list):
|
def __init__(self, messages: list):
|
||||||
self.messages = messages
|
self.messages = messages
|
||||||
|
|
||||||
|
@ -19,14 +19,16 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from json import JSONEncoder, dumps
|
from json import dumps
|
||||||
|
|
||||||
from ..all import objects
|
|
||||||
|
|
||||||
|
|
||||||
class Object:
|
class Object:
|
||||||
all = {}
|
all = {}
|
||||||
|
|
||||||
|
__slots__ = []
|
||||||
|
|
||||||
|
QUALNAME = "Base"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read(b: BytesIO, *args):
|
def read(b: BytesIO, *args):
|
||||||
return Object.all[int.from_bytes(b.read(4), "little")].read(b, *args)
|
return Object.all[int.from_bytes(b.read(4), "little")].read(b, *args)
|
||||||
@ -35,20 +37,11 @@ class Object:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return dumps(self, cls=Encoder, indent=4)
|
return dumps(self, indent=4, default=default, ensure_ascii=False)
|
||||||
|
|
||||||
def __bool__(self) -> bool:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def __eq__(self, other) -> bool:
|
|
||||||
return self.__dict__ == other.__dict__
|
|
||||||
|
|
||||||
def __len__(self) -> int:
|
def __len__(self) -> int:
|
||||||
return len(self.write())
|
return len(self.write())
|
||||||
|
|
||||||
def __call__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
return getattr(self, item)
|
return getattr(self, item)
|
||||||
|
|
||||||
@ -62,29 +55,18 @@ def remove_none(obj):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
class Encoder(JSONEncoder):
|
def default(o: "Object"):
|
||||||
def default(self, o: Object):
|
|
||||||
try:
|
try:
|
||||||
content = o.__dict__
|
content = {i: getattr(o, i) for i in o.__slots__}
|
||||||
|
|
||||||
|
return remove_none(
|
||||||
|
OrderedDict(
|
||||||
|
[("_", o.QUALNAME)]
|
||||||
|
+ [i for i in content.items()]
|
||||||
|
)
|
||||||
|
)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if isinstance(o, datetime):
|
if isinstance(o, datetime):
|
||||||
return o.strftime("%d-%b-%Y %H:%M:%S")
|
return o.strftime("%d-%b-%Y %H:%M:%S")
|
||||||
else:
|
else:
|
||||||
return repr(o)
|
return repr(o)
|
||||||
|
|
||||||
name = o.__class__.__name__
|
|
||||||
o = objects.get(getattr(o, "ID", None), None)
|
|
||||||
|
|
||||||
if o is not None:
|
|
||||||
if o.startswith("pyrogram.client"):
|
|
||||||
r = remove_none(OrderedDict([("_", "pyrogram:" + name)] + [i for i in content.items()]))
|
|
||||||
r.pop("_client", None)
|
|
||||||
|
|
||||||
return r
|
|
||||||
else:
|
|
||||||
return OrderedDict(
|
|
||||||
[("_", o.replace("pyrogram.api.types.", "telegram:"))]
|
|
||||||
+ [i for i in content.items()]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
@ -19,8 +19,7 @@
|
|||||||
from .client import Client
|
from .client import Client
|
||||||
from .ext import BaseClient, ChatAction, Emoji, ParseMode
|
from .ext import BaseClient, ChatAction, Emoji, ParseMode
|
||||||
from .filters import Filters
|
from .filters import Filters
|
||||||
from .handlers import (
|
|
||||||
MessageHandler, DeletedMessagesHandler,
|
__all__ = [
|
||||||
CallbackQueryHandler, RawUpdateHandler,
|
"Client", "BaseClient", "ChatAction", "Emoji", "ParseMode", "Filters",
|
||||||
DisconnectHandler, UserStatusHandler
|
]
|
||||||
)
|
|
||||||
|
@ -39,7 +39,11 @@ from typing import Union, List, Type
|
|||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.api.core import Object
|
from pyrogram.api.core import Object
|
||||||
from pyrogram.api.errors import (
|
from pyrogram.client.handlers import DisconnectHandler
|
||||||
|
from pyrogram.client.handlers.handler import Handler
|
||||||
|
from pyrogram.client.methods.password.utils import compute_check
|
||||||
|
from pyrogram.crypto import AES
|
||||||
|
from pyrogram.errors import (
|
||||||
PhoneMigrate, NetworkMigrate, PhoneNumberInvalid,
|
PhoneMigrate, NetworkMigrate, PhoneNumberInvalid,
|
||||||
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
PhoneNumberUnoccupied, PhoneCodeInvalid, PhoneCodeHashEmpty,
|
||||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||||
@ -47,13 +51,8 @@ from pyrogram.api.errors import (
|
|||||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate, PhoneNumberOccupied,
|
||||||
PasswordRecoveryNa, PasswordEmpty
|
PasswordRecoveryNa, PasswordEmpty
|
||||||
)
|
)
|
||||||
from pyrogram.client.handlers import DisconnectHandler
|
|
||||||
from pyrogram.client.handlers.handler import Handler
|
|
||||||
from pyrogram.client.methods.password.utils import compute_check
|
|
||||||
from pyrogram.crypto import AES
|
|
||||||
from pyrogram.session import Auth, Session
|
from pyrogram.session import Auth, Session
|
||||||
from .dispatcher import Dispatcher
|
from .ext import utils, Syncer, BaseClient, Dispatcher
|
||||||
from .ext import utils, Syncer, BaseClient
|
|
||||||
from .methods import Methods
|
from .methods import Methods
|
||||||
from .session_storage import (
|
from .session_storage import (
|
||||||
SessionDoesNotExist, SessionStorage, MemorySessionStorage, JsonSessionStorage,
|
SessionDoesNotExist, SessionStorage, MemorySessionStorage, JsonSessionStorage,
|
||||||
@ -70,9 +69,10 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
session_name (``str``):
|
session_name (``str``):
|
||||||
Name to uniquely identify a session of either a User or a Bot, e.g.: "my_main_account".
|
Name to uniquely identify a session of either a User or a Bot, e.g.: "my_account". This name will be used
|
||||||
You still can use bot token here, but it will be deprecated in next release.
|
to save a file to disk that stores details needed for reconnecting without asking again for credentials.
|
||||||
Note: as long as a valid User session file exists, Pyrogram won't ask you again to input your phone number.
|
Note for bots: You can pass a bot token here, but this usage will be deprecated in next releases.
|
||||||
|
Use *bot_token* instead.
|
||||||
|
|
||||||
api_id (``int``, *optional*):
|
api_id (``int``, *optional*):
|
||||||
The *api_id* part of your Telegram API Key, as integer. E.g.: 12345
|
The *api_id* part of your Telegram API Key, as integer. E.g.: 12345
|
||||||
@ -182,8 +182,11 @@ class Client(Methods, BaseClient):
|
|||||||
Defaults to False (normal session).
|
Defaults to False (normal session).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
terms_of_service_displayed = False
|
||||||
session_name: Union[str, SessionStorage],
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
session_name: str,
|
||||||
api_id: Union[int, str] = None,
|
api_id: Union[int, str] = None,
|
||||||
api_hash: str = None,
|
api_hash: str = None,
|
||||||
app_version: str = None,
|
app_version: str = None,
|
||||||
@ -206,7 +209,8 @@ class Client(Methods, BaseClient):
|
|||||||
config_file: str = BaseClient.CONFIG_FILE,
|
config_file: str = BaseClient.CONFIG_FILE,
|
||||||
plugins: dict = None,
|
plugins: dict = None,
|
||||||
no_updates: bool = None,
|
no_updates: bool = None,
|
||||||
takeout: bool = None):
|
takeout: bool = None
|
||||||
|
):
|
||||||
|
|
||||||
if isinstance(session_name, str):
|
if isinstance(session_name, str):
|
||||||
if session_name == ':memory:':
|
if session_name == ':memory:':
|
||||||
@ -222,6 +226,8 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
super().__init__(session_storage)
|
super().__init__(session_storage)
|
||||||
|
|
||||||
|
super().__init__(session_storage)
|
||||||
|
|
||||||
self.session_name = str(session_name) # TODO: build correct session name
|
self.session_name = str(session_name) # TODO: build correct session name
|
||||||
self.api_id = int(api_id) if api_id else None
|
self.api_id = int(api_id) if api_id else None
|
||||||
self.api_hash = api_hash
|
self.api_hash = api_hash
|
||||||
@ -277,7 +283,7 @@ class Client(Methods, BaseClient):
|
|||||||
Requires no parameters.
|
Requires no parameters.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ConnectionError`` in case you try to start an already started Client.
|
``ConnectionError`` in case you try to start an already started Client.
|
||||||
"""
|
"""
|
||||||
if self.is_started:
|
if self.is_started:
|
||||||
@ -288,10 +294,10 @@ class Client(Methods, BaseClient):
|
|||||||
self.session_storage.is_bot = True
|
self.session_storage.is_bot = True
|
||||||
self.bot_token = self.session_storage._session_name
|
self.bot_token = self.session_storage._session_name
|
||||||
self.session_storage._session_name = self.session_storage._session_name.split(":")[0]
|
self.session_storage._session_name = self.session_storage._session_name.split(":")[0]
|
||||||
warnings.warn('\nYou are using a bot token as session name.\n'
|
warnings.warn('\nWARNING: You are using a bot token as session name!\n'
|
||||||
'It will be deprecated in next update, please use session file name to load '
|
'This usage will be deprecated soon. Please use a session file name to load '
|
||||||
'existing sessions and bot_token argument to create new sessions.',
|
'an existing session and the bot_token argument to create new sessions.\n'
|
||||||
DeprecationWarning, stacklevel=2)
|
'More info: https://docs.pyrogram.ml/start/Setup#bot-authorization\n')
|
||||||
|
|
||||||
self.load_config()
|
self.load_config()
|
||||||
self.load_session()
|
self.load_session()
|
||||||
@ -309,6 +315,7 @@ class Client(Methods, BaseClient):
|
|||||||
try:
|
try:
|
||||||
if self.session_storage.user_id is None:
|
if self.session_storage.user_id is None:
|
||||||
if self.bot_token is None:
|
if self.bot_token is None:
|
||||||
|
self.is_bot = False
|
||||||
self.authorize_user()
|
self.authorize_user()
|
||||||
else:
|
else:
|
||||||
self.session_storage.is_bot = True
|
self.session_storage.is_bot = True
|
||||||
@ -446,7 +453,7 @@ class Client(Methods, BaseClient):
|
|||||||
Requires no parameters.
|
Requires no parameters.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
self.start()
|
self.start()
|
||||||
self.idle()
|
self.idle()
|
||||||
@ -558,9 +565,10 @@ class Client(Methods, BaseClient):
|
|||||||
try:
|
try:
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SendCode(
|
functions.auth.SendCode(
|
||||||
self.phone_number,
|
phone_number=self.phone_number,
|
||||||
self.api_id,
|
api_id=self.api_id,
|
||||||
self.api_hash
|
api_hash=self.api_hash,
|
||||||
|
settings=types.CodeSettings()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except (PhoneMigrate, NetworkMigrate) as e:
|
except (PhoneMigrate, NetworkMigrate) as e:
|
||||||
@ -604,8 +612,9 @@ class Client(Methods, BaseClient):
|
|||||||
phone_code_hash = r.phone_code_hash
|
phone_code_hash = r.phone_code_hash
|
||||||
terms_of_service = r.terms_of_service
|
terms_of_service = r.terms_of_service
|
||||||
|
|
||||||
if terms_of_service:
|
if terms_of_service and not Client.terms_of_service_displayed:
|
||||||
print("\n" + terms_of_service.text + "\n")
|
print("\n" + terms_of_service.text + "\n")
|
||||||
|
Client.terms_of_service_displayed = True
|
||||||
|
|
||||||
if self.force_sms:
|
if self.force_sms:
|
||||||
self.send(
|
self.send(
|
||||||
@ -640,9 +649,9 @@ class Client(Methods, BaseClient):
|
|||||||
try:
|
try:
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SignIn(
|
functions.auth.SignIn(
|
||||||
self.phone_number,
|
phone_number=self.phone_number,
|
||||||
phone_code_hash,
|
phone_code_hash=phone_code_hash,
|
||||||
self.phone_code
|
phone_code=self.phone_code
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except PhoneNumberUnoccupied:
|
except PhoneNumberUnoccupied:
|
||||||
@ -653,11 +662,11 @@ class Client(Methods, BaseClient):
|
|||||||
try:
|
try:
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.auth.SignUp(
|
functions.auth.SignUp(
|
||||||
self.phone_number,
|
phone_number=self.phone_number,
|
||||||
phone_code_hash,
|
phone_code_hash=phone_code_hash,
|
||||||
self.phone_code,
|
phone_code=self.phone_code,
|
||||||
self.first_name,
|
first_name=self.first_name,
|
||||||
self.last_name
|
last_name=self.last_name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except PhoneNumberOccupied:
|
except PhoneNumberOccupied:
|
||||||
@ -751,7 +760,11 @@ class Client(Methods, BaseClient):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if terms_of_service:
|
if terms_of_service:
|
||||||
assert self.send(functions.help.AcceptTermsOfService(terms_of_service.id))
|
assert self.send(
|
||||||
|
functions.help.AcceptTermsOfService(
|
||||||
|
id=terms_of_service.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
self.password = None
|
self.password = None
|
||||||
self.session_storage.user_id = r.user.id
|
self.session_storage.user_id = r.user.id
|
||||||
@ -992,16 +1005,16 @@ class Client(Methods, BaseClient):
|
|||||||
Timeout in seconds.
|
Timeout in seconds.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
if not self.is_started:
|
if not self.is_started:
|
||||||
raise ConnectionError("Client has not been started")
|
raise ConnectionError("Client has not been started")
|
||||||
|
|
||||||
if self.no_updates:
|
if self.no_updates:
|
||||||
data = functions.InvokeWithoutUpdates(data)
|
data = functions.InvokeWithoutUpdates(query=data)
|
||||||
|
|
||||||
if self.takeout_id:
|
if self.takeout_id:
|
||||||
data = functions.InvokeWithTakeout(self.takeout_id, data)
|
data = functions.InvokeWithTakeout(takeout_id=self.takeout_id, query=data)
|
||||||
|
|
||||||
r = self.session.send(data, retries, timeout)
|
r = self.session.send(data, retries, timeout)
|
||||||
|
|
||||||
@ -1118,7 +1131,7 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
module = import_module(module_path)
|
module = import_module(module_path)
|
||||||
except ModuleNotFoundError:
|
except ImportError:
|
||||||
log.warning('[LOAD] Ignoring non-existent module "{}"'.format(module_path))
|
log.warning('[LOAD] Ignoring non-existent module "{}"'.format(module_path))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -1154,7 +1167,7 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
module = import_module(module_path)
|
module = import_module(module_path)
|
||||||
except ModuleNotFoundError:
|
except ImportError:
|
||||||
log.warning('[UNLOAD] Ignoring non-existent module "{}"'.format(module_path))
|
log.warning('[UNLOAD] Ignoring non-existent module "{}"'.format(module_path))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -1241,7 +1254,7 @@ class Client(Methods, BaseClient):
|
|||||||
On success, the resolved peer id is returned in form of an InputPeer object.
|
On success, the resolved peer id is returned in form of an InputPeer object.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``KeyError`` in case the peer doesn't exist in the internal database.
|
``KeyError`` in case the peer doesn't exist in the internal database.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
@ -1276,7 +1289,7 @@ class Client(Methods, BaseClient):
|
|||||||
self.fetch_peers(
|
self.fetch_peers(
|
||||||
self.send(
|
self.send(
|
||||||
functions.users.GetUsers(
|
functions.users.GetUsers(
|
||||||
id=[types.InputUser(peer_id, 0)]
|
id=[types.InputUser(user_id=peer_id, access_hash=0)]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1284,7 +1297,7 @@ class Client(Methods, BaseClient):
|
|||||||
if str(peer_id).startswith("-100"):
|
if str(peer_id).startswith("-100"):
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.GetChannels(
|
functions.channels.GetChannels(
|
||||||
id=[types.InputChannel(int(str(peer_id)[4:]), 0)]
|
id=[types.InputChannel(channel_id=int(str(peer_id)[4:]), access_hash=0)]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@ -1348,7 +1361,7 @@ class Client(Methods, BaseClient):
|
|||||||
On success, the uploaded file is returned in form of an InputFile object.
|
On success, the uploaded file is returned in form of an InputFile object.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
part_size = 512 * 1024
|
part_size = 512 * 1024
|
||||||
file_size = os.path.getsize(path)
|
file_size = os.path.getsize(path)
|
||||||
@ -1591,8 +1604,8 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
hashes = session.send(
|
hashes = session.send(
|
||||||
functions.upload.GetCdnFileHashes(
|
functions.upload.GetCdnFileHashes(
|
||||||
r.file_token,
|
file_token=r.file_token,
|
||||||
offset
|
offset=offset
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
from .base_client import BaseClient
|
from .base_client import BaseClient
|
||||||
from .chat_action import ChatAction
|
from .chat_action import ChatAction
|
||||||
|
from .dispatcher import Dispatcher
|
||||||
from .emoji import Emoji
|
from .emoji import Emoji
|
||||||
from .parse_mode import ParseMode
|
from .parse_mode import ParseMode
|
||||||
from .syncer import Syncer
|
from .syncer import Syncer
|
||||||
|
@ -74,8 +74,8 @@ class BaseClient:
|
|||||||
self.rnd_id = MsgId
|
self.rnd_id = MsgId
|
||||||
self.channels_pts = {}
|
self.channels_pts = {}
|
||||||
|
|
||||||
self.markdown = Markdown(self.session_storage)
|
self.markdown = Markdown(self.session_storage, self)
|
||||||
self.html = HTML(self.session_storage)
|
self.html = HTML(self.session_storage, self)
|
||||||
|
|
||||||
self.session = None
|
self.session = None
|
||||||
self.media_sessions = {}
|
self.media_sessions = {}
|
||||||
@ -122,3 +122,6 @@ class BaseClient:
|
|||||||
|
|
||||||
def get_chat_members_count(self, *args, **kwargs):
|
def get_chat_members_count(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def answer_inline_query(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
@ -24,7 +24,10 @@ from threading import Thread
|
|||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import types
|
from pyrogram.api import types
|
||||||
from ..handlers import CallbackQueryHandler, MessageHandler, RawUpdateHandler, UserStatusHandler, DeletedMessagesHandler
|
from ..handlers import (
|
||||||
|
CallbackQueryHandler, MessageHandler, DeletedMessagesHandler,
|
||||||
|
UserStatusHandler, RawUpdateHandler, InlineQueryHandler
|
||||||
|
)
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -73,7 +76,10 @@ class Dispatcher:
|
|||||||
(types.UpdateUserStatus,):
|
(types.UpdateUserStatus,):
|
||||||
lambda upd, usr, cht: (
|
lambda upd, usr, cht: (
|
||||||
pyrogram.UserStatus._parse(self.client, upd.status, upd.user_id), UserStatusHandler
|
pyrogram.UserStatus._parse(self.client, upd.status, upd.user_id), UserStatusHandler
|
||||||
)
|
),
|
||||||
|
|
||||||
|
(types.UpdateBotInlineQuery,):
|
||||||
|
lambda upd, usr, cht: (pyrogram.InlineQuery._parse(self.client, upd, usr), InlineQueryHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
|
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}
|
@ -67,10 +67,10 @@ def get_peer_id(input_peer) -> int:
|
|||||||
|
|
||||||
def get_input_peer(peer_id: int, access_hash: int):
|
def get_input_peer(peer_id: int, access_hash: int):
|
||||||
return (
|
return (
|
||||||
types.InputPeerUser(peer_id, access_hash) if peer_id > 0
|
types.InputPeerUser(user_id=peer_id, access_hash=access_hash) if peer_id > 0
|
||||||
else types.InputPeerChannel(int(str(peer_id)[4:]), access_hash)
|
else types.InputPeerChannel(channel_id=int(str(peer_id)[4:]), access_hash=access_hash)
|
||||||
if (str(peer_id).startswith("-100") and access_hash)
|
if (str(peer_id).startswith("-100") and access_hash)
|
||||||
else types.InputPeerChat(-peer_id)
|
else types.InputPeerChat(chat_id=-peer_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ class Filters:
|
|||||||
voice = create("Voice", lambda _, m: bool(m.voice))
|
voice = create("Voice", lambda _, m: bool(m.voice))
|
||||||
"""Filter messages that contain :obj:`Voice <pyrogram.Voice>` note objects."""
|
"""Filter messages that contain :obj:`Voice <pyrogram.Voice>` note objects."""
|
||||||
|
|
||||||
video_note = create("Voice", lambda _, m: bool(m.video_note))
|
video_note = create("VideoNote", lambda _, m: bool(m.video_note))
|
||||||
"""Filter messages that contain :obj:`VideoNote <pyrogram.VideoNote>` objects."""
|
"""Filter messages that contain :obj:`VideoNote <pyrogram.VideoNote>` objects."""
|
||||||
|
|
||||||
contact = create("Contact", lambda _, m: bool(m.contact))
|
contact = create("Contact", lambda _, m: bool(m.contact))
|
||||||
@ -222,14 +222,16 @@ class Filters:
|
|||||||
- poll"""
|
- poll"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def command(command: str or list,
|
def command(
|
||||||
|
commands: str or list,
|
||||||
prefix: str or list = "/",
|
prefix: str or list = "/",
|
||||||
separator: str = " ",
|
separator: str = " ",
|
||||||
case_sensitive: bool = False):
|
case_sensitive: bool = False
|
||||||
|
):
|
||||||
"""Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
|
"""Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
command (``str`` | ``list``):
|
commands (``str`` | ``list``):
|
||||||
The command or list of commands as string the filter should look for.
|
The command or list of commands as string the filter should look for.
|
||||||
Examples: "start", ["start", "help", "settings"]. When a message text containing
|
Examples: "start", ["start", "help", "settings"]. When a message text containing
|
||||||
a command arrives, the command itself and its arguments will be stored in the *command*
|
a command arrives, the command itself and its arguments will be stored in the *command*
|
||||||
@ -249,31 +251,25 @@ class Filters:
|
|||||||
Examples: when True, command="Start" would trigger /Start but not /start.
|
Examples: when True, command="Start" would trigger /Start but not /start.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def f(_, m):
|
def func(flt, message):
|
||||||
if m.text:
|
text = message.text or message.caption
|
||||||
for i in _.p:
|
|
||||||
if m.text.startswith(i):
|
if text:
|
||||||
t = m.text.split(_.s)
|
for p in flt.p:
|
||||||
c, a = t[0][len(i):], t[1:]
|
if text.startswith(p):
|
||||||
c = c if _.cs else c.lower()
|
s = text.split(flt.s)
|
||||||
m.command = ([c] + a) if c in _.c else None
|
c, a = s[0][len(p):], s[1:]
|
||||||
|
c = c if flt.cs else c.lower()
|
||||||
|
message.command = ([c] + a) if c in flt.c else None
|
||||||
break
|
break
|
||||||
|
|
||||||
return bool(m.command)
|
return bool(message.command)
|
||||||
|
|
||||||
return create(
|
commands = commands if type(commands) is list else [commands]
|
||||||
"Command",
|
commands = {c if case_sensitive else c.lower() for c in commands}
|
||||||
f,
|
prefixes = set(prefix) if prefix else {""}
|
||||||
c={command if case_sensitive
|
|
||||||
else command.lower()}
|
return create("Command", func=func, c=commands, p=prefixes, s=separator, cs=case_sensitive)
|
||||||
if not isinstance(command, list)
|
|
||||||
else {c if case_sensitive
|
|
||||||
else c.lower()
|
|
||||||
for c in command},
|
|
||||||
p=set(prefix) if prefix else {""},
|
|
||||||
s=separator,
|
|
||||||
cs=case_sensitive
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def regex(pattern, flags: int = 0):
|
def regex(pattern, flags: int = 0):
|
||||||
@ -311,21 +307,20 @@ class Filters:
|
|||||||
|
|
||||||
def __init__(self, users: int or str or list = None):
|
def __init__(self, users: int or str or list = None):
|
||||||
users = [] if users is None else users if type(users) is list else [users]
|
users = [] if users is None else users if type(users) is list else [users]
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
{"me" if i in ["me", "self"] else i.lower().strip("@") if type(i) is str else i for i in users}
|
"me" if u in ["me", "self"]
|
||||||
if type(users) is list else
|
else u.lower().strip("@") if type(u) is str
|
||||||
{"me" if users in ["me", "self"] else users.lower().strip("@") if type(users) is str else users}
|
else u for u in users
|
||||||
)
|
)
|
||||||
|
|
||||||
def __call__(self, message):
|
def __call__(self, message):
|
||||||
return bool(
|
return (message.from_user
|
||||||
message.from_user
|
|
||||||
and (message.from_user.id in self
|
and (message.from_user.id in self
|
||||||
or (message.from_user.username
|
or (message.from_user.username
|
||||||
and message.from_user.username.lower() in self)
|
and message.from_user.username.lower() in self)
|
||||||
or ("me" in self
|
or ("me" in self
|
||||||
and message.from_user.is_self))
|
and message.from_user.is_self)))
|
||||||
)
|
|
||||||
|
|
||||||
# noinspection PyPep8Naming
|
# noinspection PyPep8Naming
|
||||||
class chat(Filter, set):
|
class chat(Filter, set):
|
||||||
@ -343,21 +338,21 @@ class Filters:
|
|||||||
|
|
||||||
def __init__(self, chats: int or str or list = None):
|
def __init__(self, chats: int or str or list = None):
|
||||||
chats = [] if chats is None else chats if type(chats) is list else [chats]
|
chats = [] if chats is None else chats if type(chats) is list else [chats]
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
{"me" if i in ["me", "self"] else i.lower().strip("@") if type(i) is str else i for i in chats}
|
"me" if c in ["me", "self"]
|
||||||
if type(chats) is list else
|
else c.lower().strip("@") if type(c) is str
|
||||||
{"me" if chats in ["me", "self"] else chats.lower().strip("@") if type(chats) is str else chats}
|
else c for c in chats
|
||||||
)
|
)
|
||||||
|
|
||||||
def __call__(self, message):
|
def __call__(self, message):
|
||||||
return bool(
|
return (message.chat
|
||||||
message.chat
|
|
||||||
and (message.chat.id in self
|
and (message.chat.id in self
|
||||||
or (message.chat.username
|
or (message.chat.username
|
||||||
and message.chat.username.lower() in self)
|
and message.chat.username.lower() in self)
|
||||||
or ("me" in self and message.from_user
|
or ("me" in self
|
||||||
|
and message.from_user
|
||||||
and message.from_user.is_self
|
and message.from_user.is_self
|
||||||
and not message.outgoing))
|
and not message.outgoing)))
|
||||||
)
|
|
||||||
|
|
||||||
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
dan = create("Dan", lambda _, m: bool(m.from_user and m.from_user.id == 23122162))
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
from .callback_query_handler import CallbackQueryHandler
|
from .callback_query_handler import CallbackQueryHandler
|
||||||
from .deleted_messages_handler import DeletedMessagesHandler
|
from .deleted_messages_handler import DeletedMessagesHandler
|
||||||
from .disconnect_handler import DisconnectHandler
|
from .disconnect_handler import DisconnectHandler
|
||||||
|
from .inline_query_handler import InlineQueryHandler
|
||||||
from .message_handler import MessageHandler
|
from .message_handler import MessageHandler
|
||||||
from .raw_update_handler import RawUpdateHandler
|
from .raw_update_handler import RawUpdateHandler
|
||||||
from .user_status_handler import UserStatusHandler
|
from .user_status_handler import UserStatusHandler
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"MessageHandler", "DeletedMessagesHandler", "CallbackQueryHandler", "RawUpdateHandler", "DisconnectHandler",
|
||||||
|
"UserStatusHandler", "InlineQueryHandler"
|
||||||
|
]
|
||||||
|
54
pyrogram/client/handlers/inline_query_handler.py
Normal file
54
pyrogram/client/handlers/inline_query_handler.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 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 .handler import Handler
|
||||||
|
|
||||||
|
|
||||||
|
class InlineQueryHandler(Handler):
|
||||||
|
"""The InlineQuery handler class. Used to handle inline queries.
|
||||||
|
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
||||||
|
|
||||||
|
For a nicer way to register this handler, have a look at the
|
||||||
|
:meth:`on_inline_query() <pyrogram.Client.on_inline_query>` decorator.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback (``callable``):
|
||||||
|
Pass a function that will be called when a new InlineQuery arrives. It takes *(client, inline_query)*
|
||||||
|
as positional arguments (look at the section below for a detailed description).
|
||||||
|
|
||||||
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
Pass one or more filters to allow only a subset of inline queries to be passed
|
||||||
|
in your callback function.
|
||||||
|
|
||||||
|
Other parameters:
|
||||||
|
client (:obj:`Client <pyrogram.Client>`):
|
||||||
|
The Client itself, useful when you want to call other API methods inside the inline query handler.
|
||||||
|
|
||||||
|
inline_query (:obj:`InlineQuery <pyrogram.InlineQuery>`):
|
||||||
|
The received inline query.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, callback: callable, filters=None):
|
||||||
|
super().__init__(callback, filters)
|
||||||
|
|
||||||
|
def check(self, callback_query):
|
||||||
|
return (
|
||||||
|
self.filters(callback_query)
|
||||||
|
if callable(self.filters)
|
||||||
|
else True
|
||||||
|
)
|
@ -17,6 +17,7 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .answer_callback_query import AnswerCallbackQuery
|
from .answer_callback_query import AnswerCallbackQuery
|
||||||
|
from .answer_inline_query import AnswerInlineQuery
|
||||||
from .get_game_high_scores import GetGameHighScores
|
from .get_game_high_scores import GetGameHighScores
|
||||||
from .get_inline_bot_results import GetInlineBotResults
|
from .get_inline_bot_results import GetInlineBotResults
|
||||||
from .request_callback_answer import RequestCallbackAnswer
|
from .request_callback_answer import RequestCallbackAnswer
|
||||||
@ -27,6 +28,7 @@ from .set_game_score import SetGameScore
|
|||||||
|
|
||||||
class Bots(
|
class Bots(
|
||||||
AnswerCallbackQuery,
|
AnswerCallbackQuery,
|
||||||
|
AnswerInlineQuery,
|
||||||
GetInlineBotResults,
|
GetInlineBotResults,
|
||||||
RequestCallbackAnswer,
|
RequestCallbackAnswer,
|
||||||
SendInlineBotResult,
|
SendInlineBotResult,
|
||||||
|
@ -21,12 +21,14 @@ from pyrogram.client.ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class AnswerCallbackQuery(BaseClient):
|
class AnswerCallbackQuery(BaseClient):
|
||||||
def answer_callback_query(self,
|
def answer_callback_query(
|
||||||
|
self,
|
||||||
callback_query_id: str,
|
callback_query_id: str,
|
||||||
text: str = None,
|
text: str = None,
|
||||||
show_alert: bool = None,
|
show_alert: bool = None,
|
||||||
url: str = None,
|
url: str = None,
|
||||||
cache_time: int = 0):
|
cache_time: int = 0
|
||||||
|
):
|
||||||
"""Use this method to send answers to callback queries sent from inline keyboards.
|
"""Use this method to send answers to callback queries sent from inline keyboards.
|
||||||
The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
|
The answer will be displayed to the user as a notification at the top of the chat screen or as an alert.
|
||||||
|
|
||||||
@ -55,7 +57,7 @@ class AnswerCallbackQuery(BaseClient):
|
|||||||
True, on success.
|
True, on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SetBotCallbackAnswer(
|
functions.messages.SetBotCallbackAnswer(
|
||||||
|
91
pyrogram/client/methods/bots/answer_inline_query.py
Normal file
91
pyrogram/client/methods/bots/answer_inline_query.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 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 List
|
||||||
|
|
||||||
|
from pyrogram.api import functions, types
|
||||||
|
from pyrogram.client.ext import BaseClient
|
||||||
|
from ...types.inline_mode import InlineQueryResult
|
||||||
|
|
||||||
|
|
||||||
|
class AnswerInlineQuery(BaseClient):
|
||||||
|
def answer_inline_query(
|
||||||
|
self,
|
||||||
|
inline_query_id: str,
|
||||||
|
results: List[InlineQueryResult],
|
||||||
|
cache_time: int = 300,
|
||||||
|
is_personal: bool = None,
|
||||||
|
next_offset: str = "",
|
||||||
|
switch_pm_text: str = "",
|
||||||
|
switch_pm_parameter: str = ""
|
||||||
|
):
|
||||||
|
"""Use this method to send answers to an inline query.
|
||||||
|
No more than 50 results per query are allowed.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
inline_query_id (``str``):
|
||||||
|
Unique identifier for the answered query.
|
||||||
|
|
||||||
|
results (List of :obj:`InlineQueryResult <pyrogram.InlineQueryResult>`):
|
||||||
|
A list of results for the inline query.
|
||||||
|
|
||||||
|
cache_time (``int``, *optional*):
|
||||||
|
The maximum amount of time in seconds that the result of the inline query may be cached on the server.
|
||||||
|
Defaults to 300.
|
||||||
|
|
||||||
|
is_personal (``bool``, *optional*):
|
||||||
|
Pass True, if results may be cached on the server side only for the user that sent the query.
|
||||||
|
By default, results may be returned to any user who sends the same query.
|
||||||
|
|
||||||
|
next_offset (``str``, *optional*):
|
||||||
|
Pass the offset that a client should send in the next query with the same text to receive more results.
|
||||||
|
Pass an empty string if there are no more results or if you don‘t support pagination.
|
||||||
|
Offset length can’t exceed 64 bytes.
|
||||||
|
|
||||||
|
switch_pm_text (``str``, *optional*):
|
||||||
|
If passed, clients will display a button with specified text that switches the user to a private chat
|
||||||
|
with the bot and sends the bot a start message with the parameter switch_pm_parameter
|
||||||
|
|
||||||
|
switch_pm_parameter (``str``, *optional*):
|
||||||
|
`Deep-linking <https://core.telegram.org/bots#deep-linking>`_ parameter for the /start message sent to
|
||||||
|
the bot when user presses the switch button. 1-64 characters, only A-Z, a-z, 0-9, _ and - are allowed.
|
||||||
|
|
||||||
|
Example: An inline bot that sends YouTube videos can ask the user to connect the bot to their YouTube
|
||||||
|
account to adapt search results accordingly. To do this, it displays a "Connect your YouTube account"
|
||||||
|
button above the results, or even before showing any. The user presses the button, switches to a private
|
||||||
|
chat with the bot and, in doing so, passes a start parameter that instructs the bot to return an oauth
|
||||||
|
link. Once done, the bot can offer a switch_inline button so that the user can easily return to the chat
|
||||||
|
where they wanted to use the bot's inline capabilities.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
On success, True is returned.
|
||||||
|
"""
|
||||||
|
return self.send(
|
||||||
|
functions.messages.SetInlineBotResults(
|
||||||
|
query_id=int(inline_query_id),
|
||||||
|
results=[r.write() for r in results],
|
||||||
|
cache_time=cache_time,
|
||||||
|
gallery=None,
|
||||||
|
private=is_personal or None,
|
||||||
|
next_offset=next_offset or None,
|
||||||
|
switch_pm=types.InlineBotSwitchPM(
|
||||||
|
text=switch_pm_text,
|
||||||
|
start_param=switch_pm_parameter
|
||||||
|
) if switch_pm_text else None
|
||||||
|
)
|
||||||
|
)
|
@ -24,10 +24,12 @@ from pyrogram.client.ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class GetGameHighScores(BaseClient):
|
class GetGameHighScores(BaseClient):
|
||||||
def get_game_high_scores(self,
|
def get_game_high_scores(
|
||||||
|
self,
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
message_id: int = None):
|
message_id: int = None
|
||||||
|
):
|
||||||
"""Use this method to get data for high score tables.
|
"""Use this method to get data for high score tables.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -50,7 +52,7 @@ class GetGameHighScores(BaseClient):
|
|||||||
On success, a :obj:`GameHighScores <pyrogram.GameHighScores>` object is returned.
|
On success, a :obj:`GameHighScores <pyrogram.GameHighScores>` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
# TODO: inline_message_id
|
# TODO: inline_message_id
|
||||||
|
|
||||||
|
@ -19,17 +19,19 @@
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.api.errors import UnknownError
|
from pyrogram.errors import UnknownError
|
||||||
from pyrogram.client.ext import BaseClient
|
from pyrogram.client.ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class GetInlineBotResults(BaseClient):
|
class GetInlineBotResults(BaseClient):
|
||||||
def get_inline_bot_results(self,
|
def get_inline_bot_results(
|
||||||
|
self,
|
||||||
bot: Union[int, str],
|
bot: Union[int, str],
|
||||||
query: str,
|
query: str,
|
||||||
offset: str = "",
|
offset: str = "",
|
||||||
latitude: float = None,
|
latitude: float = None,
|
||||||
longitude: float = None):
|
longitude: float = None
|
||||||
|
):
|
||||||
"""Use this method to get bot results via inline queries.
|
"""Use this method to get bot results via inline queries.
|
||||||
You can then send a result using :obj:`send_inline_bot_result <pyrogram.Client.send_inline_bot_result>`
|
You can then send a result using :obj:`send_inline_bot_result <pyrogram.Client.send_inline_bot_result>`
|
||||||
|
|
||||||
@ -56,7 +58,7 @@ class GetInlineBotResults(BaseClient):
|
|||||||
On Success, :obj:`BotResults <pyrogram.api.types.messages.BotResults>` is returned.
|
On Success, :obj:`BotResults <pyrogram.api.types.messages.BotResults>` is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``TimeoutError`` if the bot fails to answer within 10 seconds
|
``TimeoutError`` if the bot fails to answer within 10 seconds
|
||||||
"""
|
"""
|
||||||
# TODO: Don't return the raw type
|
# TODO: Don't return the raw type
|
||||||
|
@ -23,12 +23,14 @@ from pyrogram.client.ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class RequestCallbackAnswer(BaseClient):
|
class RequestCallbackAnswer(BaseClient):
|
||||||
def request_callback_answer(self,
|
def request_callback_answer(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
message_id: int,
|
message_id: int,
|
||||||
callback_data: bytes):
|
callback_data: bytes
|
||||||
"""Use this method to request a callback answer from bots. This is the equivalent of clicking an
|
):
|
||||||
inline button containing callback data.
|
"""Use this method to request a callback answer from bots.
|
||||||
|
This is the equivalent of clicking an inline button containing callback data.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -47,7 +49,7 @@ class RequestCallbackAnswer(BaseClient):
|
|||||||
or as an alert.
|
or as an alert.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``TimeoutError`` if the bot fails to answer within 10 seconds.
|
``TimeoutError`` if the bot fails to answer within 10 seconds.
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
|
@ -24,15 +24,19 @@ from pyrogram.client.ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class SendGame(BaseClient):
|
class SendGame(BaseClient):
|
||||||
def send_game(self,
|
def send_game(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
game_short_name: str,
|
game_short_name: str,
|
||||||
disable_notification: bool = None,
|
disable_notification: bool = None,
|
||||||
reply_to_message_id: int = None,
|
reply_to_message_id: int = None,
|
||||||
reply_markup: Union["pyrogram.InlineKeyboardMarkup",
|
reply_markup: Union[
|
||||||
|
"pyrogram.InlineKeyboardMarkup",
|
||||||
"pyrogram.ReplyKeyboardMarkup",
|
"pyrogram.ReplyKeyboardMarkup",
|
||||||
"pyrogram.ReplyKeyboardRemove",
|
"pyrogram.ReplyKeyboardRemove",
|
||||||
"pyrogram.ForceReply"] = None) -> "pyrogram.Message":
|
"pyrogram.ForceReply"
|
||||||
|
] = None
|
||||||
|
) -> "pyrogram.Message":
|
||||||
"""Use this method to send a game.
|
"""Use this method to send a game.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -59,7 +63,7 @@ class SendGame(BaseClient):
|
|||||||
On success, the sent :obj:`Message` is returned.
|
On success, the sent :obj:`Message` is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.messages.SendMedia(
|
functions.messages.SendMedia(
|
||||||
|
@ -23,13 +23,15 @@ from pyrogram.client.ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class SendInlineBotResult(BaseClient):
|
class SendInlineBotResult(BaseClient):
|
||||||
def send_inline_bot_result(self,
|
def send_inline_bot_result(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
query_id: int,
|
query_id: int,
|
||||||
result_id: str,
|
result_id: str,
|
||||||
disable_notification: bool = None,
|
disable_notification: bool = None,
|
||||||
reply_to_message_id: int = None,
|
reply_to_message_id: int = None,
|
||||||
hide_via: bool = None):
|
hide_via: bool = None
|
||||||
|
):
|
||||||
"""Use this method to send an inline bot result.
|
"""Use this method to send an inline bot result.
|
||||||
Bot results can be retrieved using :obj:`get_inline_bot_results <pyrogram.Client.get_inline_bot_results>`
|
Bot results can be retrieved using :obj:`get_inline_bot_results <pyrogram.Client.get_inline_bot_results>`
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ class SendInlineBotResult(BaseClient):
|
|||||||
On success, the sent Message is returned.
|
On success, the sent Message is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.SendInlineBotResult(
|
functions.messages.SendInlineBotResult(
|
||||||
|
@ -24,13 +24,15 @@ from pyrogram.client.ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class SetGameScore(BaseClient):
|
class SetGameScore(BaseClient):
|
||||||
def set_game_score(self,
|
def set_game_score(
|
||||||
|
self,
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
score: int,
|
score: int,
|
||||||
force: bool = None,
|
force: bool = None,
|
||||||
disable_edit_message: bool = None,
|
disable_edit_message: bool = None,
|
||||||
chat_id: Union[int, str] = None,
|
chat_id: Union[int, str] = None,
|
||||||
message_id: int = None):
|
message_id: int = None
|
||||||
|
):
|
||||||
# inline_message_id: str = None): TODO Add inline_message_id
|
# inline_message_id: str = None): TODO Add inline_message_id
|
||||||
"""Use this method to set the score of the specified user in a game.
|
"""Use this method to set the score of the specified user in a game.
|
||||||
|
|
||||||
@ -65,7 +67,7 @@ class SetGameScore(BaseClient):
|
|||||||
otherwise returns True.
|
otherwise returns True.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
:class:`BotScoreNotModified` if the new score is not greater than the user's current score in the chat and force is False.
|
:class:`BotScoreNotModified` if the new score is not greater than the user's current score in the chat and force is False.
|
||||||
"""
|
"""
|
||||||
r = self.send(
|
r = self.send(
|
||||||
|
@ -31,12 +31,14 @@ from .kick_chat_member import KickChatMember
|
|||||||
from .leave_chat import LeaveChat
|
from .leave_chat import LeaveChat
|
||||||
from .pin_chat_message import PinChatMessage
|
from .pin_chat_message import PinChatMessage
|
||||||
from .promote_chat_member import PromoteChatMember
|
from .promote_chat_member import PromoteChatMember
|
||||||
|
from .restrict_chat import RestrictChat
|
||||||
from .restrict_chat_member import RestrictChatMember
|
from .restrict_chat_member import RestrictChatMember
|
||||||
from .set_chat_description import SetChatDescription
|
from .set_chat_description import SetChatDescription
|
||||||
from .set_chat_photo import SetChatPhoto
|
from .set_chat_photo import SetChatPhoto
|
||||||
from .set_chat_title import SetChatTitle
|
from .set_chat_title import SetChatTitle
|
||||||
from .unban_chat_member import UnbanChatMember
|
from .unban_chat_member import UnbanChatMember
|
||||||
from .unpin_chat_message import UnpinChatMessage
|
from .unpin_chat_message import UnpinChatMessage
|
||||||
|
from .update_chat_username import UpdateChatUsername
|
||||||
|
|
||||||
|
|
||||||
class Chats(
|
class Chats(
|
||||||
@ -60,6 +62,8 @@ class Chats(
|
|||||||
GetChatMembersCount,
|
GetChatMembersCount,
|
||||||
GetChatPreview,
|
GetChatPreview,
|
||||||
IterDialogs,
|
IterDialogs,
|
||||||
IterChatMembers
|
IterChatMembers,
|
||||||
|
UpdateChatUsername,
|
||||||
|
RestrictChat
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -23,8 +23,10 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class DeleteChatPhoto(BaseClient):
|
class DeleteChatPhoto(BaseClient):
|
||||||
def delete_chat_photo(self,
|
def delete_chat_photo(
|
||||||
chat_id: Union[int, str]) -> bool:
|
self,
|
||||||
|
chat_id: Union[int, str]
|
||||||
|
) -> bool:
|
||||||
"""Use this method to delete a chat photo.
|
"""Use this method to delete a chat photo.
|
||||||
Photos can't be changed for private chats.
|
Photos can't be changed for private chats.
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
@ -41,7 +43,7 @@ class DeleteChatPhoto(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
``ValueError`` if a chat_id belongs to user.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -23,8 +23,10 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class ExportChatInviteLink(BaseClient):
|
class ExportChatInviteLink(BaseClient):
|
||||||
def export_chat_invite_link(self,
|
def export_chat_invite_link(
|
||||||
chat_id: Union[int, str]) -> str:
|
self,
|
||||||
|
chat_id: Union[int, str]
|
||||||
|
) -> str:
|
||||||
"""Use this method to generate a new invite link for a chat; any previously generated link is revoked.
|
"""Use this method to generate a new invite link for a chat; any previously generated link is revoked.
|
||||||
|
|
||||||
You must be an administrator in the chat for this to work and have the appropriate admin rights.
|
You must be an administrator in the chat for this to work and have the appropriate admin rights.
|
||||||
@ -38,14 +40,14 @@ class ExportChatInviteLink(BaseClient):
|
|||||||
On success, the exported invite link as string is returned.
|
On success, the exported invite link as string is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if isinstance(peer, types.InputPeerChat):
|
if isinstance(peer, types.InputPeerChat):
|
||||||
return self.send(
|
return self.send(
|
||||||
functions.messages.ExportChatInvite(
|
functions.messages.ExportChatInvite(
|
||||||
chat_id=peer.chat_id
|
peer=peer.chat_id
|
||||||
)
|
)
|
||||||
).link
|
).link
|
||||||
elif isinstance(peer, types.InputPeerChannel):
|
elif isinstance(peer, types.InputPeerChannel):
|
||||||
|
@ -24,10 +24,13 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class GetChat(BaseClient):
|
class GetChat(BaseClient):
|
||||||
def get_chat(self,
|
def get_chat(
|
||||||
chat_id: Union[int, str]) -> "pyrogram.Chat":
|
self,
|
||||||
"""Use this method to get up to date information about the chat (current name of the user for
|
chat_id: Union[int, str]
|
||||||
one-on-one conversations, current username of a user, group or channel, etc.)
|
) -> "pyrogram.Chat":
|
||||||
|
"""Use this method to get up to date information about the chat.
|
||||||
|
Information include current name of the user for one-on-one conversations, current username of a user, group or
|
||||||
|
channel, etc.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -39,7 +42,7 @@ class GetChat(BaseClient):
|
|||||||
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
|
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` in case the chat invite link refers to a chat you haven't joined yet.
|
``ValueError`` in case the chat invite link refers to a chat you haven't joined yet.
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(str(chat_id))
|
match = self.INVITE_LINK_RE.match(str(chat_id))
|
||||||
@ -67,10 +70,10 @@ class GetChat(BaseClient):
|
|||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if isinstance(peer, types.InputPeerChannel):
|
if isinstance(peer, types.InputPeerChannel):
|
||||||
r = self.send(functions.channels.GetFullChannel(peer))
|
r = self.send(functions.channels.GetFullChannel(channel=peer))
|
||||||
elif isinstance(peer, (types.InputPeerUser, types.InputPeerSelf)):
|
elif isinstance(peer, (types.InputPeerUser, types.InputPeerSelf)):
|
||||||
r = self.send(functions.users.GetFullUser(peer))
|
r = self.send(functions.users.GetFullUser(id=peer))
|
||||||
else:
|
else:
|
||||||
r = self.send(functions.messages.GetFullChat(peer.chat_id))
|
r = self.send(functions.messages.GetFullChat(chat_id=peer.chat_id))
|
||||||
|
|
||||||
return pyrogram.Chat._parse_full(self, r)
|
return pyrogram.Chat._parse_full(self, r)
|
||||||
|
@ -19,14 +19,17 @@
|
|||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types, errors
|
from pyrogram.api import functions, types
|
||||||
|
from pyrogram.errors import UserNotParticipant
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class GetChatMember(BaseClient):
|
class GetChatMember(BaseClient):
|
||||||
def get_chat_member(self,
|
def get_chat_member(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str]) -> "pyrogram.ChatMember":
|
user_id: Union[int, str]
|
||||||
|
) -> "pyrogram.ChatMember":
|
||||||
"""Use this method to get information about one member of a chat.
|
"""Use this method to get information about one member of a chat.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -42,7 +45,7 @@ class GetChatMember(BaseClient):
|
|||||||
On success, a :obj:`ChatMember <pyrogram.ChatMember>` object is returned.
|
On success, a :obj:`ChatMember <pyrogram.ChatMember>` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
chat_id = self.resolve_peer(chat_id)
|
chat_id = self.resolve_peer(chat_id)
|
||||||
user_id = self.resolve_peer(user_id)
|
user_id = self.resolve_peer(user_id)
|
||||||
@ -55,10 +58,10 @@ class GetChatMember(BaseClient):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for member in pyrogram.ChatMembers._parse(self, full_chat).chat_members:
|
for member in pyrogram.ChatMembers._parse(self, full_chat).chat_members:
|
||||||
if member.user.id == user_id.user_id:
|
if member.user.is_self:
|
||||||
return member
|
return member
|
||||||
else:
|
else:
|
||||||
raise errors.UserNotParticipant
|
raise UserNotParticipant
|
||||||
elif isinstance(chat_id, types.InputPeerChannel):
|
elif isinstance(chat_id, types.InputPeerChannel):
|
||||||
r = self.send(
|
r = self.send(
|
||||||
functions.channels.GetParticipant(
|
functions.channels.GetParticipant(
|
||||||
|
@ -16,12 +16,17 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
|
from pyrogram.errors import FloodWait
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Filters:
|
class Filters:
|
||||||
ALL = "all"
|
ALL = "all"
|
||||||
@ -33,12 +38,14 @@ class Filters:
|
|||||||
|
|
||||||
|
|
||||||
class GetChatMembers(BaseClient):
|
class GetChatMembers(BaseClient):
|
||||||
def get_chat_members(self,
|
def get_chat_members(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
offset: int = 0,
|
offset: int = 0,
|
||||||
limit: int = 200,
|
limit: int = 200,
|
||||||
query: str = "",
|
query: str = "",
|
||||||
filter: str = Filters.ALL) -> "pyrogram.ChatMembers":
|
filter: str = Filters.ALL
|
||||||
|
) -> "pyrogram.ChatMembers":
|
||||||
"""Use this method to get a chunk of the members list of a chat.
|
"""Use this method to get a chunk of the members list of a chat.
|
||||||
|
|
||||||
You can get up to 200 chat members at once.
|
You can get up to 200 chat members at once.
|
||||||
@ -82,7 +89,7 @@ class GetChatMembers(BaseClient):
|
|||||||
On success, a :obj:`ChatMembers` object is returned.
|
On success, a :obj:`ChatMembers` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` if you used an invalid filter or a chat_id that belongs to a user.
|
``ValueError`` if you used an invalid filter or a chat_id that belongs to a user.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
@ -92,7 +99,7 @@ class GetChatMembers(BaseClient):
|
|||||||
self,
|
self,
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.GetFullChat(
|
functions.messages.GetFullChat(
|
||||||
peer.chat_id
|
chat_id=peer.chat_id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -114,6 +121,8 @@ class GetChatMembers(BaseClient):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Invalid filter \"{}\"".format(filter))
|
raise ValueError("Invalid filter \"{}\"".format(filter))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
return pyrogram.ChatMembers._parse(
|
return pyrogram.ChatMembers._parse(
|
||||||
self,
|
self,
|
||||||
self.send(
|
self.send(
|
||||||
@ -126,5 +135,8 @@ class GetChatMembers(BaseClient):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
except FloodWait as e:
|
||||||
|
log.warning("Sleeping for {}s".format(e.x))
|
||||||
|
time.sleep(e.x)
|
||||||
else:
|
else:
|
||||||
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
||||||
|
@ -23,8 +23,10 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class GetChatMembersCount(BaseClient):
|
class GetChatMembersCount(BaseClient):
|
||||||
def get_chat_members_count(self,
|
def get_chat_members_count(
|
||||||
chat_id: Union[int, str]) -> int:
|
self,
|
||||||
|
chat_id: Union[int, str]
|
||||||
|
) -> int:
|
||||||
"""Use this method to get the number of members in a chat.
|
"""Use this method to get the number of members in a chat.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -35,7 +37,7 @@ class GetChatMembersCount(BaseClient):
|
|||||||
On success, an integer is returned.
|
On success, an integer is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
``ValueError`` if a chat_id belongs to user.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -22,8 +22,10 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class GetChatPreview(BaseClient):
|
class GetChatPreview(BaseClient):
|
||||||
def get_chat_preview(self,
|
def get_chat_preview(
|
||||||
invite_link: str):
|
self,
|
||||||
|
invite_link: str
|
||||||
|
):
|
||||||
"""Use this method to get the preview of a chat using the invite link.
|
"""Use this method to get the preview of a chat using the invite link.
|
||||||
|
|
||||||
This method only returns a chat preview, if you want to join a chat use :meth:`join_chat`
|
This method only returns a chat preview, if you want to join a chat use :meth:`join_chat`
|
||||||
@ -36,7 +38,7 @@ class GetChatPreview(BaseClient):
|
|||||||
Either :obj:`Chat` or :obj:`ChatPreview`, depending on whether you already joined the chat or not.
|
Either :obj:`Chat` or :obj:`ChatPreview`, depending on whether you already joined the chat or not.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` in case of an invalid invite_link.
|
``ValueError`` in case of an invalid invite_link.
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(invite_link)
|
match = self.INVITE_LINK_RE.match(invite_link)
|
||||||
|
@ -21,18 +21,20 @@ import time
|
|||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.api.errors import FloodWait
|
from pyrogram.errors import FloodWait
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class GetDialogs(BaseClient):
|
class GetDialogs(BaseClient):
|
||||||
def get_dialogs(self,
|
def get_dialogs(
|
||||||
|
self,
|
||||||
offset_date: int = 0,
|
offset_date: int = 0,
|
||||||
limit: int = 100,
|
limit: int = 100,
|
||||||
pinned_only: bool = False) -> "pyrogram.Dialogs":
|
pinned_only: bool = False
|
||||||
"""Use this method to get a chunk of the user's dialogs
|
) -> "pyrogram.Dialogs":
|
||||||
|
"""Use this method to get a chunk of the user's dialogs.
|
||||||
|
|
||||||
You can get up to 100 dialogs at once.
|
You can get up to 100 dialogs at once.
|
||||||
For a more convenient way of getting a user's dialogs see :meth:`iter_dialogs`.
|
For a more convenient way of getting a user's dialogs see :meth:`iter_dialogs`.
|
||||||
@ -54,7 +56,7 @@ class GetDialogs(BaseClient):
|
|||||||
On success, a :obj:`Dialogs` object is returned.
|
On success, a :obj:`Dialogs` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
@ -20,6 +20,7 @@ from string import ascii_lowercase
|
|||||||
from typing import Union, Generator
|
from typing import Union, Generator
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
from pyrogram.api import types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
@ -37,11 +38,13 @@ QUERYABLE_FILTERS = (Filters.ALL, Filters.KICKED, Filters.RESTRICTED)
|
|||||||
|
|
||||||
|
|
||||||
class IterChatMembers(BaseClient):
|
class IterChatMembers(BaseClient):
|
||||||
def iter_chat_members(self,
|
def iter_chat_members(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
limit: int = 0,
|
limit: int = 0,
|
||||||
query: str = "",
|
query: str = "",
|
||||||
filter: str = Filters.ALL) -> Generator["pyrogram.ChatMember", None, None]:
|
filter: str = Filters.ALL
|
||||||
|
) -> Generator["pyrogram.ChatMember", None, None]:
|
||||||
"""Use this method to iterate through the members of a chat sequentially.
|
"""Use this method to iterate through the members of a chat sequentially.
|
||||||
|
|
||||||
This convenience method does the same as repeatedly calling :meth:`get_chat_members` in a loop, thus saving you
|
This convenience method does the same as repeatedly calling :meth:`get_chat_members` in a loop, thus saving you
|
||||||
@ -75,13 +78,14 @@ class IterChatMembers(BaseClient):
|
|||||||
A generator yielding :obj:`ChatMember <pyrogram.ChatMember>` objects.
|
A generator yielding :obj:`ChatMember <pyrogram.ChatMember>` objects.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
current = 0
|
current = 0
|
||||||
yielded = set()
|
yielded = set()
|
||||||
queries = [query] if query else QUERIES
|
queries = [query] if query else QUERIES
|
||||||
total = limit or (1 << 31) - 1
|
total = limit or (1 << 31) - 1
|
||||||
limit = min(200, total)
|
limit = min(200, total)
|
||||||
|
resolved_chat_id = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
filter = (
|
filter = (
|
||||||
Filters.RECENT
|
Filters.RECENT
|
||||||
@ -107,6 +111,9 @@ class IterChatMembers(BaseClient):
|
|||||||
if not chat_members:
|
if not chat_members:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if isinstance(resolved_chat_id, types.InputPeerChat):
|
||||||
|
total = len(chat_members)
|
||||||
|
|
||||||
offset += len(chat_members)
|
offset += len(chat_members)
|
||||||
|
|
||||||
for chat_member in chat_members:
|
for chat_member in chat_members:
|
||||||
|
@ -23,9 +23,11 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class IterDialogs(BaseClient):
|
class IterDialogs(BaseClient):
|
||||||
def iter_dialogs(self,
|
def iter_dialogs(
|
||||||
|
self,
|
||||||
offset_date: int = 0,
|
offset_date: int = 0,
|
||||||
limit: int = 0) -> Generator["pyrogram.Dialog", None, None]:
|
limit: int = 0
|
||||||
|
) -> Generator["pyrogram.Dialog", None, None]:
|
||||||
"""Use this method to iterate through a user's dialogs sequentially.
|
"""Use this method to iterate through a user's dialogs sequentially.
|
||||||
|
|
||||||
This convenience method does the same as repeatedly calling :meth:`get_dialogs` in a loop, thus saving you from
|
This convenience method does the same as repeatedly calling :meth:`get_dialogs` in a loop, thus saving you from
|
||||||
@ -44,7 +46,7 @@ class IterDialogs(BaseClient):
|
|||||||
A generator yielding :obj:`Dialog <pyrogram.Dialog>` objects.
|
A generator yielding :obj:`Dialog <pyrogram.Dialog>` objects.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
current = 0
|
current = 0
|
||||||
total = limit or (1 << 31) - 1
|
total = limit or (1 << 31) - 1
|
||||||
|
@ -16,13 +16,16 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class JoinChat(BaseClient):
|
class JoinChat(BaseClient):
|
||||||
def join_chat(self,
|
def join_chat(
|
||||||
chat_id: str):
|
self,
|
||||||
|
chat_id: str
|
||||||
|
):
|
||||||
"""Use this method to join a group chat or channel.
|
"""Use this method to join a group chat or channel.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -30,17 +33,24 @@ class JoinChat(BaseClient):
|
|||||||
Unique identifier for the target chat in form of a *t.me/joinchat/* link or username of the target
|
Unique identifier for the target chat in form of a *t.me/joinchat/* link or username of the target
|
||||||
channel/supergroup (in the format @username).
|
channel/supergroup (in the format @username).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
match = self.INVITE_LINK_RE.match(chat_id)
|
match = self.INVITE_LINK_RE.match(chat_id)
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
return self.send(
|
chat = self.send(
|
||||||
functions.messages.ImportChatInvite(
|
functions.messages.ImportChatInvite(
|
||||||
hash=match.group(1)
|
hash=match.group(1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
if isinstance(chat.chats[0], types.Chat):
|
||||||
|
return pyrogram.Chat._parse_chat_chat(self, chat.chats[0])
|
||||||
|
elif isinstance(chat.chats[0], types.Channel):
|
||||||
|
return pyrogram.Chat._parse_channel_chat(self, chat.chats[0])
|
||||||
else:
|
else:
|
||||||
resolved_peer = self.send(
|
resolved_peer = self.send(
|
||||||
functions.contacts.ResolveUsername(
|
functions.contacts.ResolveUsername(
|
||||||
@ -53,8 +63,10 @@ class JoinChat(BaseClient):
|
|||||||
access_hash=resolved_peer.chats[0].access_hash
|
access_hash=resolved_peer.chats[0].access_hash
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.send(
|
chat = self.send(
|
||||||
functions.channels.JoinChannel(
|
functions.channels.JoinChannel(
|
||||||
channel=channel
|
channel=channel
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return pyrogram.Chat._parse_channel_chat(self, chat.chats[0])
|
||||||
|
@ -24,10 +24,12 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class KickChatMember(BaseClient):
|
class KickChatMember(BaseClient):
|
||||||
def kick_chat_member(self,
|
def kick_chat_member(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
until_date: int = 0) -> Union["pyrogram.Message", bool]:
|
until_date: int = 0
|
||||||
|
) -> Union["pyrogram.Message", bool]:
|
||||||
"""Use this method to kick a user from a group, a supergroup or a channel.
|
"""Use this method to kick a user from a group, a supergroup or a channel.
|
||||||
In the case of supergroups and channels, the user will not be able to return to the group on their own using
|
In the case of supergroups and channels, the user will not be able to return to the group on their own using
|
||||||
invite links, etc., unless unbanned first. You must be an administrator in the chat for this to work and must
|
invite links, etc., unless unbanned first. You must be an administrator in the chat for this to work and must
|
||||||
@ -55,7 +57,7 @@ class KickChatMember(BaseClient):
|
|||||||
On success, either True or a service :obj:`Message <pyrogram.Message>` will be returned (when applicable).
|
On success, either True or a service :obj:`Message <pyrogram.Message>` will be returned (when applicable).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
chat_peer = self.resolve_peer(chat_id)
|
chat_peer = self.resolve_peer(chat_id)
|
||||||
user_peer = self.resolve_peer(user_id)
|
user_peer = self.resolve_peer(user_id)
|
||||||
@ -65,7 +67,7 @@ class KickChatMember(BaseClient):
|
|||||||
functions.channels.EditBanned(
|
functions.channels.EditBanned(
|
||||||
channel=chat_peer,
|
channel=chat_peer,
|
||||||
user_id=user_peer,
|
user_id=user_peer,
|
||||||
banned_rights=types.ChannelBannedRights(
|
banned_rights=types.ChatBannedRights(
|
||||||
until_date=until_date,
|
until_date=until_date,
|
||||||
view_messages=True,
|
view_messages=True,
|
||||||
send_messages=True,
|
send_messages=True,
|
||||||
|
@ -23,9 +23,11 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class LeaveChat(BaseClient):
|
class LeaveChat(BaseClient):
|
||||||
def leave_chat(self,
|
def leave_chat(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
delete: bool = False):
|
delete: bool = False
|
||||||
|
):
|
||||||
"""Use this method to leave a group chat or channel.
|
"""Use this method to leave a group chat or channel.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -37,7 +39,7 @@ class LeaveChat(BaseClient):
|
|||||||
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
Deletes the group chat dialog after leaving (for simple group chats, not supergroups).
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
@ -23,10 +23,12 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class PinChatMessage(BaseClient):
|
class PinChatMessage(BaseClient):
|
||||||
def pin_chat_message(self,
|
def pin_chat_message(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
message_id: int,
|
message_id: int,
|
||||||
disable_notification: bool = None) -> bool:
|
disable_notification: bool = None
|
||||||
|
) -> bool:
|
||||||
"""Use this method to pin a message in a group, channel or your own chat.
|
"""Use this method to pin a message in a group, channel or your own chat.
|
||||||
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin right in
|
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin right in
|
||||||
the supergroup or "can_edit_messages" admin right in the channel.
|
the supergroup or "can_edit_messages" admin right in the channel.
|
||||||
@ -46,7 +48,7 @@ class PinChatMessage(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.UpdatePinnedMessage(
|
functions.messages.UpdatePinnedMessage(
|
||||||
@ -55,3 +57,5 @@ class PinChatMessage(BaseClient):
|
|||||||
silent=disable_notification or None
|
silent=disable_notification or None
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return True
|
||||||
|
@ -23,18 +23,21 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class PromoteChatMember(BaseClient):
|
class PromoteChatMember(BaseClient):
|
||||||
def promote_chat_member(self,
|
def promote_chat_member(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
can_change_info: bool = True,
|
can_change_info: bool = True,
|
||||||
can_post_messages: bool = False,
|
can_post_messages: bool = False,
|
||||||
can_edit_messages: bool = False,
|
can_edit_messages: bool = False,
|
||||||
can_delete_messages: bool = True,
|
can_delete_messages: bool = True,
|
||||||
can_invite_users: bool = True,
|
|
||||||
can_restrict_members: bool = True,
|
can_restrict_members: bool = True,
|
||||||
|
can_invite_users: bool = True,
|
||||||
can_pin_messages: bool = False,
|
can_pin_messages: bool = False,
|
||||||
can_promote_members: bool = False) -> bool:
|
can_promote_members: bool = False
|
||||||
|
) -> bool:
|
||||||
"""Use this method to promote or demote a user in a supergroup or a channel.
|
"""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.
|
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.
|
Pass False for all boolean parameters to demote a user.
|
||||||
|
|
||||||
@ -58,12 +61,12 @@ class PromoteChatMember(BaseClient):
|
|||||||
can_delete_messages (``bool``, *optional*):
|
can_delete_messages (``bool``, *optional*):
|
||||||
Pass True, if the administrator can delete messages of other users.
|
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*):
|
can_restrict_members (``bool``, *optional*):
|
||||||
Pass True, if the administrator can restrict, ban or unban chat members.
|
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*):
|
can_pin_messages (``bool``, *optional*):
|
||||||
Pass True, if the administrator can pin messages, supergroups only.
|
Pass True, if the administrator can pin messages, supergroups only.
|
||||||
|
|
||||||
@ -76,23 +79,21 @@ class PromoteChatMember(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditAdmin(
|
functions.channels.EditAdmin(
|
||||||
channel=self.resolve_peer(chat_id),
|
channel=self.resolve_peer(chat_id),
|
||||||
user_id=self.resolve_peer(user_id),
|
user_id=self.resolve_peer(user_id),
|
||||||
admin_rights=types.ChannelAdminRights(
|
admin_rights=types.ChatAdminRights(
|
||||||
change_info=can_change_info or None,
|
change_info=can_change_info or None,
|
||||||
post_messages=can_post_messages or None,
|
post_messages=can_post_messages or None,
|
||||||
edit_messages=can_edit_messages or None,
|
edit_messages=can_edit_messages or None,
|
||||||
delete_messages=can_delete_messages or None,
|
delete_messages=can_delete_messages or None,
|
||||||
ban_users=can_restrict_members or None,
|
ban_users=can_restrict_members or None,
|
||||||
invite_users=can_invite_users or None,
|
invite_users=can_invite_users or None,
|
||||||
invite_link=can_invite_users or None,
|
|
||||||
pin_messages=can_pin_messages or None,
|
pin_messages=can_pin_messages or None,
|
||||||
add_admins=can_promote_members or None,
|
add_admins=can_promote_members or None,
|
||||||
manage_call=None
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
143
pyrogram/client/methods/chats/restrict_chat.py
Normal file
143
pyrogram/client/methods/chats/restrict_chat.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# 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 functions, types
|
||||||
|
from ...ext import BaseClient
|
||||||
|
from ...types.user_and_chats import Chat
|
||||||
|
|
||||||
|
|
||||||
|
class RestrictChat(BaseClient):
|
||||||
|
def restrict_chat(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
can_send_messages: bool = False,
|
||||||
|
can_send_media_messages: bool = False,
|
||||||
|
can_send_other_messages: bool = False,
|
||||||
|
can_add_web_page_previews: bool = False,
|
||||||
|
can_send_polls: bool = False,
|
||||||
|
can_change_info: bool = False,
|
||||||
|
can_invite_users: bool = False,
|
||||||
|
can_pin_messages: bool = False
|
||||||
|
) -> Chat:
|
||||||
|
"""Use this method to restrict a chat.
|
||||||
|
Pass True for all boolean parameters to lift restrictions from a chat.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (``int`` | ``str``):
|
||||||
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
|
||||||
|
can_send_messages (``bool``, *optional*):
|
||||||
|
Pass True, if the user can send text messages, contacts, locations and venues.
|
||||||
|
|
||||||
|
can_send_media_messages (``bool``, *optional*):
|
||||||
|
Pass 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*):
|
||||||
|
Pass 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*):
|
||||||
|
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
|
||||||
|
|
||||||
|
can_send_polls (``bool``, *optional*):
|
||||||
|
Pass True, if the user can send polls, implies can_send_media_messages.
|
||||||
|
|
||||||
|
can_change_info (``bool``, *optional*):
|
||||||
|
Pass True, if the user can change the chat title, photo and other settings.
|
||||||
|
|
||||||
|
can_invite_users (``bool``, *optional*):
|
||||||
|
Pass True, if the user can invite new users to the chat.
|
||||||
|
|
||||||
|
can_pin_messages (``bool``, *optional*):
|
||||||
|
Pass True, if the user can pin messages.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
|
"""
|
||||||
|
send_messages = True
|
||||||
|
send_media = True
|
||||||
|
send_stickers = True
|
||||||
|
send_gifs = True
|
||||||
|
send_games = True
|
||||||
|
send_inline = True
|
||||||
|
embed_links = True
|
||||||
|
send_polls = True
|
||||||
|
change_info = True
|
||||||
|
invite_users = True
|
||||||
|
pin_messages = True
|
||||||
|
|
||||||
|
if can_send_messages:
|
||||||
|
send_messages = None
|
||||||
|
|
||||||
|
if can_send_media_messages:
|
||||||
|
send_messages = None
|
||||||
|
send_media = None
|
||||||
|
|
||||||
|
if can_send_other_messages:
|
||||||
|
send_messages = None
|
||||||
|
send_media = None
|
||||||
|
send_stickers = None
|
||||||
|
send_gifs = None
|
||||||
|
send_games = None
|
||||||
|
send_inline = None
|
||||||
|
|
||||||
|
if can_add_web_page_previews:
|
||||||
|
send_messages = None
|
||||||
|
send_media = None
|
||||||
|
embed_links = None
|
||||||
|
|
||||||
|
if can_send_polls:
|
||||||
|
send_messages = None
|
||||||
|
send_polls = None
|
||||||
|
|
||||||
|
if can_change_info:
|
||||||
|
change_info = None
|
||||||
|
|
||||||
|
if can_invite_users:
|
||||||
|
invite_users = None
|
||||||
|
|
||||||
|
if can_pin_messages:
|
||||||
|
pin_messages = None
|
||||||
|
|
||||||
|
r = self.send(
|
||||||
|
functions.messages.EditChatDefaultBannedRights(
|
||||||
|
peer=self.resolve_peer(chat_id),
|
||||||
|
banned_rights=types.ChatBannedRights(
|
||||||
|
until_date=0,
|
||||||
|
send_messages=send_messages,
|
||||||
|
send_media=send_media,
|
||||||
|
send_stickers=send_stickers,
|
||||||
|
send_gifs=send_gifs,
|
||||||
|
send_games=send_games,
|
||||||
|
send_inline=send_inline,
|
||||||
|
embed_links=embed_links,
|
||||||
|
send_polls=send_polls,
|
||||||
|
change_info=change_info,
|
||||||
|
invite_users=invite_users,
|
||||||
|
pin_messages=pin_messages
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return Chat._parse_chat(self, r.chats[0])
|
@ -20,20 +20,28 @@ from typing import Union
|
|||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
from ...types.user_and_chats import Chat
|
||||||
|
|
||||||
|
|
||||||
class RestrictChatMember(BaseClient):
|
class RestrictChatMember(BaseClient):
|
||||||
def restrict_chat_member(self,
|
def restrict_chat_member(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str],
|
user_id: Union[int, str],
|
||||||
until_date: int = 0,
|
until_date: int = 0,
|
||||||
can_send_messages: bool = False,
|
can_send_messages: bool = False,
|
||||||
can_send_media_messages: bool = False,
|
can_send_media_messages: bool = False,
|
||||||
can_send_other_messages: bool = False,
|
can_send_other_messages: bool = False,
|
||||||
can_add_web_page_previews: bool = False) -> bool:
|
can_add_web_page_previews: bool = False,
|
||||||
"""Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for
|
can_send_polls: bool = False,
|
||||||
this to work and must have the appropriate admin rights. Pass True for all boolean parameters to lift
|
can_change_info: bool = False,
|
||||||
restrictions from a user.
|
can_invite_users: bool = False,
|
||||||
|
can_pin_messages: bool = False
|
||||||
|
) -> Chat:
|
||||||
|
"""Use this method to restrict a user in a supergroup.
|
||||||
|
|
||||||
|
The bot must be an administrator in the supergroup for this to work and must have the appropriate admin rights.
|
||||||
|
Pass True for all boolean parameters to lift restrictions from a user.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
chat_id (``int`` | ``str``):
|
chat_id (``int`` | ``str``):
|
||||||
@ -60,13 +68,25 @@ class RestrictChatMember(BaseClient):
|
|||||||
implies can_send_media_messages.
|
implies can_send_media_messages.
|
||||||
|
|
||||||
can_add_web_page_previews (``bool``, *optional*):
|
can_add_web_page_previews (``bool``, *optional*):
|
||||||
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages
|
Pass True, if the user may add web page previews to their messages, implies can_send_media_messages.
|
||||||
|
|
||||||
|
can_send_polls (``bool``, *optional*):
|
||||||
|
Pass True, if the user can send polls, implies can_send_media_messages.
|
||||||
|
|
||||||
|
can_change_info (``bool``, *optional*):
|
||||||
|
Pass True, if the user can change the chat title, photo and other settings.
|
||||||
|
|
||||||
|
can_invite_users (``bool``, *optional*):
|
||||||
|
Pass True, if the user can invite new users to the chat.
|
||||||
|
|
||||||
|
can_pin_messages (``bool``, *optional*):
|
||||||
|
Pass True, if the user can pin messages.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True on success.
|
On success, a :obj:`Chat <pyrogram.Chat>` object is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
send_messages = True
|
send_messages = True
|
||||||
send_media = True
|
send_media = True
|
||||||
@ -75,6 +95,10 @@ class RestrictChatMember(BaseClient):
|
|||||||
send_games = True
|
send_games = True
|
||||||
send_inline = True
|
send_inline = True
|
||||||
embed_links = True
|
embed_links = True
|
||||||
|
send_polls = True
|
||||||
|
change_info = True
|
||||||
|
invite_users = True
|
||||||
|
pin_messages = True
|
||||||
|
|
||||||
if can_send_messages:
|
if can_send_messages:
|
||||||
send_messages = None
|
send_messages = None
|
||||||
@ -84,6 +108,7 @@ class RestrictChatMember(BaseClient):
|
|||||||
send_media = None
|
send_media = None
|
||||||
|
|
||||||
if can_send_other_messages:
|
if can_send_other_messages:
|
||||||
|
send_messages = None
|
||||||
send_media = None
|
send_media = None
|
||||||
send_stickers = None
|
send_stickers = None
|
||||||
send_gifs = None
|
send_gifs = None
|
||||||
@ -91,14 +116,28 @@ class RestrictChatMember(BaseClient):
|
|||||||
send_inline = None
|
send_inline = None
|
||||||
|
|
||||||
if can_add_web_page_previews:
|
if can_add_web_page_previews:
|
||||||
|
send_messages = None
|
||||||
send_media = None
|
send_media = None
|
||||||
embed_links = None
|
embed_links = None
|
||||||
|
|
||||||
self.send(
|
if can_send_polls:
|
||||||
|
send_messages = None
|
||||||
|
send_polls = None
|
||||||
|
|
||||||
|
if can_change_info:
|
||||||
|
change_info = None
|
||||||
|
|
||||||
|
if can_invite_users:
|
||||||
|
invite_users = None
|
||||||
|
|
||||||
|
if can_pin_messages:
|
||||||
|
pin_messages = None
|
||||||
|
|
||||||
|
r = self.send(
|
||||||
functions.channels.EditBanned(
|
functions.channels.EditBanned(
|
||||||
channel=self.resolve_peer(chat_id),
|
channel=self.resolve_peer(chat_id),
|
||||||
user_id=self.resolve_peer(user_id),
|
user_id=self.resolve_peer(user_id),
|
||||||
banned_rights=types.ChannelBannedRights(
|
banned_rights=types.ChatBannedRights(
|
||||||
until_date=until_date,
|
until_date=until_date,
|
||||||
send_messages=send_messages,
|
send_messages=send_messages,
|
||||||
send_media=send_media,
|
send_media=send_media,
|
||||||
@ -106,9 +145,13 @@ class RestrictChatMember(BaseClient):
|
|||||||
send_gifs=send_gifs,
|
send_gifs=send_gifs,
|
||||||
send_games=send_games,
|
send_games=send_games,
|
||||||
send_inline=send_inline,
|
send_inline=send_inline,
|
||||||
embed_links=embed_links
|
embed_links=embed_links,
|
||||||
|
send_polls=send_polls,
|
||||||
|
change_info=change_info,
|
||||||
|
invite_users=invite_users,
|
||||||
|
pin_messages=pin_messages
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return True
|
return Chat._parse_chat(self, r.chats[0])
|
||||||
|
@ -23,9 +23,11 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class SetChatDescription(BaseClient):
|
class SetChatDescription(BaseClient):
|
||||||
def set_chat_description(self,
|
def set_chat_description(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
description: str) -> bool:
|
description: str
|
||||||
|
) -> bool:
|
||||||
"""Use this method to change the description of a supergroup or a channel.
|
"""Use this method to change the description of a supergroup or a channel.
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
|
|
||||||
@ -40,20 +42,18 @@ class SetChatDescription(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
|
``ValueError`` if a chat_id doesn't belong to a supergroup or a channel.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
if isinstance(peer, types.InputPeerChannel):
|
if isinstance(peer, (types.InputPeerChannel, types.InputPeerChat)):
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditAbout(
|
functions.messages.EditChatAbout(
|
||||||
channel=peer,
|
peer=peer,
|
||||||
about=description
|
about=description
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif isinstance(peer, types.InputPeerChat):
|
|
||||||
raise ValueError("The chat_id \"{}\" belongs to a basic group".format(chat_id))
|
|
||||||
else:
|
else:
|
||||||
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))
|
||||||
|
|
||||||
|
@ -26,9 +26,11 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class SetChatPhoto(BaseClient):
|
class SetChatPhoto(BaseClient):
|
||||||
def set_chat_photo(self,
|
def set_chat_photo(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
photo: str) -> bool:
|
photo: str
|
||||||
|
) -> bool:
|
||||||
"""Use this method to set a new profile photo for the chat.
|
"""Use this method to set a new profile photo for the chat.
|
||||||
Photos can't be changed for private chats.
|
Photos can't be changed for private chats.
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
@ -48,7 +50,7 @@ class SetChatPhoto(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
``ValueError`` if a chat_id belongs to user.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -23,9 +23,11 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class SetChatTitle(BaseClient):
|
class SetChatTitle(BaseClient):
|
||||||
def set_chat_title(self,
|
def set_chat_title(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
title: str) -> bool:
|
title: str
|
||||||
|
) -> bool:
|
||||||
"""Use this method to change the title of a chat.
|
"""Use this method to change the title of a chat.
|
||||||
Titles can't be changed for private chats.
|
Titles can't be changed for private chats.
|
||||||
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
You must be an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
@ -45,7 +47,7 @@ class SetChatTitle(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
``ValueError`` if a chat_id belongs to user.
|
``ValueError`` if a chat_id belongs to user.
|
||||||
"""
|
"""
|
||||||
peer = self.resolve_peer(chat_id)
|
peer = self.resolve_peer(chat_id)
|
||||||
|
@ -23,9 +23,11 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class UnbanChatMember(BaseClient):
|
class UnbanChatMember(BaseClient):
|
||||||
def unban_chat_member(self,
|
def unban_chat_member(
|
||||||
|
self,
|
||||||
chat_id: Union[int, str],
|
chat_id: Union[int, str],
|
||||||
user_id: Union[int, str]) -> bool:
|
user_id: Union[int, str]
|
||||||
|
) -> bool:
|
||||||
"""Use this method to unban a previously kicked user in a supergroup or channel.
|
"""Use this method to unban a previously kicked user in a supergroup or channel.
|
||||||
The user will **not** return to the group or channel automatically, but will be able to join via link, etc.
|
The user will **not** return to the group or channel automatically, but will be able to join via link, etc.
|
||||||
You must be an administrator for this to work.
|
You must be an administrator for this to work.
|
||||||
@ -42,13 +44,13 @@ class UnbanChatMember(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.channels.EditBanned(
|
functions.channels.EditBanned(
|
||||||
channel=self.resolve_peer(chat_id),
|
channel=self.resolve_peer(chat_id),
|
||||||
user_id=self.resolve_peer(user_id),
|
user_id=self.resolve_peer(user_id),
|
||||||
banned_rights=types.ChannelBannedRights(
|
banned_rights=types.ChatBannedRights(
|
||||||
until_date=0
|
until_date=0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -23,8 +23,10 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class UnpinChatMessage(BaseClient):
|
class UnpinChatMessage(BaseClient):
|
||||||
def unpin_chat_message(self,
|
def unpin_chat_message(
|
||||||
chat_id: Union[int, str]) -> bool:
|
self,
|
||||||
|
chat_id: Union[int, str]
|
||||||
|
) -> bool:
|
||||||
"""Use this method to unpin a message in a group, channel or your own chat.
|
"""Use this method to unpin a message in a group, channel or your own chat.
|
||||||
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin
|
You must be an administrator in the chat for this to work and must have the "can_pin_messages" admin
|
||||||
right in the supergroup or "can_edit_messages" admin right in the channel.
|
right in the supergroup or "can_edit_messages" admin right in the channel.
|
||||||
@ -37,7 +39,7 @@ class UnpinChatMessage(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
self.send(
|
self.send(
|
||||||
functions.messages.UpdatePinnedMessage(
|
functions.messages.UpdatePinnedMessage(
|
||||||
|
61
pyrogram/client/methods/chats/update_chat_username.py
Normal file
61
pyrogram/client/methods/chats/update_chat_username.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
# 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 functions, types
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateChatUsername(BaseClient):
|
||||||
|
def update_chat_username(
|
||||||
|
self,
|
||||||
|
chat_id: Union[int, str],
|
||||||
|
username: Union[str, None]
|
||||||
|
) -> bool:
|
||||||
|
"""Use this method to update a channel or a supergroup username.
|
||||||
|
|
||||||
|
To update your own username (for users only, not bots) you can use :meth:`update_username`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id (``int`` | ``str``)
|
||||||
|
Unique identifier (int) or username (str) of the target chat.
|
||||||
|
username (``str`` | ``None``):
|
||||||
|
Username to set. Pass "" (empty string) or None to remove the username.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True on success.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
|
``ValueError`` if a chat_id belongs to a user or chat.
|
||||||
|
"""
|
||||||
|
|
||||||
|
peer = self.resolve_peer(chat_id)
|
||||||
|
|
||||||
|
if isinstance(peer, types.InputPeerChannel):
|
||||||
|
return bool(
|
||||||
|
self.send(
|
||||||
|
functions.channels.UpdateUsername(
|
||||||
|
channel=peer,
|
||||||
|
username=username or ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise ValueError("The chat_id \"{}\" belongs to a user or chat".format(chat_id))
|
@ -24,8 +24,10 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class AddContacts(BaseClient):
|
class AddContacts(BaseClient):
|
||||||
def add_contacts(self,
|
def add_contacts(
|
||||||
contacts: List["pyrogram.InputPhoneContact"]):
|
self,
|
||||||
|
contacts: List["pyrogram.InputPhoneContact"]
|
||||||
|
):
|
||||||
"""Use this method to add contacts to your Telegram address book.
|
"""Use this method to add contacts to your Telegram address book.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -36,7 +38,7 @@ class AddContacts(BaseClient):
|
|||||||
On success, the added contacts are returned.
|
On success, the added contacts are returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
imported_contacts = self.send(
|
imported_contacts = self.send(
|
||||||
functions.contacts.ImportContacts(
|
functions.contacts.ImportContacts(
|
||||||
|
@ -19,14 +19,16 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
from pyrogram.api.errors import PeerIdInvalid
|
from pyrogram.errors import PeerIdInvalid
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class DeleteContacts(BaseClient):
|
class DeleteContacts(BaseClient):
|
||||||
def delete_contacts(self,
|
def delete_contacts(
|
||||||
ids: List[int]):
|
self,
|
||||||
"""Use this method to delete contacts from your Telegram address book
|
ids: List[int]
|
||||||
|
):
|
||||||
|
"""Use this method to delete contacts from your Telegram address book.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
ids (List of ``int``):
|
ids (List of ``int``):
|
||||||
@ -37,7 +39,7 @@ class DeleteContacts(BaseClient):
|
|||||||
True on success.
|
True on success.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
contacts = []
|
contacts = []
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import time
|
|||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import functions
|
from pyrogram.api import functions
|
||||||
from pyrogram.api.errors import FloodWait
|
from pyrogram.errors import FloodWait
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -35,11 +35,11 @@ class GetContacts(BaseClient):
|
|||||||
On success, a list of :obj:`User` objects is returned.
|
On success, a list of :obj:`User` objects is returned.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
|
:class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error.
|
||||||
"""
|
"""
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
contacts = self.send(functions.contacts.GetContacts(0))
|
contacts = self.send(functions.contacts.GetContacts(hash=0))
|
||||||
except FloodWait as e:
|
except FloodWait as e:
|
||||||
log.warning("get_contacts flood: waiting {} seconds".format(e.x))
|
log.warning("get_contacts flood: waiting {} seconds".format(e.x))
|
||||||
time.sleep(e.x)
|
time.sleep(e.x)
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
from .on_callback_query import OnCallbackQuery
|
from .on_callback_query import OnCallbackQuery
|
||||||
from .on_deleted_messages import OnDeletedMessages
|
from .on_deleted_messages import OnDeletedMessages
|
||||||
from .on_disconnect import OnDisconnect
|
from .on_disconnect import OnDisconnect
|
||||||
|
from .on_inline_query import OnInlineQuery
|
||||||
from .on_message import OnMessage
|
from .on_message import OnMessage
|
||||||
from .on_raw_update import OnRawUpdate
|
from .on_raw_update import OnRawUpdate
|
||||||
from .on_user_status import OnUserStatus
|
from .on_user_status import OnUserStatus
|
||||||
@ -30,6 +31,7 @@ class Decorators(
|
|||||||
OnCallbackQuery,
|
OnCallbackQuery,
|
||||||
OnRawUpdate,
|
OnRawUpdate,
|
||||||
OnDisconnect,
|
OnDisconnect,
|
||||||
OnUserStatus
|
OnUserStatus,
|
||||||
|
OnInlineQuery
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -25,19 +25,13 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class OnCallbackQuery(BaseClient):
|
class OnCallbackQuery(BaseClient):
|
||||||
def on_callback_query(self=None,
|
def on_callback_query(
|
||||||
|
self=None,
|
||||||
filters=None,
|
filters=None,
|
||||||
group: int = 0) -> callable:
|
group: int = 0
|
||||||
"""Use this decorator to automatically register a function for handling
|
) -> callable:
|
||||||
callback queries. This does the same thing as :meth:`add_handler` using the
|
"""Use this decorator to automatically register a function for handling callback queries.
|
||||||
:class:`CallbackQueryHandler`.
|
This does the same thing as :meth:`add_handler` using the :class:`CallbackQueryHandler`.
|
||||||
|
|
||||||
.. note::
|
|
||||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
|
||||||
|
|
||||||
To reference your own function after it has been decorated, you need to access
|
|
||||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
|
||||||
first element in the tuple.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
@ -25,19 +25,13 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class OnDeletedMessages(BaseClient):
|
class OnDeletedMessages(BaseClient):
|
||||||
def on_deleted_messages(self=None,
|
def on_deleted_messages(
|
||||||
|
self=None,
|
||||||
filters=None,
|
filters=None,
|
||||||
group: int = 0) -> callable:
|
group: int = 0
|
||||||
"""Use this decorator to automatically register a function for handling
|
) -> callable:
|
||||||
deleted messages. This does the same thing as :meth:`add_handler` using the
|
"""Use this decorator to automatically register a function for handling deleted messages.
|
||||||
:class:`DeletedMessagesHandler`.
|
This does the same thing as :meth:`add_handler` using the :class:`DeletedMessagesHandler`.
|
||||||
|
|
||||||
.. note::
|
|
||||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
|
||||||
|
|
||||||
To reference your own function after it has been decorated, you need to access
|
|
||||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
|
||||||
first element in the tuple.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
@ -23,9 +23,8 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
class OnDisconnect(BaseClient):
|
class OnDisconnect(BaseClient):
|
||||||
def on_disconnect(self=None) -> callable:
|
def on_disconnect(self=None) -> callable:
|
||||||
"""Use this decorator to automatically register a function for handling
|
"""Use this decorator to automatically register a function for handling disconnections.
|
||||||
disconnections. This does the same thing as :meth:`add_handler` using the
|
This does the same thing as :meth:`add_handler` using the :class:`DisconnectHandler`.
|
||||||
:class:`DisconnectHandler`.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func: callable) -> Handler:
|
def decorator(func: callable) -> Handler:
|
||||||
|
59
pyrogram/client/methods/decorators/on_inline_query.py
Normal file
59
pyrogram/client/methods/decorators/on_inline_query.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 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 Tuple
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from pyrogram.client.filters.filter import Filter
|
||||||
|
from pyrogram.client.handlers.handler import Handler
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class OnInlineQuery(BaseClient):
|
||||||
|
def on_inline_query(
|
||||||
|
self=None,
|
||||||
|
filters=None,
|
||||||
|
group: int = 0
|
||||||
|
) -> callable:
|
||||||
|
"""Use this decorator to automatically register a function for handling inline queries.
|
||||||
|
This does the same thing as :meth:`add_handler` using the :class:`InlineQueryHandler`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
Pass one or more filters to allow only a subset of inline queries to be passed
|
||||||
|
in your function.
|
||||||
|
|
||||||
|
group (``int``, *optional*):
|
||||||
|
The group identifier, defaults to 0.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(func: callable) -> Tuple[Handler, int]:
|
||||||
|
if isinstance(func, tuple):
|
||||||
|
func = func[0].callback
|
||||||
|
|
||||||
|
handler = pyrogram.InlineQueryHandler(func, filters)
|
||||||
|
|
||||||
|
if isinstance(self, Filter):
|
||||||
|
return pyrogram.InlineQueryHandler(func, self), group if filters is None else filters
|
||||||
|
|
||||||
|
if self is not None:
|
||||||
|
self.add_handler(handler, group)
|
||||||
|
|
||||||
|
return handler, group
|
||||||
|
|
||||||
|
return decorator
|
@ -25,19 +25,13 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class OnMessage(BaseClient):
|
class OnMessage(BaseClient):
|
||||||
def on_message(self=None,
|
def on_message(
|
||||||
|
self=None,
|
||||||
filters=None,
|
filters=None,
|
||||||
group: int = 0) -> callable:
|
group: int = 0
|
||||||
"""Use this decorator to automatically register a function for handling
|
) -> callable:
|
||||||
messages. This does the same thing as :meth:`add_handler` using the
|
"""Use this decorator to automatically register a function for handling messages.
|
||||||
:class:`MessageHandler`.
|
This does the same thing as :meth:`add_handler` using the :class:`MessageHandler`.
|
||||||
|
|
||||||
.. note::
|
|
||||||
This decorator will wrap your defined function in a tuple consisting of *(Handler, group)*.
|
|
||||||
|
|
||||||
To reference your own function after it has been decorated, you need to access
|
|
||||||
*my_function[0].callback*, that is, the *callback* field of Handler object which is the the
|
|
||||||
first element in the tuple.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
filters (:obj:`Filters <pyrogram.Filters>`):
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user