Merge branch 'develop' into inline-mode

# Conflicts:
#	compiler/api/compiler.py
#	compiler/error/source/400_BAD_REQUEST.tsv
#	pyrogram/__init__.py
#	pyrogram/client/dispatcher/dispatcher.py
#	pyrogram/client/ext/utils.py
#	pyrogram/client/methods/bots/__init__.py
#	pyrogram/client/types/__init__.py
This commit is contained in:
Dan 2019-03-21 17:40:49 +01:00
commit acbbfabb27
267 changed files with 12512 additions and 3959 deletions

2
NOTICE
View File

@ -1,5 +1,5 @@
Pyrogram - Telegram MTProto API Client Library for Python
Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
This file is part of Pyrogram.

View File

@ -17,18 +17,24 @@ Pyrogram
app.run()
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for building
custom Telegram applications that interact with the MTProto API as both User and Bot.
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and C.
It enables you to easily create custom apps using both user and bot identities (bot API alternative) via the `MTProto API`_.
`Pyrogram in fully-asynchronous mode is also available » <https://github.com/pyrogram/pyrogram/issues/181>`_
`Working PoC of Telegram voice calls using Pyrogram » <https://github.com/bakatrouble/pytgvoip>`_
Features
--------
- **Easy to use**: You can easily install Pyrogram using pip and start building your app right away.
- **High-level**: The low-level details of MTProto are abstracted and automatically handled.
- **Easy**: You can install Pyrogram with pip and start building your applications right away.
- **Elegant**: Low-level details are abstracted and re-presented in a much nicer and easier way.
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
- **Updated** to the latest Telegram API version, currently Layer 82 on top of MTProto 2.0.
- **Documented**: The Pyrogram API is well documented and resembles the Telegram Bot API.
- **Full API**, allowing to execute any advanced action an official client is able to do, and more.
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
- **Updated**, to the latest Telegram API version, currently Layer 95 on top of `MTProto 2.0`_.
- **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.
Requirements
------------
@ -43,11 +49,11 @@ Installing
pip3 install pyrogram
Getting Started
---------------
Resources
---------
- The Docs contain lots of resources to help you getting started with Pyrogram: https://docs.pyrogram.ml.
- Reading Examples_ in this repository is also a good way for learning how things work.
- Reading `Examples in this repository`_ is also a good way for learning how Pyrogram works.
- Seeking extra help? Don't be shy, come join and ask our Community_!
- For other requests you can send an Email_ or a Message_.
@ -61,17 +67,19 @@ and documentation. Any help is appreciated!
Copyright & License
-------------------
- Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
- Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
- Licensed under the terms of the `GNU Lesser General Public License v3 or later (LGPLv3+)`_
.. _`Telegram`: https://telegram.org/
.. _`MTProto API`: https://core.telegram.org/api#telegram-api
.. _`Telegram API key`: https://docs.pyrogram.ml/start/ProjectSetup#api-keys
.. _`Community`: https://t.me/PyrogramChat
.. _`Examples`: https://github.com/pyrogram/pyrogram/tree/master/examples
.. _`Examples in this repository`: https://github.com/pyrogram/pyrogram/tree/master/examples
.. _`GitHub`: https://github.com/pyrogram/pyrogram/issues
.. _`Email`: admin@pyrogram.ml
.. _`Message`: https://t.me/haskell
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
.. _`MTProto 2.0`: https://core.telegram.org/mtproto
.. _`GNU Lesser General Public License v3 or later (LGPLv3+)`: COPYING.lesser
.. |header| raw:: html
@ -83,28 +91,28 @@ Copyright & License
</h1>
<p align="center">
<b>Telegram MTProto API Client Library for Python</b>
<b>Telegram MTProto API Framework for Python</b>
<br>
<a href="https://github.com/pyrogram/pyrogram/releases/latest">
Download
</a>
<a href="https://docs.pyrogram.ml">
Documentation
</a>
<a href="https://github.com/pyrogram/pyrogram/releases">
Changelog
</a>
<a href="https://t.me/PyrogramChat">
Community
</a>
<br>
<a href="compiler/api/source/main_api.tl">
<img src="https://img.shields.io/badge/schema-layer%2082-eda738.svg?longCache=true&colorA=262b30"
<img src="https://img.shields.io/badge/schema-layer%2095-eda738.svg?longCache=true&colorA=262b30"
alt="Schema Layer">
</a>
<a href="https://github.com/pyrogram/tgcrypto">
<img src="https://img.shields.io/badge/tgcrypto-v1.1.1-eda738.svg?longCache=true&colorA=262b30"
alt="TgCrypto">
alt="TgCrypto Version">
</a>
</p>
@ -112,12 +120,12 @@ Copyright & License
:target: https://pyrogram.ml
:alt: Pyrogram
.. |description| replace:: **Telegram MTProto API Client Library for Python**
.. |description| replace:: **Telegram MTProto API Framework for Python**
.. |scheme| image:: "https://img.shields.io/badge/SCHEME-LAYER%2082-eda738.svg?longCache=true&style=for-the-badge&colorA=262b30"
.. |schema| image:: https://img.shields.io/badge/schema-layer%2095-eda738.svg?longCache=true&colorA=262b30
:target: compiler/api/source/main_api.tl
:alt: Scheme Layer
:alt: Schema Layer
.. |tgcrypto| image:: "https://img.shields.io/badge/TGCRYPTO-V1.1.1-eda738.svg?longCache=true&style=for-the-badge&colorA=262b30"
.. |tgcrypto| image:: https://img.shields.io/badge/tgcrypto-v1.1.1-eda738.svg?longCache=true&colorA=262b30
:target: https://github.com/pyrogram/tgcrypto
:alt: TgCrypto
:alt: TgCrypto Version

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -26,7 +26,7 @@ NOTICE_PATH = "NOTICE"
SECTION_RE = re.compile(r"---(\w+)---")
LAYER_RE = re.compile(r"//\sLAYER\s(\d+)")
COMBINATOR_RE = re.compile(r"^([\w.]+)#([0-9a-f]+)\s(?:.*)=\s([\w<>.]+);(?: // Docs: (.+))?$", re.MULTILINE)
ARGS_RE = re.compile("[^{](\w+):([\w?!.<>]+)")
ARGS_RE = re.compile("[^{](\w+):([\w?!.<>#]+)")
FLAGS_RE = re.compile(r"flags\.(\d+)\?")
FLAGS_RE_2 = re.compile(r"flags\.(\d+)\?([\w<>.]+)")
FLAGS_RE_3 = re.compile(r"flags:#")
@ -171,8 +171,8 @@ def start():
shutil.rmtree("{}/functions".format(DESTINATION), ignore_errors=True)
with open("{}/source/auth_key.tl".format(HOME), encoding="utf-8") as auth, \
open("{}/source/sys_msgs.tl".format(HOME), encoding="utf-8") as system, \
open("{}/source/main_api.tl".format(HOME), encoding="utf-8") as api:
open("{}/source/sys_msgs.tl".format(HOME), encoding="utf-8") as system, \
open("{}/source/main_api.tl".format(HOME), encoding="utf-8") as api:
schema = (auth.read() + system.read() + api.read()).splitlines()
with open("{}/template/mtproto.txt".format(HOME), encoding="utf-8") as f:
@ -287,18 +287,23 @@ def start():
sorted_args = sort_args(c.args)
arguments = ", " + ", ".join(
[get_argument_type(i) for i in sorted_args]
) if c.args else ""
arguments = (
", "
+ ("*, " if c.args else "")
+ (", ".join([get_argument_type(i) for i in sorted_args if i != ("flags", "#")]) if c.args else "")
)
fields = "\n ".join(
["self.{0} = {0} # {1}".format(i[0], i[1]) for i in c.args]
["self.{0} = {0} # {1}".format(i[0], i[1]) for i in c.args if i != ("flags", "#")]
) if c.args else "pass"
docstring_args = []
docs = c.docs.split("|")[1:] if c.docs else None
for i, arg in enumerate(sorted_args):
if arg == ("flags", "#"):
continue
arg_name, arg_type = arg
is_optional = FLAGS_RE.match(arg_type)
flag_number = is_optional.group(1) if is_optional else -1
@ -338,28 +343,31 @@ def start():
if references:
docstring_args += "\n\n See Also:\n This object can be returned by " + references + "."
if c.has_flags:
write_flags = []
for i in c.args:
flag = FLAGS_RE.match(i[1])
if flag:
write_flags.append("flags |= (1 << {}) if self.{} is not None else 0".format(flag.group(1), i[0]))
write_flags = "\n ".join([
"flags = 0",
"\n ".join(write_flags),
"b.write(Int(flags))"
])
else:
write_flags = "# No flags"
read_flags = "flags = Int.read(b)" if c.has_flags else "# No flags"
write_types = read_types = ""
write_types = read_types = "" if c.has_flags else "# No flags\n "
for arg_name, arg_type in c.args:
flag = FLAGS_RE_2.findall(arg_type)
if arg_name == "flags" and arg_type == "#":
write_flags = []
for i in c.args:
flag = FLAGS_RE.match(i[1])
if flag:
write_flags.append(
"flags |= (1 << {}) if self.{} is not None else 0".format(flag.group(1), i[0]))
write_flags = "\n ".join([
"flags = 0",
"\n ".join(write_flags),
"b.write(Int(flags))\n "
])
write_types += write_flags
read_types += "flags = Int.read(b)\n "
continue
if flag:
index, flag_type = flag[0]
@ -448,11 +456,13 @@ def start():
object_id=c.id,
arguments=arguments,
fields=fields,
read_flags=read_flags,
read_types=read_types,
write_flags=write_flags,
write_types=write_types,
return_arguments=", ".join([i[0] for i in sorted_args])
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)
)
)
@ -475,40 +485,6 @@ def start():
f.write("\n 0x3072cfa1: \"pyrogram.api.core.GzipPacked\",")
f.write("\n 0x5bb8e511: \"pyrogram.api.core.Message\",")
f.write("\n 0xb0700000: \"pyrogram.client.types.Update\",")
f.write("\n 0xb0700001: \"pyrogram.client.types.User\",")
f.write("\n 0xb0700002: \"pyrogram.client.types.Chat\",")
f.write("\n 0xb0700003: \"pyrogram.client.types.Message\",")
f.write("\n 0xb0700004: \"pyrogram.client.types.MessageEntity\",")
f.write("\n 0xb0700005: \"pyrogram.client.types.PhotoSize\",")
f.write("\n 0xb0700006: \"pyrogram.client.types.Audio\",")
f.write("\n 0xb0700007: \"pyrogram.client.types.Document\",")
f.write("\n 0xb0700008: \"pyrogram.client.types.Video\",")
f.write("\n 0xb0700009: \"pyrogram.client.types.Voice\",")
f.write("\n 0xb0700010: \"pyrogram.client.types.VideoNote\",")
f.write("\n 0xb0700011: \"pyrogram.client.types.Contact\",")
f.write("\n 0xb0700012: \"pyrogram.client.types.Location\",")
f.write("\n 0xb0700013: \"pyrogram.client.types.Venue\",")
f.write("\n 0xb0700014: \"pyrogram.client.types.UserProfilePhotos\",")
f.write("\n 0xb0700015: \"pyrogram.client.types.ChatPhoto\",")
f.write("\n 0xb0700016: \"pyrogram.client.types.ChatMember\",")
f.write("\n 0xb0700017: \"pyrogram.client.types.Sticker\",")
f.write("\n 0xb0700018: \"pyrogram.client.types.bots.ForceReply\",")
f.write("\n 0xb0700019: \"pyrogram.client.types.bots.InlineKeyboardButton\",")
f.write("\n 0xb0700020: \"pyrogram.client.types.bots.InlineKeyboardMarkup\",")
f.write("\n 0xb0700021: \"pyrogram.client.types.bots.KeyboardButton\",")
f.write("\n 0xb0700022: \"pyrogram.client.types.bots.ReplyKeyboardMarkup\",")
f.write("\n 0xb0700023: \"pyrogram.client.types.bots.ReplyKeyboardRemove\",")
f.write("\n 0xb0700024: \"pyrogram.client.types.CallbackQuery\",")
f.write("\n 0xb0700025: \"pyrogram.client.types.Animation\",")
f.write("\n 0xb0700026: \"pyrogram.client.types.Messages\",")
f.write("\n 0xb0700027: \"pyrogram.client.types.Photo\",")
f.write("\n 0xb0700028: \"pyrogram.client.types.Dialog\",")
f.write("\n 0xb0700029: \"pyrogram.client.types.Dialogs\",")
f.write("\n 0xb0700030: \"pyrogram.client.types.ChatMembers\",")
f.write("\n 0xb0700031: \"pyrogram.client.types.UserStatus\",")
f.write("\n 0xb0700032: \"pyrogram.client.types.InlineQuery\"")
f.write("\n}\n")
for k, v in namespaces.items():

View File

@ -45,7 +45,8 @@ inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = In
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
inputMediaGeoLive#7b1a118f geo_point:InputGeoPoint period:int = InputMedia;
inputMediaGeoLive#ce4e82fd flags:# stopped:flags.0?true geo_point:InputGeoPoint period:flags.1?int = InputMedia;
inputMediaPoll#6b3765b poll:Poll = InputMedia;
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
inputChatUploadedPhoto#927c55b4 file:InputFile = InputChatPhoto;
@ -55,16 +56,14 @@ inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
inputPhotoEmpty#1cd7bf0d = InputPhoto;
inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#430f0724 id:long access_hash:long version:int = InputFileLocation;
inputDocumentFileLocation#196683d9 id:long access_hash:long file_reference:bytes = InputFileLocation;
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
inputTakeoutFileLocation#29be5899 = InputFileLocation;
inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent;
peerUser#9db1bc6d user_id:int = Peer;
peerChat#bad0e5bb chat_id:int = Peer;
peerChannel#bddde532 channel_id:int = Peer;
@ -81,10 +80,10 @@ storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
fileLocation#91d11eb dc_id:int volume_id:long local_id:int secret:long file_reference:bytes = FileLocation;
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;
userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
@ -97,13 +96,13 @@ userStatusLastWeek#7bf09fc = UserStatus;
userStatusLastMonth#77ebc742 = UserStatus;
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;
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;
chatFull#2e02a614 id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:ExportedChatInvite bot_info:Vector<BotInfo> = ChatFull;
channelFull#76af5481 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?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 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;
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;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
@ -116,7 +115,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
messageEmpty#83e5de54 id:int = Message;
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
message#44f9b43d flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true id:int from_id:flags.8?int to_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to_msg_id:flags.3?int date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long = Message;
messageService#9e19a1f6 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true id:int from_id:flags.8?int to_id:Peer reply_to_msg_id:flags.3?int date:int action:MessageAction = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@ -130,6 +129,7 @@ messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:str
messageMediaGame#fdb19008 game:Game = MessageMedia;
messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
messageMediaGeoLive#7c3c2609 geo:GeoPoint period:int = MessageMedia;
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
messageActionEmpty#b6aef7b0 = MessageAction;
messageActionChatCreate#a6638b9a title:string users:Vector<int> = MessageAction;
@ -153,15 +153,17 @@ messageActionCustomAction#fae69f56 message:string = MessageAction;
messageActionBotAllowed#abe9affe domain:string = MessageAction;
messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:SecureCredentialsEncrypted = MessageAction;
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
messageActionContactSignUp#f3f25f76 = MessageAction;
dialog#e4def5db flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage = Dialog;
photoEmpty#2331b22d id:long = Photo;
photo#9288dd29 flags:# has_stickers:flags.0?true id:long access_hash:long date:int sizes:Vector<PhotoSize> = Photo;
photo#9c477dd8 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> = Photo;
photoSizeEmpty#e17e23c type:string = 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;
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
@ -177,6 +179,7 @@ auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorizat
inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
inputNotifyUsers#193b4417 = InputNotifyPeer;
inputNotifyChats#4a95e84e = InputNotifyPeer;
inputNotifyBroadcasts#b1db7c7e = InputNotifyPeer;
inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = InputPeerNotifySettings;
@ -184,15 +187,16 @@ peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bo
peerSettings#818426cd flags:# report_spam:flags.0?true = PeerSettings;
wallPaper#ccb03657 id:int title:string sizes:Vector<PhotoSize> color:int = WallPaper;
wallPaperSolid#63117f24 id:int title:string bg_color:int 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;
inputReportReasonSpam#58dbcab8 = ReportReason;
inputReportReasonViolence#1e22c78d = ReportReason;
inputReportReasonPornography#2e59d922 = ReportReason;
inputReportReasonChildAbuse#adf44ee3 = ReportReason;
inputReportReasonOther#e1746d0a text:string = ReportReason;
inputReportReasonCopyright#9b89f93a = ReportReason;
userFull#f220f3f flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo common_chats_count:int = UserFull;
userFull#8ea4a881 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true user:User about:flags.1?string link:contacts.Link profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int = UserFull;
contact#f911c994 user_id:int mutual:Bool = Contact;
@ -217,8 +221,8 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
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.channelMessages#99262e37 flags:# pts:int 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.messagesNotModified#74535f21 count:int = messages.Messages;
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
@ -254,7 +258,6 @@ updateChatParticipants#7761198 participants:ChatParticipants = Update;
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
updateUserPhoto#95313b0c user_id:int date:int photo:UserProfilePhoto previous:Bool = Update;
updateContactRegistered#2575bbb9 user_id:int date:int = Update;
updateContactLink#9d2e67c5 user_id:int my_link:ContactLink foreign_link:ContactLink = Update;
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
@ -278,7 +281,6 @@ updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count: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;
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;
updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update;
updateStickerSetsOrder#bb2d201 flags:# masks:flags.0?true order:Vector<long> = Update;
@ -305,13 +307,17 @@ updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Upd
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
updateBotPrecheckoutQuery#5d2f3aa9 flags:# query_id:long user_id:int payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string currency:string total_amount:long = Update;
updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
updateLangPackTooLong#10c2404b = Update;
updateLangPackTooLong#46560264 lang_code:string = Update;
updateLangPack#56022f4d difference:LangPackDifference = Update;
updateFavedStickers#e511996d = Update;
updateChannelReadMessagesContents#89893b45 channel_id:int messages:Vector<int> = Update;
updateContactsReset#7084a7be = Update;
updateChannelAvailableMessages#70db6837 channel_id:int available_min_id:int = Update;
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
updateChatPinnedMessage#22893b26 chat_id:int id:int = 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;
@ -338,11 +344,11 @@ upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes
dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
config#3213dbba flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int = Config;
config#e6ca25f6 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;
help.appUpdate#8987f311 id:int critical:Bool url:string text:string = help.AppUpdate;
help.appUpdate#1da7158f flags:# popup:flags.0?true id:int version:string text:string entities:Vector<MessageEntity> document:flags.1?Document url:flags.2?string = help.AppUpdate;
help.noAppUpdate#c45a6536 = help.AppUpdate;
help.inviteText#18cb9f78 message:string = help.InviteText;
@ -373,16 +379,17 @@ messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage;
messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage;
inputDocumentEmpty#72f0eaae = InputDocument;
inputDocument#18798952 id:long access_hash:long = InputDocument;
inputDocument#1abfb575 id:long access_hash:long file_reference:bytes = InputDocument;
documentEmpty#36f8c871 id:long = Document;
document#87232bc7 id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int version: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;
notifyPeer#9fd40bd8 peer:Peer = NotifyPeer;
notifyUsers#b4c83b4c = NotifyPeer;
notifyChats#c007cec3 = NotifyPeer;
notifyBroadcasts#d612e8ef = NotifyPeer;
sendMessageTypingAction#16bf744e = SendMessageAction;
sendMessageCancelAction#fd5ec8f5 = SendMessageAction;
@ -403,10 +410,12 @@ contacts.found#b3134d9d my_results:Vector<Peer> results:Vector<Peer> chats:Vecto
inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
inputPrivacyKeyChatInvite#bdfb0426 = InputPrivacyKey;
inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
privacyKeyChatInvite#500e6dfa = PrivacyKey;
privacyKeyPhoneCall#3d662b7b = PrivacyKey;
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
@ -454,16 +463,15 @@ webPagePending#c586da1c id:long date:int = WebPage;
webPage#5f07b4bc flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page = WebPage;
webPageNotModified#85849473 = WebPage;
authorization#7bf2e6f6 hash:long flags:int device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
account.noPassword#5ea182f6 new_salt:bytes new_secure_salt:bytes secure_random:bytes email_unconfirmed_pattern:string = account.Password;
account.password#ca39b447 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true current_salt:bytes new_salt:bytes new_secure_salt:bytes secure_random:bytes hint:string email_unconfirmed_pattern:string = account.Password;
account.password#ad2641f8 flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes = account.Password;
account.passwordSettings#7bd9c3f1 email:string secure_salt:bytes secure_secret:bytes secure_secret_id:long = account.PasswordSettings;
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
account.passwordInputSettings#21ffa60d flags:# new_salt:flags.0?bytes new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_salt:flags.2?bytes new_secure_secret:flags.2?bytes new_secure_secret_id:flags.2?long = account.PasswordInputSettings;
account.passwordInputSettings#c23727c9 flags:# new_algo:flags.0?PasswordKdfAlgo new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_settings:flags.2?SecureSecretSettings = account.PasswordInputSettings;
auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
@ -536,8 +544,8 @@ channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:
channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant;
channelParticipantSelf#a3289a6d user_id:int inviter_id:int date: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;
channelParticipantBanned#222c1886 flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChannelBannedRights = 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#1c0facaf flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant;
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
@ -545,6 +553,7 @@ channelParticipantsKicked#a3b54985 q:string = ChannelParticipantsFilter;
channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
channelParticipantsBanned#1427a5e1 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.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
@ -663,6 +672,12 @@ textFixed#6c3f19b9 text:RichText = RichText;
textUrl#3c2884c1 text:RichText url:string webpage_id:long = RichText;
textEmail#de5a0dd6 text:RichText email:string = RichText;
textConcat#7e6260d7 texts:Vector<RichText> = RichText;
textSubscript#ed6a8504 text:RichText = RichText;
textSuperscript#c7fb5e01 text:RichText = RichText;
textMarked#34b8621 text:RichText = RichText;
textPhone#1ccb966a text:RichText phone:string = RichText;
textImage#81ccf4f document_id:long w:int h:int = RichText;
textAnchor#35553762 text:RichText name:string = RichText;
pageBlockUnsupported#13567e8a = PageBlock;
pageBlockTitle#70abc3fd text:RichText = PageBlock;
@ -675,21 +690,24 @@ pageBlockPreformatted#c070d93e text:RichText language:string = PageBlock;
pageBlockFooter#48870999 text:RichText = PageBlock;
pageBlockDivider#db20b188 = PageBlock;
pageBlockAnchor#ce0d37b0 name:string = PageBlock;
pageBlockList#3a58c7f4 ordered:Bool items:Vector<RichText> = PageBlock;
pageBlockList#e4e88011 items:Vector<PageListItem> = PageBlock;
pageBlockBlockquote#263d7c26 text:RichText caption:RichText = PageBlock;
pageBlockPullquote#4f4456d3 text:RichText caption:RichText = PageBlock;
pageBlockPhoto#e9c69982 photo_id:long caption:RichText = PageBlock;
pageBlockVideo#d9d71866 flags:# autoplay:flags.0?true loop:flags.1?true video_id:long caption:RichText = PageBlock;
pageBlockPhoto#1759c560 flags:# photo_id:long caption:PageCaption url:flags.0?string webpage_id:flags.0?long = PageBlock;
pageBlockVideo#7c8fe7b6 flags:# autoplay:flags.0?true loop:flags.1?true video_id:long caption:PageCaption = PageBlock;
pageBlockCover#39f23300 cover:PageBlock = PageBlock;
pageBlockEmbed#cde200d1 flags:# full_width:flags.0?true allow_scrolling:flags.3?true url:flags.1?string html:flags.2?string poster_photo_id:flags.4?long w:int h:int caption:RichText = PageBlock;
pageBlockEmbedPost#292c7be9 url:string webpage_id:long author_photo_id:long author:string date:int blocks:Vector<PageBlock> caption:RichText = PageBlock;
pageBlockCollage#8b31c4f items:Vector<PageBlock> caption:RichText = PageBlock;
pageBlockSlideshow#130c8963 items:Vector<PageBlock> caption:RichText = PageBlock;
pageBlockEmbed#a8718dc5 flags:# full_width:flags.0?true allow_scrolling:flags.3?true url:flags.1?string html:flags.2?string poster_photo_id:flags.4?long w:flags.5?int h:flags.5?int caption:PageCaption = PageBlock;
pageBlockEmbedPost#f259a80b url:string webpage_id:long author_photo_id:long author:string date:int blocks:Vector<PageBlock> caption:PageCaption = PageBlock;
pageBlockCollage#65a0fa4d items:Vector<PageBlock> caption:PageCaption = PageBlock;
pageBlockSlideshow#31f9590 items:Vector<PageBlock> caption:PageCaption = PageBlock;
pageBlockChannel#ef1751b5 channel:Chat = PageBlock;
pageBlockAudio#31b81a7f audio_id:long caption:RichText = PageBlock;
pagePart#8e3f9ebe blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
pageFull#556ec7aa blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
pageBlockAudio#804361ea audio_id:long caption:PageCaption = PageBlock;
pageBlockKicker#1e148390 text:RichText = PageBlock;
pageBlockTable#bf4dea82 flags:# bordered:flags.0?true striped:flags.1?true title:RichText rows:Vector<PageTableRow> = PageBlock;
pageBlockOrderedList#9a8ae1e1 items:Vector<PageListOrderedItem> = PageBlock;
pageBlockDetails#76768bed flags:# open:flags.0?true blocks:Vector<PageBlock> title:RichText = PageBlock;
pageBlockRelatedArticles#16115a96 title:RichText articles:Vector<PageRelatedArticle> = PageBlock;
pageBlockMap#a44f3ef6 geo:GeoPoint zoom:int w:int h:int caption:PageCaption = PageBlock;
phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason;
phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason;
@ -748,7 +766,7 @@ phoneCallEmpty#5366c915 id:long = PhoneCall;
phoneCallWaiting#1b8f4ad1 flags:# id:long access_hash:long date:int admin_id:int participant_id:int protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall;
phoneCallRequested#83761ce4 id:long access_hash:long date:int admin_id:int participant_id:int g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall;
phoneCallAccepted#6d003d3f id:long access_hash:long date:int admin_id:int participant_id:int g_b:bytes protocol:PhoneCallProtocol = PhoneCall;
phoneCall#ffe6ab67 id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connection:PhoneConnection alternative_connections:Vector<PhoneConnection> start_date:int = PhoneCall;
phoneCall#e6f9ddf3 flags:# p2p_allowed:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connection:PhoneConnection alternative_connections:Vector<PhoneConnection> start_date:int = PhoneCall;
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall;
phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
@ -770,11 +788,7 @@ langPackStringDeleted#2979eeb2 key:string = LangPackString;
langPackDifference#f385c1f6 lang_code:string from_version:int version:int strings:Vector<LangPackString> = LangPackDifference;
langPackLanguage#117698f1 name:string native_name:string lang_code: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;
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;
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
@ -792,6 +806,8 @@ channelAdminLogEventActionParticipantToggleBan#e6d83d7e prev_participant:Channel
channelAdminLogEventActionParticipantToggleAdmin#d5676710 prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = 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;
@ -864,9 +880,9 @@ secureValueTypeTemporaryRegistration#ea02ec33 = SecureValueType;
secureValueTypePhone#b320aadb = SecureValueType;
secureValueTypeEmail#8e3ca7ee = SecureValueType;
secureValue#b4b4b699 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;
secureValue#187fa0ca flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile translation:flags.6?Vector<SecureFile> files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;
inputSecureValue#67872e8 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;
inputSecureValue#db21d0a7 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile translation:flags.6?Vector<InputSecureFile> files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;
secureValueHash#ed1ecdb0 type:SecureValueType hash:bytes = SecureValueHash;
@ -876,10 +892,13 @@ secureValueErrorReverseSide#868a2aa5 type:SecureValueType file_hash:bytes text:s
secureValueErrorSelfie#e537ced6 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorFile#7a700873 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorFiles#666220e9 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
secureValueError#869d758f type:SecureValueType hash:bytes text:string = SecureValueError;
secureValueErrorTranslationFile#a1144770 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorTranslationFiles#34636dd8 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
secureCredentialsEncrypted#33f0ea47 data:bytes hash:bytes secret:bytes = SecureCredentialsEncrypted;
account.authorizationForm#cb976d53 flags:# selfie_required:flags.1?true required_types:Vector<SecureValueType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
account.authorizationForm#ad2e1cd8 flags:# required_types:Vector<SecureRequiredType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;
account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEmailCode;
@ -890,6 +909,82 @@ savedPhoneContact#1142bd56 phone:string first_name:string last_name:string date:
account.takeout#4dba4501 id:long = account.Takeout;
passwordKdfAlgoUnknown#d45ab096 = PasswordKdfAlgo;
passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow#3a912d4a salt1:bytes salt2:bytes g:int p:bytes = PasswordKdfAlgo;
securePasswordKdfAlgoUnknown#4a8537 = SecurePasswordKdfAlgo;
securePasswordKdfAlgoPBKDF2HMACSHA512iter100000#bbf2dda0 salt:bytes = SecurePasswordKdfAlgo;
securePasswordKdfAlgoSHA512#86471d92 salt:bytes = SecurePasswordKdfAlgo;
secureSecretSettings#1527bcac secure_algo:SecurePasswordKdfAlgo secure_secret:bytes secure_secret_id:long = SecureSecretSettings;
inputCheckPasswordEmpty#9880f658 = InputCheckPasswordSRP;
inputCheckPasswordSRP#d27ff082 srp_id:long A:bytes M1:bytes = InputCheckPasswordSRP;
secureRequiredType#829d99da flags:# native_names:flags.0?true selfie_required:flags.1?true translation_required:flags.2?true type:SecureValueType = SecureRequiredType;
secureRequiredTypeOneOf#27477b4 types:Vector<SecureRequiredType> = SecureRequiredType;
help.passportConfigNotModified#bfb9f457 = help.PassportConfig;
help.passportConfig#a098d6af hash:int countries_langs:DataJSON = help.PassportConfig;
inputAppEvent#1d1b1245 time:double type:string peer:long data:JSONValue = InputAppEvent;
jsonObjectValue#c0de1bd9 key:string value:JSONValue = JSONObjectValue;
jsonNull#3f6d7b68 = JSONValue;
jsonBool#c7345e6a value:Bool = JSONValue;
jsonNumber#2be0dfa4 value:double = JSONValue;
jsonString#b71e767a value:string = JSONValue;
jsonArray#f7444763 value:Vector<JSONValue> = JSONValue;
jsonObject#99c1d49d value:Vector<JSONObjectValue> = JSONValue;
pageTableCell#34566b6a flags:# header:flags.0?true align_center:flags.3?true align_right:flags.4?true valign_middle:flags.5?true valign_bottom:flags.6?true text:flags.7?RichText colspan:flags.1?int rowspan:flags.2?int = PageTableCell;
pageTableRow#e0c0c5e5 cells:Vector<PageTableCell> = PageTableRow;
pageCaption#6f747657 text:RichText credit:RichText = PageCaption;
pageListItemText#b92fb6cd text:RichText = PageListItem;
pageListItemBlocks#25e073fc blocks:Vector<PageBlock> = PageListItem;
pageListOrderedItemText#5e068047 num:string text:RichText = PageListOrderedItem;
pageListOrderedItemBlocks#98dd8936 num:string blocks:Vector<PageBlock> = PageListOrderedItem;
pageRelatedArticle#b390dc08 flags:# url:string webpage_id:long title:flags.0?string description:flags.1?string photo_id:flags.2?long author:flags.3?string published_date:flags.4?int = PageRelatedArticle;
page#ae891bec flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
help.supportName#8c05f1c9 name:string = help.SupportName;
help.userInfoEmpty#f3ae2eed = help.UserInfo;
help.userInfo#1eb3758 message:string entities:Vector<MessageEntity> author:string date:int = help.UserInfo;
pollAnswer#6ca9c2e9 text:string option:bytes = PollAnswer;
poll#d5529d06 id:long flags:# closed:flags.0?true question:string answers:Vector<PollAnswer> = Poll;
pollAnswerVoters#3b6ddad2 flags:# chosen:flags.0?true option:bytes voters:int = PollAnswerVoters;
pollResults#5755785a flags:# min:flags.0?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int = PollResults;
chatOnlines#f041e250 onlines:int = ChatOnlines;
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;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -900,7 +995,7 @@ invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange 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.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
auth.logOut#5717da40 = Bool;
@ -909,7 +1004,7 @@ auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
auth.importAuthorization#e3ef9613 id:int bytes:bytes = auth.Authorization;
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
auth.checkPassword#a63011e password_hash:bytes = auth.Authorization;
auth.checkPassword#d18b4d16 password:InputCheckPasswordSRP = auth.Authorization;
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
auth.recoverPassword#4ea56e92 code:string = auth.Authorization;
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
@ -923,7 +1018,7 @@ account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
account.resetNotifySettings#db7e1747 = Bool;
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.getWallPapers#c04cfac2 = Vector<WallPaper>;
account.getWallPapers#aabb1763 hash:int = account.WallPapers;
account.reportPeer#ae189d5f peer:InputPeer reason:ReportReason = Bool;
account.checkUsername#2714d86c username:string = Bool;
account.updateUsername#3e0bdd7c username:string = User;
@ -932,17 +1027,17 @@ account.setPrivacy#c9f81ce8 key:InputPrivacyKey rules:Vector<InputPrivacyRule> =
account.deleteAccount#418d4e0b reason:string = Bool;
account.getAccountTTL#8fc711d = AccountDaysTTL;
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.updateDeviceLocked#38df3532 period:int = Bool;
account.getAuthorizations#e320c158 = account.Authorizations;
account.resetAuthorization#df77f3bc hash:long = Bool;
account.getPassword#548a30f5 = account.Password;
account.getPasswordSettings#bc8d11bb current_password_hash:bytes = account.PasswordSettings;
account.updatePasswordSettings#fa7c4b86 current_password_hash:bytes new_settings:account.PasswordInputSettings = Bool;
account.sendConfirmPhoneCode#1516d7bd flags:# allow_flashcall:flags.0?true hash:string current_number:flags.0?Bool = auth.SentCode;
account.getPasswordSettings#9cd4eaf9 password:InputCheckPasswordSRP = account.PasswordSettings;
account.updatePasswordSettings#a59b102f password:InputCheckPasswordSRP new_settings:account.PasswordInputSettings = Bool;
account.sendConfirmPhoneCode#1b3faa88 hash:string settings:CodeSettings = auth.SentCode;
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
account.getTmpPassword#4a82327e password_hash:bytes period:int = account.TmpPassword;
account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
account.resetWebAuthorization#2d01b9ef hash:long = Bool;
account.resetWebAuthorizations#682d2594 = Bool;
@ -952,27 +1047,38 @@ account.saveSecureValue#899fe31d value:InputSecureValue secure_secret_id:long =
account.deleteSecureValue#b880bc4b types:Vector<SecureValueType> = Bool;
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.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.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
account.verifyEmail#ecba39db email:string code:string = Bool;
account.initTakeoutSession#f05b4804 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?int = account.Takeout;
account.finishTakeoutSession#1d2652ee flags:# success:flags.0?true = Bool;
account.confirmPasswordEmail#8fdf1920 code:string = Bool;
account.resendPasswordEmail#7a7f2a15 = Bool;
account.cancelPasswordEmail#c1cbd5b6 = Bool;
account.getContactSignUpNotification#9f07c728 = Bool;
account.setContactSignUpNotification#cff43f61 silent:Bool = Bool;
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;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
contacts.getContactIDs#2caa4a42 hash:int = Vector<int>;
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
contacts.getContacts#c023849f hash:int = contacts.Contacts;
contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts;
contacts.deleteContact#8e953744 id:InputUser = contacts.Link;
contacts.deleteContacts#59ab389e id:Vector<InputUser> = Bool;
contacts.deleteByPhones#1013fd9e phones:Vector<string> = Bool;
contacts.block#332b49fc id:InputUser = Bool;
contacts.unblock#e54100bd id:InputUser = Bool;
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
contacts.exportCard#84e53737 = Vector<int>;
contacts.importCard#4fe196fe export_card:Vector<int> = User;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
@ -1019,7 +1125,7 @@ messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
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.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
@ -1027,7 +1133,6 @@ messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = m
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
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.toggleChatAdmins#ec8bd9e1 chat_id:int enabled:Bool = Updates;
messages.editChatAdmin#a9e69f2e chat_id:int user_id:InputUser is_admin:Bool = Bool;
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;
@ -1038,10 +1143,10 @@ messages.getSavedGifs#83bf3d52 hash:int = messages.SavedGifs;
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool;
messages.sendInlineBotResult#b16e06fe flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates;
messages.sendInlineBotResult#b16e06fe flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string = Updates;
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
messages.editMessage#c000e4c8 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Updates;
messages.editInlineBotMessage#adc3e828 flags:# no_webpage:flags.1?true stop_geo_live:flags.12?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> geo_point:flags.13?InputGeoPoint = Bool;
messages.editMessage#d116f31e flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Updates;
messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
messages.getBotCallbackAnswer#810a9fec flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes = messages.BotCallbackAnswer;
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
@ -1080,6 +1185,14 @@ messages.searchStickerSets#c2b7d08b flags:# exclude_featured:flags.0?true q:stri
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
messages.clearAllDrafts#7e58ee9c = Bool;
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true peer:InputPeer id:int = Updates;
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
messages.getStatsURL#83f6c0cd peer:InputPeer = StatsURL;
messages.editChatAbout#def60797 peer:InputPeer about:string = Bool;
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1101,8 +1214,7 @@ upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<Fil
help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
help.getAppUpdate#ae2de196 = help.AppUpdate;
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getAppUpdate#522d5a7d source:string = help.AppUpdate;
help.getInviteText#4d392343 = help.InviteText;
help.getSupport#9cdf08cd = help.Support;
help.getAppChangelog#9010ef6f prev_app_version:string = Updates;
@ -1113,6 +1225,12 @@ help.getProxyData#3d7758e1 = help.ProxyData;
help.getTermsOfServiceUpdate#2ca51fd1 = help.TermsOfServiceUpdate;
help.acceptTermsOfService#ee72f79a id:DataJSON = Bool;
help.getDeepLinkInfo#3fedc75f path:string = help.DeepLinkInfo;
help.getAppConfig#98914110 = JSONValue;
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getPassportConfig#c661ad08 hash:int = help.PassportConfig;
help.getSupportName#d360e72c = help.SupportName;
help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
@ -1124,8 +1242,7 @@ channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channe
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
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.editAbout#13e27f1e channel:InputChannel about:string = Bool;
channels.editAdmin#20b88214 channel:InputChannel user_id:InputUser admin_rights:ChannelAdminRights = Updates;
channels.editAdmin#70f893ba channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights = Updates;
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
channels.checkUsername#10e6bd2c channel:InputChannel username:string = Bool;
@ -1133,14 +1250,11 @@ channels.updateUsername#3514b3de channel:InputChannel username:string = Bool;
channels.joinChannel#24b524c5 channel:InputChannel = Updates;
channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> = Updates;
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;
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.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
channels.updatePinnedMessage#a72ded52 flags:# silent:flags.0?true channel:InputChannel id:int = Updates;
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.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
@ -1172,9 +1286,10 @@ phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDisc
phone.setCallRating#1c536a34 peer:InputPhoneCall rating:int comment:string = Updates;
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
langpack.getLangPack#9ab5c58e lang_code:string = LangPackDifference;
langpack.getStrings#2e1ee318 lang_code:string keys:Vector<string> = Vector<LangPackString>;
langpack.getDifference#b2e4d7d from_version:int = LangPackDifference;
langpack.getLanguages#800fd57d = Vector<LangPackLanguage>;
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.getDifference#cd984aa5 lang_pack:string lang_code:string from_version:int = LangPackDifference;
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
// LAYER 82
// LAYER 95

View File

@ -9,14 +9,16 @@ class {class_name}(Object):
"""{docstring_args}
"""
__slots__ = [{slots}]
ID = {object_id}
QUALNAME = "{qualname}"
def __init__(self{arguments}):
{fields}
@staticmethod
def read(b: BytesIO, *args) -> "{class_name}":
{read_flags}
{read_types}
return {class_name}({return_arguments})
@ -24,6 +26,5 @@ class {class_name}(Object):
b = BytesIO()
b.write(Int(self.ID, False))
{write_flags}
{write_types}
return b.getvalue()

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -73,7 +73,7 @@ def start():
f_init.write("from .{}_{} import *\n".format(name.lower(), code))
with open("{}/source/{}".format(HOME, i), encoding="utf-8") as f_csv, \
open("{}/{}_{}.py".format(DEST, name.lower(), code), "w", encoding="utf-8") as f_class:
open("{}/{}_{}.py".format(DEST, name.lower(), code), "w", encoding="utf-8") as f_class:
reader = csv.reader(f_csv, delimiter="\t")
super_class = caml(name)

View File

@ -51,7 +51,7 @@ BOT_INLINE_DISABLED The inline feature of the bot is disabled
INLINE_RESULT_EXPIRED The inline bot query expired
INVITE_HASH_INVALID The invite link hash is invalid
USER_ALREADY_PARTICIPANT The user is already a participant of this chat
TTL_MEDIA_INVALID This kind of media does not support self-destruction
TTL_MEDIA_INVALID The media does not support self-destruction
MAX_ID_INVALID The max_id parameter is invalid
CHANNEL_INVALID The channel parameter is invalid
DC_ID_INVALID The dc_id parameter is invalid
@ -59,15 +59,40 @@ LIMIT_INVALID The limit parameter is invalid
OFFSET_INVALID The offset parameter is invalid
EMAIL_INVALID The email provided is invalid
USER_IS_BOT A bot cannot send messages to other bots or to itself
WEBPAGE_CURL_FAILED Telegram could not fetch the provided URL
WEBPAGE_CURL_FAILED Telegram server could not fetch the provided URL
STICKERSET_INVALID The requested sticker set is invalid
PEER_FLOOD The method can't be used because your account is limited
MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters
MEDIA_CAPTION_TOO_LONG The media caption is longer than 1024 characters
USER_NOT_MUTUAL_CONTACT The user is not a mutual contact
USER_CHANNELS_TOO_MUCH The user is already in too many channels or supergroups
API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server side
USER_NOT_PARTICIPANT The user is not a member of this chat
CHANNEL_PRIVATE The channel/supergroup is not accessible
MESSAGE_IDS_EMPTY The requested message doesn't exist
WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media
QUERY_ID_INVALID The callback query id is invalid
MEDIA_EMPTY The media is invalid
USER_IS_BLOCKED The user blocked you
YOU_BLOCKED_USER You blocked this user
ADMINS_TOO_MUCH The chat has too many administrators
BOTS_TOO_MUCH The chat has too many bots
USER_ADMIN_INVALID The action requires admin privileges
INPUT_USER_DEACTIVATED The target user has been deactivated
PASSWORD_RECOVERY_NA The password recovery e-mail is not available
PASSWORD_EMPTY The password entered is empty
PHONE_NUMBER_FLOOD This number has tried to login too many times
TAKEOUT_INVALID The takeout id is invalid
TAKEOUT_REQUIRED The method must be invoked inside a takeout session
MESSAGE_POLL_CLOSED You can't interact with a closed poll
MEDIA_INVALID The media is invalid
BOT_SCORE_NOT_MODIFIED The bot score was not modified
USER_BOT_REQUIRED The method can be used by bots only
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_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
1 id message
51 INLINE_RESULT_EXPIRED The inline bot query expired
52 INVITE_HASH_INVALID The invite link hash is invalid
53 USER_ALREADY_PARTICIPANT The user is already a participant of this chat
54 TTL_MEDIA_INVALID This kind of media does not support self-destruction The media does not support self-destruction
55 MAX_ID_INVALID The max_id parameter is invalid
56 CHANNEL_INVALID The channel parameter is invalid
57 DC_ID_INVALID The dc_id parameter is invalid
59 OFFSET_INVALID The offset parameter is invalid
60 EMAIL_INVALID The email provided is invalid
61 USER_IS_BOT A bot cannot send messages to other bots or to itself
62 WEBPAGE_CURL_FAILED Telegram could not fetch the provided URL Telegram server could not fetch the provided URL
63 STICKERSET_INVALID The requested sticker set is invalid
64 PEER_FLOOD The method can't be used because your account is limited
65 MEDIA_CAPTION_TOO_LONG The media caption is longer than 200 characters The media caption is longer than 1024 characters
66 USER_NOT_MUTUAL_CONTACT The user is not a mutual contact
67 USER_CHANNELS_TOO_MUCH The user is already in too many channels or supergroups
68 API_ID_PUBLISHED_FLOOD You are using an API key that is limited on the server side
69 USER_NOT_PARTICIPANT The user is not a member of this chat
70 CHANNEL_PRIVATE The channel/supergroup is not accessible
71 MESSAGE_IDS_EMPTY The requested message doesn't exist
72 WEBPAGE_MEDIA_EMPTY The URL doesn't contain any valid media
73 QUERY_ID_INVALID The callback query id is invalid
74 MEDIA_EMPTY The media is invalid
75 USER_IS_BLOCKED The user blocked you
76 YOU_BLOCKED_USER You blocked this user
77 ADMINS_TOO_MUCH The chat has too many administrators
78 BOTS_TOO_MUCH The chat has too many bots
79 USER_ADMIN_INVALID The action requires admin privileges
80 INPUT_USER_DEACTIVATED The target user has been deactivated
81 PASSWORD_RECOVERY_NA The password recovery e-mail is not available
82 PASSWORD_EMPTY The password entered is empty
83 PHONE_NUMBER_FLOOD This number has tried to login too many times
84 TAKEOUT_INVALID The takeout id is invalid
85 TAKEOUT_REQUIRED The method must be invoked inside a takeout session
86 MESSAGE_POLL_CLOSED You can't interact with a closed poll
87 MEDIA_INVALID The media is invalid
88 BOT_SCORE_NOT_MODIFIED The bot score was not modified
89 USER_BOT_REQUIRED The method can be used by bots only
90 IMAGE_PROCESS_FAILED The server failed to process your image
91 USERNAME_NOT_MODIFIED The username was not modified
92 CALL_ALREADY_ACCEPTED The call is already accepted
93 CALL_ALREADY_DECLINED The call is already declined
94 PHOTO_EXT_INVALID The photo extension is invalid
95 EXTERNAL_URL_INVALID The external media URL is invalid
96 CHAT_NOT_MODIFIED The chat settings were not modified
97 RESULTS_TOO_MUCH The result contains too many items
98 RESULT_ID_DUPLICATE The result contains items with duplicated identifiers

View File

@ -1,2 +1,3 @@
id message
AUTH_KEY_DUPLICATED Authorization error. You must log out and log in again with your phone number. We apologize for the inconvenience.
AUTH_KEY_DUPLICATED Authorization error - you must delete your session file and log in again with your phone number
FILEREF_UPGRADE_NEEDED The file reference has expired - you must obtain the original media message
1 id message
2 AUTH_KEY_DUPLICATED Authorization error. You must log out and log in again with your phone number. We apologize for the inconvenience. Authorization error - you must delete your session file and log in again with your phone number
3 FILEREF_UPGRADE_NEEDED The file reference has expired - you must obtain the original media message

View File

@ -1,2 +1,3 @@
id message
FLOOD_WAIT_X A wait of {x} seconds is required
TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {x} seconds

1 id message
2 FLOOD_WAIT_X A wait of {x} seconds is required
3 TAKEOUT_INIT_DELAY_X You have to confirm the data export request using one of your mobile devices or wait {x} seconds

View File

@ -4,4 +4,5 @@ RPC_CALL_FAIL Telegram is having internal problems. Please try again later
RPC_MCGET_FAIL Telegram is having internal problems. Please try again later
PERSISTENT_TIMESTAMP_OUTDATED Telegram is having internal problems. Please try again later
HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later
1 id message
4 RPC_MCGET_FAIL Telegram is having internal problems. Please try again later
5 PERSISTENT_TIMESTAMP_OUTDATED Telegram is having internal problems. Please try again later
6 HISTORY_GET_FAILED Telegram is having internal problems. Please try again later
7 REG_ID_GENERATE_FAILED Telegram is having internal problems. Please try again later
8 RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later

View File

@ -1,5 +1,5 @@
Bad Request
===========
400 - Bad Request
=================
.. module:: pyrogram.api.errors.BadRequest

View File

@ -1,5 +1,5 @@
Flood
=====
420 - Flood
===========
.. module:: pyrogram.api.errors.Flood

View File

@ -0,0 +1,8 @@
403 - Forbidden
===============
.. module:: pyrogram.api.errors.Forbidden
.. automodule:: pyrogram.api.errors.exceptions.forbidden_403
:members:
:show-inheritance:

View File

@ -1,5 +1,5 @@
Internal Server Error
=====================
500 - Internal Server Error
===========================
.. module:: pyrogram.api.errors.InternalServerError

View File

@ -0,0 +1,8 @@
406 - Not Acceptable
====================
.. module:: pyrogram.api.errors.NotAcceptable
.. automodule:: pyrogram.api.errors.exceptions.not_acceptable_406
:members:
:show-inheritance:

View File

@ -1,5 +1,5 @@
See Other
=========
303 - See Other
===============
.. module:: pyrogram.api.errors.SeeOther

View File

@ -1,5 +1,5 @@
Unauthorized
============
401 - Unauthorized
==================
.. module:: pyrogram.api.errors.Unauthorized

View File

@ -1,5 +1,5 @@
Unknown Error
=============
520 - Unknown Error
===================
.. module:: pyrogram.api.errors.UnknownError

View File

@ -10,27 +10,28 @@ Welcome to Pyrogram
</div>
<p align="center">
<b>Telegram MTProto API Client Library for Python</b>
<b>Telegram MTProto API Framework for Python</b>
<br>
<a href="https://github.com/pyrogram/pyrogram/releases/latest">
Download
<a href="https://docs.pyrogram.ml">
Documentation
</a>
<a href="https://github.com/pyrogram/pyrogram">
Source code
<a href="https://github.com/pyrogram/pyrogram/releases">
Changelog
</a>
<a href="https://t.me/PyrogramChat">
Community
</a>
<br>
<a href="https://github.com/pyrogram/pyrogram/blob/master/compiler/api/source/main_api.tl">
<img src="https://img.shields.io/badge/schema-layer%2082-eda738.svg?longCache=true&colorA=262b30"
alt="Scheme Layer">
<a href="compiler/api/source/main_api.tl">
<img src="https://img.shields.io/badge/schema-layer%2095-eda738.svg?longCache=true&colorA=262b30"
alt="Schema Layer">
</a>
<a href="https://github.com/pyrogram/tgcrypto">
<img src="https://img.shields.io/badge/tgcrypto-v1.1.1-eda738.svg?longCache=true&colorA=262b30"
alt="TgCrypto">
alt="TgCrypto Version">
</a>
</p>
@ -48,25 +49,27 @@ Welcome to Pyrogram
app.run()
Welcome to Pyrogram's Documentation! Here you can find resources for learning how to use the library.
Welcome to Pyrogram's Documentation! Here you can find resources for learning how to use the framework.
Contents are organized into self-contained topics and can be accessed from the sidebar, or by following them in order
using the Next button at the end of each page. But first, here's a brief overview of what is this all about.
About
-----
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for
building custom Telegram applications that interact with the MTProto API as both User and Bot.
**Pyrogram** is an elegant, easy-to-use Telegram_ client library and framework written from the ground up in Python and C.
It enables you to easily create custom apps using both user and bot identities (bot API alternative) via the `MTProto API`_.
Features
--------
- **Easy to use**: You can easily install Pyrogram using pip and start building your app right away.
- **High-level**: The low-level details of MTProto are abstracted and automatically handled.
- **Easy**: You can install Pyrogram with pip and start building your applications right away.
- **Elegant**: Low-level details are abstracted and re-presented in a much nicer and easier way.
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
- **Updated** to the latest Telegram API version, currently Layer 82 on top of MTProto 2.0.
- **Documented**: The Pyrogram API is well documented and resembles the Telegram Bot API.
- **Full API**, allowing to execute any advanced action an official client is able to do, and more.
- **Documented**: Pyrogram API methods, types and public interfaces are well documented.
- **Type-hinted**: Exposed Pyrogram types and method parameters are all type-hinted.
- **Updated**, to the latest Telegram API version, currently Layer 95 on top of `MTProto 2.0`_.
- **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.
To get started, press the Next button.
@ -84,6 +87,8 @@ To get started, press the Next button.
resources/UpdateHandling
resources/UsingFilters
resources/MoreOnUpdates
resources/ConfigurationFile
resources/SmartPlugins
resources/AutoAuthorization
resources/CustomizeSessions
@ -92,6 +97,10 @@ To get started, press the Next button.
resources/SOCKS5Proxy
resources/BotsInteraction
resources/ErrorHandling
resources/TestServers
resources/AdvancedUsage
resources/VoiceCalls
resources/Changelog
.. toctree::
:hidden:
@ -107,4 +116,6 @@ To get started, press the Next button.
types/index
.. _`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 2.0`: https://core.telegram.org/mtproto

View File

@ -13,13 +13,15 @@ Utilities
start
stop
restart
idle
run
add_handler
remove_handler
send
resolve_peer
download_media
save_file
stop_transmission
Decorators
----------
@ -62,6 +64,11 @@ Messages
delete_messages
get_messages
get_history
iter_history
send_poll
vote_poll
retract_vote
download_media
Chats
-----
@ -83,10 +90,13 @@ Chats
pin_chat_message
unpin_chat_message
get_chat
get_chat_preview
get_chat_member
get_chat_members
get_chat_members_count
iter_chat_members
get_dialogs
iter_dialogs
Users
-----
@ -130,6 +140,9 @@ Bots
send_inline_bot_result
answer_callback_query
request_callback_answer
send_game
set_game_score
get_game_high_scores
.. autoclass:: pyrogram.Client

View File

@ -9,6 +9,8 @@ Error
../errors/SeeOther
../errors/BadRequest
../errors/Unauthorized
../errors/Forbidden
../errors/NotAcceptable
../errors/Flood
../errors/InternalServerError
../errors/UnknownError

View File

@ -12,9 +12,11 @@ Users & Chats
User
UserStatus
Chat
ChatPreview
ChatPhoto
ChatMember
ChatMembers
ChatPermissions
Dialog
Dialogs
@ -40,6 +42,8 @@ Messages & Media
Location
Venue
Sticker
Poll
PollOption
Bots
----
@ -54,6 +58,7 @@ Bots
InlineKeyboardButton
ForceReply
CallbackQuery
Game
Input Media
-----------
@ -91,6 +96,9 @@ Inline Mode
.. autoclass:: Chat
:members:
.. autoclass:: ChatPreview
:members:
.. autoclass:: ChatPhoto
:members:
@ -157,6 +165,12 @@ Inline Mode
.. autoclass:: Sticker
:members:
.. autoclass:: Poll
:members:
.. autoclass:: PollOption
:members:
.. Bots
----
@ -181,6 +195,15 @@ Inline Mode
.. autoclass:: CallbackQuery
:members:
.. autoclass:: Game
:members:
.. autoclass:: GameHighScore
:members:
.. autoclass:: GameHighScores
:members:
.. Input Media
-----------

View File

@ -0,0 +1,121 @@
Advanced Usage
==============
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main Telegram
API with its raw functions and types.
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
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.
.. hint::
Every available high-level method mentioned in the previous page 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
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API.
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
Caveats
-------
As hinted before, raw functions and types can be confusing, mainly because people don't realize they must accept
*exactly* the right values, but also because most of them don't have enough Python experience to fully grasp how things
work.
This section will therefore explain some pitfalls to take into consideration when working with the raw API.
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.
Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed.
There are three different InputPeer types, one for each kind of Telegram entity.
Whenever an InputPeer is needed you must pass one of these:
- `InputPeerUser <https://docs.pyrogram.ml/types/InputPeerUser>`_ - Users
- `InputPeerChat <https://docs.pyrogram.ml/types/InputPeerChat>`_ - Basic Chats
- `InputPeerChannel <https://docs.pyrogram.ml/types/InputPeerChannel>`_ - Either Channels or Supergroups
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
:meth:`resolve_peer() <pyrogram.Client.resolve_peer>` as a convenience utility method that returns the correct InputPeer
by accepting a peer ID only.
Another thing to take into consideration about chat IDs is the way they are represented: they are all integers and
all positive within their respective raw types.
Things are different when working with Pyrogram's API because having them in the same space can theoretically lead to
collisions, and that's why Pyrogram (as well as the official Bot API) uses a slightly different representation for each
kind of ID.
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:
- ``+ID`` - User: *123456789*
- ``-ID`` - Chat: *-123456789*
- ``-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
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
]
)
)
.. _plenty of them: ../pyrogram/Client.html#messages
.. _Raw Functions: Usage.html#using-raw-functions
.. _Community: https://t.me/PyrogramChat

View File

@ -0,0 +1,11 @@
Changelog
=========
Currently, all Pyrogram release notes live inside the GitHub repository web page:
https://github.com/pyrogram/pyrogram/releases
(You will be automatically redirected in 10 seconds.)
.. raw:: html
<meta http-equiv="refresh" content="10; URL=https://github.com/pyrogram/pyrogram/releases"/>

View File

@ -0,0 +1,90 @@
Configuration File
==================
As already mentioned in previous sections, Pyrogram can also 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.
Introduction
------------
The idea behind using a configuration file is to help keeping your code free of settings (private) information such as
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
fill in the necessary parts.
.. note::
The configuration file is optional, but recommended. If, for any reason, you prefer not to use it, there's always an
alternative way to configure Pyrogram via Client's parameters. Doing so, you can have full control on how to store
and load your settings (e.g.: from environment variables).
Settings specified via Client's parameter have higher priority and will override any setting stored in the
configuration file.
The config.ini File
-------------------
By default, Pyrogram will look for a file named ``config.ini`` placed at the root of your working directory, that is,
the same folder of your running script. You can change the name or location of your configuration file by specifying it
in your Client's parameter *config_file*.
- Replace the default *config.ini* file with *my_configuration.ini*:
.. code-block:: python
from pyrogram import Client
app = Client("my_account", config_file="my_configuration.ini")
Configuration Sections
----------------------
These are all the sections Pyrogram uses in its configuration file:
Pyrogram
^^^^^^^^
The ``[pyrogram]`` section contains your Telegram API credentials *api_id* and *api_hash*.
.. code-block:: ini
[pyrogram]
api_id = 12345
api_hash = 0123456789abcdef0123456789abcdef
`More info about API Key. <../start/Setup.html#configuration>`_
Proxy
^^^^^
The ``[proxy]`` section contains settings about your SOCKS5 proxy.
.. code-block:: ini
[proxy]
enabled = True
hostname = 11.22.33.44
port = 1080
username = <your_username>
password = <your_password>
`More info about SOCKS5 Proxy. <SOCKS5Proxy.html>`_
Plugins
^^^^^^^
The ``[plugins]`` section contains settings about Smart Plugins.
.. code-block:: ini
[plugins]
root = plugins
include =
module
folder.module
exclude =
module fn2
`More info about Smart Plugins. <SmartPlugins.html>`_

View File

@ -1,17 +1,18 @@
Error Handling
==============
Errors are inevitable when working with the API, and they must be correctly handled by
the use of ``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 five exception 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)
- :obj:`303 See Other <pyrogram.api.errors.SeeOther>`
- :obj:`400 Bad Request <pyrogram.api.errors.BadRequest>`
- :obj:`401 Unauthorized <pyrogram.api.errors.Unauthorized>`
- :obj:`420 Flood <pyrogram.api.errors.Flood>`
- :obj:`500 Internal Server Error <pyrogram.api.errors.InternalServerError>`
- :obj:`303 - See Other <pyrogram.api.errors.SeeOther>`
- :obj:`400 - Bad Request <pyrogram.api.errors.BadRequest>`
- :obj:`401 - Unauthorized <pyrogram.api.errors.Unauthorized>`
- :obj:`403 - Forbidden <pyrogram.api.errors.Forbidden>`
- :obj:`406 - Not Acceptable <pyrogram.api.errors.NotAcceptable>`
- :obj:`420 - Flood <pyrogram.api.errors.Flood>`
- :obj:`500 - Internal Server Error <pyrogram.api.errors.InternalServerError>`
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
@ -56,5 +57,3 @@ before you can try again. The value is always stored in the ``x`` field of the r
...
except FloodWait as e:
time.sleep(e.x)
**TODO: Better explanation on how to deal with exceptions**

View File

@ -0,0 +1,221 @@
More on Updates
===============
Here we'll show some advanced usages when working with updates.
.. 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
--------------
If you register handlers with overlapping filters, only the first one is executed and any other handler will be ignored.
In order to process the same update more than once, you can register your handler in a different group.
Groups are identified by a number (number 0 being the default) and are sorted, that is, a lower group number has a
higher priority.
For example, in:
.. code-block:: python
@app.on_message(Filters.text | Filters.sticker)
def text_or_sticker(client, message):
print("Text or Sticker")
@app.on_message(Filters.text)
def just_text(client, message):
print("Just Text")
``just_text`` is never executed because ``text_or_sticker`` already handles texts. To enable it, simply register the
function using a different group:
.. code-block:: python
@app.on_message(Filters.text, group=1)
def just_text(client, message):
print("Just Text")
Or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-1``, which is less than ``0``):
.. code-block:: python
@app.on_message(Filters.text, group=-1)
def just_text(client, message):
print("Just Text")
With :meth:`add_handler() <pyrogram.Client.add_handler>` (without decorators) the same can be achieved with:
.. code-block:: python
app.add_handler(MessageHandler(just_text, Filters.text), -1)
Update propagation
------------------
Registering multiple handlers, each in a different group, becomes useful when you want to handle the same update more
than once. Any incoming update will be sequentially processed by all of your registered functions by respecting the
groups priority policy described above. Even in case any handler raises an unhandled exception, Pyrogram will still
continue to propagate the same update to the next groups until all the handlers are done. Example:
.. code-block:: python
@app.on_message(Filters.private)
def _(client, message):
print(0)
@app.on_message(Filters.private, group=1)
def _(client, message):
print(1 / 0) # Unhandled exception: ZeroDivisionError
@app.on_message(Filters.private, group=2)
def _(client, message):
print(2)
All these handlers will handle the same kind of messages, that are, messages sent or received in private chats.
The output for each incoming update will therefore be:
.. code-block:: text
0
ZeroDivisionError: division by zero
2
Stop Propagation
^^^^^^^^^^^^^^^^
In order to prevent further propagation of an update in the dispatching phase, you can do *one* of the following:
- Call the update's bound-method ``.stop_propagation()`` (preferred way).
- Manually ``raise StopPropagation`` exception (more suitable for raw updates only).
.. note::
Internally, the propagation is stopped by handling a custom exception. ``.stop_propagation()`` is just an elegant
and intuitive way to ``raise StopPropagation``; this also means that any code coming *after* calling the method
won't be executed as your function just raised an exception to signal the dispatcher not to propagate the
update anymore.
Example with ``stop_propagation()``:
.. code-block:: python
@app.on_message(Filters.private)
def _(client, message):
print(0)
@app.on_message(Filters.private, group=1)
def _(client, message):
print(1)
message.stop_propagation()
@app.on_message(Filters.private, group=2)
def _(client, message):
print(2)
Example with ``raise StopPropagation``:
.. code-block:: python
from pyrogram import StopPropagation
@app.on_message(Filters.private)
def _(client, message):
print(0)
@app.on_message(Filters.private, group=1)
def _(client, message):
print(1)
raise StopPropagation
@app.on_message(Filters.private, group=2)
def _(client, message):
print(2)
Each handler is registered in a different group, but the handler in group number 2 will never be executed because the
propagation was stopped earlier. The output of both (equivalent) examples will be:
.. code-block:: text
0
1
Continue Propagation
^^^^^^^^^^^^^^^^^^^^
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
the group regardless of the next handler's filters. This allows you to register multiple handlers with overlapping
filters in the same group; to let the dispatcher process the next handler you can do *one* of the following in each
handler you want to grant permission to continue:
- Call the update's bound-method ``.continue_propagation()`` (preferred way).
- Manually ``raise ContinuePropagation`` exception (more suitable for raw updates only).
.. note::
Internally, the propagation is continued by handling a custom exception. ``.continue_propagation()`` is just an
elegant and intuitive way to ``raise ContinuePropagation``; this also means that any code coming *after* calling the
method won't be executed as your function just raised an exception to signal the dispatcher to continue with the
next available handler.
Example with ``continue_propagation()``:
.. code-block:: python
@app.on_message(Filters.private)
def _(client, message):
print(0)
message.continue_propagation()
@app.on_message(Filters.private)
def _(client, message):
print(1)
message.continue_propagation()
@app.on_message(Filters.private)
def _(client, message):
print(2)
Example with ``raise ContinuePropagation``:
.. code-block:: python
from pyrogram import ContinuePropagation
@app.on_message(Filters.private)
def _(client, message):
print(0)
raise ContinuePropagation
@app.on_message(Filters.private)
def _(client, message):
print(1)
raise ContinuePropagation
@app.on_message(Filters.private)
def _(client, message):
print(2)
Three handlers are registered in the same group, and all of them will be executed because the propagation was continued
in each handler (except in the last one, where is useless to do so since there is no more handlers after).
The output of both (equivalent) examples will be:
.. code-block:: text
0
1
2

View File

@ -1,9 +1,9 @@
Smart Plugins
=============
Pyrogram embeds a **smart** (automatic) and lightweight plugin system that is meant to further simplify the organization
of large projects and to provide a way for creating pluggable components that can be **easily shared** across different
Pyrogram applications with **minimal boilerplate code**.
Pyrogram embeds a **smart**, lightweight yet powerful plugin system that is meant to further simplify the organization
of large projects and to provide a way for creating pluggable (modular) components that can be **easily shared** across
different Pyrogram applications with **minimal boilerplate code**.
.. tip::
@ -13,7 +13,8 @@ Introduction
------------
Prior to the Smart Plugin system, pluggable handlers were already possible. For example, if you wanted to modularize
your applications, you had to do something like this...
your applications, you had to put your function definitions in separate files and register them inside your main script,
like this:
.. note::
@ -63,19 +64,19 @@ your applications, you had to do something like this...
app.run()
...which is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
This is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
manually ``import``, manually :meth:`add_handler <pyrogram.Client.add_handler>` and manually instantiate each
:obj:`MessageHandler <pyrogram.MessageHandler>` object because **you can't use those cool decorators** for your
functions. So... What if you could?
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
Using Smart Plugins
-------------------
Setting up your Pyrogram project to accommodate Smart Plugins is pretty straightforward:
Setting up your Pyrogram project to accommodate Smart Plugins is straightforward:
#. Create a new folder to store all the plugins (e.g.: "plugins").
#. Put your files full of plugins inside.
#. Enable plugins in your Client.
#. 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.
#. Enable plugins in your Client or via the *config.ini* file.
.. note::
@ -107,20 +108,252 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
def echo_reversed(client, message):
message.reply(message.text[::-1])
- ``config.ini``
.. code-block:: ini
[plugins]
root = plugins
- ``main.py``
.. code-block:: python
from pyrogram import Client
Client("my_account", plugins_dir="plugins").run()
Client("my_account").run()
The first important thing to note is the new ``plugins`` folder, whose name is passed to the the ``plugins_dir``
parameter when creating a :obj:`Client <pyrogram.Client>` in the ``main.py`` file — you can put *any python file* in
there and each file can contain *any decorated function* (handlers) with only one limitation: within a single plugin
file you must use different names for each decorated function. Your Pyrogram Client instance will **automatically**
scan the folder upon creation to search for valid handlers and register them for you.
Alternatively, without using the *config.ini* file:
.. code-block:: python
from pyrogram import Client
plugins = dict(
root="plugins"
)
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
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.
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
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
functions in a static way, i.e. **without having the Client instance around**: simply use ``@Client`` (Client class)
instead of the usual ``@app`` (Client instance) namespace and things will work just the same.
instead of the usual ``@app`` (Client instance) and things will work just the same.
Specifying the Plugins to include
---------------------------------
By default, if you don't explicitly supply a list of plugins, every valid one found inside your plugins root folder will
be included by following the alphabetical order of the directory structure (files and subfolders); the single handlers
found inside each module will be, instead, loaded in the order they are defined, from top to bottom.
.. note::
Remember: there can be at most one handler, within a group, dealing with a specific update. Plugins with overlapping
filters included a second time will not work. Learn more at `More on Updates <MoreOnUpdates.html>`_.
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``
keys, 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 ``include`` is given, only the specified plugins will be loaded, in the order they are passed.
- If ``exclude`` is given, the plugins specified here will be unloaded.
The ``include`` and ``exclude`` value is a **list of strings**. Each string containing the path of the module relative
to the plugins root folder, in Python notation (dots instead of slashes).
E.g.: ``subfolder.module`` refers to ``plugins/subfolder/module.py``, with ``root="plugins"``.
You can also choose the order in which the single handlers inside a module are loaded, thus overriding the default
top-to-bottom loading policy. You can do this by appending the name of the functions to the module path, each one
separated by a blank space.
E.g.: ``subfolder.module fn2 fn1 fn3`` will load *fn2*, *fn1* and *fn3* from *subfolder.module*, in this order.
Examples
^^^^^^^^
Given this plugins folder structure with three modules, each containing their own handlers (fn1, fn2, etc...), which are
also organized in subfolders:
.. code-block:: text
myproject/
plugins/
subfolder1/
plugins1.py
- fn1
- fn2
- fn3
subfolder2/
plugins2.py
...
plugins0.py
...
...
- Load every handler from every module, namely *plugins0.py*, *plugins1.py* and *plugins2.py* in alphabetical order
(files) and definition order (handlers inside files):
Using *config.ini* file:
.. code-block:: ini
[plugins]
root = plugins
Using *Client*'s parameter:
.. code-block:: python
plugins = dict(
root="plugins"
)
Client("my_account", plugins=plugins).run()
- Load only handlers defined inside *plugins2.py* and *plugins0.py*, in this order:
Using *config.ini* file:
.. code-block:: ini
[plugins]
root = plugins
include =
subfolder2.plugins2
plugins0
Using *Client*'s parameter:
.. code-block:: python
plugins = dict(
root="plugins",
include=[
"subfolder2.plugins2",
"plugins0"
]
)
Client("my_account", plugins=plugins).run()
- Load everything except the handlers inside *plugins2.py*:
Using *config.ini* file:
.. code-block:: ini
[plugins]
root = plugins
exclude = subfolder2.plugins2
Using *Client*'s parameter:
.. code-block:: python
plugins = dict(
root="plugins",
exclude=["subfolder2.plugins2"]
)
Client("my_account", plugins=plugins).run()
- Load only *fn3*, *fn1* and *fn2* (in this order) from *plugins1.py*:
Using *config.ini* file:
.. code-block:: ini
[plugins]
root = plugins
include = subfolder1.plugins1 fn3 fn1 fn2
Using *Client*'s parameter:
.. code-block:: python
plugins = dict(
root="plugins",
include=["subfolder1.plugins1 fn3 fn1 fn2"]
)
Client("my_account", plugins=plugins).run()
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
which to ignore before your Client starts. Here we'll show, instead, how to unload and load again a previously
registered plugins at runtime.
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
*(handler: Handler, group: int)*. The actual callback function is therefore stored inside the handler's *callback*
attribute. Here's an example:
- ``plugins/handlers.py``
.. code-block:: python
:emphasize-lines: 5, 6
@Client.on_message(Filters.text & Filters.private)
def echo(client, message):
message.reply(message.text)
print(echo)
print(echo[0].callback)
- 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
Handler, will reveal the actual callback ``<function echo at 0x10e3b6598>``.
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
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:
- ``main.py``
.. code-block:: python
from plugins.handlers import echo
...
app.remove_handler(*echo)
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
exactly what is needed. The same could have been achieved with:
.. code-block:: python
handler, group = echo
app.remove_handler(handler, group)
Loading
^^^^^^^
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:
- ``main.py``
.. code-block:: python
from plugins.handlers import echo
...
app.add_handler(*echo)

View File

@ -0,0 +1,39 @@
Test Servers
============
If you wish to test your application in a separate environment, Pyrogram is able to authorize your account into
Telegram's test servers without hassle. All you need to do is start a new session (e.g.: "my_account_test") using
``test_mode=True``:
.. code-block:: python
from pyrogram import Client
with Client("my_account_test", test_mode=True) as app:
print(app.get_me())
.. note::
If this is the first time you login into test servers, you will be asked to register your account first.
Don't worry about your contacts and chats, they will be kept untouched inside the production environment;
accounts authorized on test servers reside in a different, parallel instance of a Telegram database.
Test Mode in Official Apps
--------------------------
You can also login yourself into test servers using official desktop apps, such as Webogram and TDesktop:
- **Webogram**: Login here: https://web.telegram.org/?test=1
- **TDesktop**: Open settings and type ``testmode``.
Test Numbers
------------
Beside normal numbers, the test environment allows you to login with reserved test numbers.
Valid phone numbers follow the pattern ``99966XYYYY``, where ``X`` is the DC number (1 to 3) and ``YYYY`` are random
numbers. Users with such numbers always get ``XXXXX`` as the confirmation code (the DC number, repeated five times).
.. important::
Do not store any important or private information in such test users' accounts; anyone can make use of the
simplified authorization mechanism and login at any time.

View File

@ -1,5 +1,5 @@
TgCrypto
========
Fast Crypto
===========
Pyrogram's speed can be *dramatically* boosted up by TgCrypto_, a high-performance, easy-to-install Telegram Crypto
Library specifically written in C for Pyrogram [#f1]_ as a Python extension.

View File

@ -5,7 +5,8 @@ For a finer grained control over what kind of messages will be allowed or not in
:class:`Filters <pyrogram.Filters>`.
.. note::
This section makes use of Handlers to handle updates. Learn more at `Update Handling <UpdateHandling.html>`_.
This page makes use of Handlers to show you how to handle updates.
Learn more at `Update Handling <UpdateHandling.html>`_.
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
ignore any other message:
@ -99,45 +100,6 @@ More handlers using different filters can also live together.
def from_pyrogramchat(client, message):
print("New message in @PyrogramChat")
Handler Groups
--------------
If you register handlers with overlapping filters, only the first one is executed and any other handler will be ignored.
In order to process the same message more than once, you can register your handler in a different group.
Groups are identified by a number (number 0 being the default) and are sorted. This means that a lower group number has
a higher priority.
For example, in:
.. code-block:: python
@app.on_message(Filters.text | Filters.sticker)
def text_or_sticker(client, message):
print("Text or Sticker")
@app.on_message(Filters.text)
def just_text(client, message):
print("Just Text")
``just_text`` is never executed because ``text_or_sticker`` already handles texts. To enable it, simply register the
function using a different group:
.. code-block:: python
@app.on_message(Filters.text, group=1)
def just_text(client, message):
print("Just Text")
or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-1``, which is less than ``0``):
.. code-block:: python
@app.on_message(Filters.text, group=-1)
def just_text(client, message):
print("Just Text")
Custom Filters
--------------
@ -162,7 +124,7 @@ yourself. This allows you to test your filter by pressing the inline button:
"username", # Change this to your username or id
"Pyrogram's custom filter test",
reply_markup=InlineKeyboardMarkup(
[[InlineKeyboardButton("Press me", "pyrogram")]]
[[InlineKeyboardButton("Press me", b"pyrogram")]]
)
)
@ -178,7 +140,7 @@ containing "pyrogram" as data:
hardcoded_data = Filters.create(
name="HardcodedData",
func=lambda filter, callback_query: callback_query.data == "pyrogram"
func=lambda filter, 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
@ -187,7 +149,7 @@ could be achieved with a normal function, but we don't really need it as it make
.. code-block:: python
def func(filter, callback_query):
return callback_query.data == "pyrogram"
return callback_query.data == b"pyrogram"
hardcoded_data = Filters.create(
name="HardcodedData",
@ -223,6 +185,6 @@ And its usage:
.. code-block:: python
@app.on_callback_query(dynamic_data("pyrogram"))
@app.on_callback_query(dynamic_data(b"pyrogram"))
def pyrogram_data(client, callback_query):
client.answer_callback_query(callback_query.id, "it works!")

View File

@ -0,0 +1,10 @@
Voice Calls
===========
A working proof-of-concept of Telegram voice calls using Pyrogram can be found here:
https://github.com/bakatrouble/pylibtgvoip. Thanks to `@bakatrouble <https://t.me/bakatrouble>`_.
.. note::
This page will be updated with more information once voice calls become eventually more usable and more integrated
in Pyrogram itself.

View File

@ -18,23 +18,23 @@ Install Pyrogram
.. code-block:: text
$ pip3 install --upgrade pyrogram
$ pip3 install -U pyrogram
- or, with TgCrypto_ as extra requirement (recommended):
.. code-block:: text
$ pip3 install --upgrade pyrogram[fast]
$ pip3 install -U pyrogram[fast]
Bleeding Edge
-------------
If you want the latest development version of Pyrogram, you can install it straight from the develop_
branch using this command (you might need to install **git** first):
branch using this command (note "develop.zip" in the link):
.. code-block:: text
$ pip3 install --upgrade git+https://github.com/pyrogram/pyrogram.git
$ pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip
Asynchronous
------------
@ -43,11 +43,11 @@ Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging
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).
Use this command to install:
Use this command to install (note "asyncio.zip" in the link):
.. code-block:: text
$ pip3 install --upgrade git+https://github.com/pyrogram/pyrogram.git@asyncio
$ pip3 install -U https://github.com/pyrogram/pyrogram/archive/asyncio.zip
Pyrogram API remains the same and features are kept up to date from the non-async, default develop branch, but you
@ -82,7 +82,7 @@ If no error shows up you are good to go.
>>> import pyrogram
>>> pyrogram.__version__
'0.9.1'
'0.12.0'
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
.. _develop: http://github.com/pyrogram/pyrogram

View File

@ -1,8 +1,7 @@
Usage
=====
Having your `project set up`_ and your account authorized_, it's time to play with the API.
In this section, you'll be shown two ways of communicating with Telegram using Pyrogram. Let's start!
Having your `project set up`_ and your account authorized_, it's time to play with the API. Let's start!
High-level API
--------------
@ -43,79 +42,8 @@ exceptions in your code:
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
Raw Functions
-------------
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>` 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.
.. hint::
Every high-level method mentioned in the section above 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
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API.
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/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
.. _plenty of them: ../pyrogram/Client.html#messages
.. _types: ../pyrogram/Types.html
.. _Raw Functions: Usage.html#using-raw-functions
.. _Community: https://t.me/PyrogramChat
.. _project set up: Setup.html
.. _authorized: Setup.html#user-authorization
.. _Telegram Bot API: https://core.telegram.org/bots/api
.. _Telegram Bot API: https://core.telegram.org/bots/api
.. _methods: ../pyrogram/Client.html#messages
.. _types: ../pyrogram/Types.html

View File

@ -2,21 +2,21 @@
This folder contains example scripts to show you how **Pyrogram** looks like.
Every script is working right away (provided you correctly set up your credentials), meaning
you can simply copy-paste and run. The only things you have to change are session names and target chats.
Every script is working right away (provided you correctly set up your credentials), meaning you can simply copy-paste
and run. The only things you have to change are session names and target chats.
All the examples listed in this directory are licensed under the terms of the [CC0 1.0 Universal](LICENSE) license and
can be freely used as basic building blocks for your own applications without worrying about copyrights.
Example | Description
---: | :---
[**hello_world**](hello_world.py) | Demonstration of basic API usages
[**echo_bot**](echo_bot.py) | Echo bot that replies to every private text message
[**welcome_bot**](welcome_bot.py) | The Welcome Bot source code in [@PyrogramChat](https://t.me/pyrogramchat)
[**get_history**](get_history.py) | How to retrieve the full message history of a chat
[**get_chat_members**](get_chat_members.py) | How to get the first 10.000 members of a supergroup/channel
[**get_chat_members2**](get_chat_members2.py) | Improved version to get more than 10.000 members
[**query_inline_bots**](query_inline_bots.py) | How to query an inline bot and send a result to a chat
[**send_bot_keyboards**](send_bot_keyboards.py) | How to send normal and inline keyboards using regular bots
[**callback_query_handler**](callback_query_handler.py) | How to handle queries coming from inline button presses
[**raw_update_handler**](raw_update_handler.py) | How to handle raw updates (old, should be avoided)
[**hello**](hello.py) | Demonstration of basic API usage
[**echo**](echo.py) | Reply to every private text message
[**welcome**](welcome.py) | The Welcome Bot in [@PyrogramChat](https://t.me/pyrogramchat)
[**history**](history.py) | Get the full message history of a chat
[**chat_members**](chat_members.py) | Get all the members of a chat
[**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
[**keyboards**](keyboards.py) | Send normal and inline keyboards using regular bots
[**callback_queries**](callback_queries.py) | Handle queries coming from inline button presses
[**raw_updates**](raw_updates.py) | Handle raw updates (old, should be avoided)

10
examples/chat_members.py Normal file
View File

@ -0,0 +1,10 @@
"""This example shows how to get all the members of a chat."""
from pyrogram import Client
app = Client("my_count")
target = "pyrogramchat" # Target channel/supergroup
with app:
for member in app.iter_chat_members(target):
print(member.user.first_name)

9
examples/dialogs.py Normal file
View File

@ -0,0 +1,9 @@
"""This example shows how to get the full dialogs list of a user."""
from pyrogram import Client
app = Client("my_account")
with app:
for dialog in app.iter_dialogs():
print(dialog.chat.title or dialog.chat.first_name)

View File

@ -11,7 +11,7 @@ app = Client("my_account")
@app.on_message(Filters.text & Filters.private)
def echo(client, message):
message.reply(message.text, quote=True)
message.reply(message.text)
app.run() # Automatically start() and idle()

View File

@ -1,31 +0,0 @@
"""This example shows you how to get the first 10.000 members of a chat.
Refer to get_chat_members2.py for more than 10.000 members.
"""
import time
from pyrogram import Client
from pyrogram.api.errors import FloodWait
app = Client("my_account")
target = "pyrogramchat" # Target channel/supergroup
members = [] # List that will contain all the members of the target chat
offset = 0 # Offset starts at 0
limit = 200 # Amount of users to retrieve for each API call (max 200)
with app:
while True:
try:
chunk = app.get_chat_members(target, offset)
except FloodWait as e: # Very large chats could trigger FloodWait
time.sleep(e.x) # When it happens, wait X seconds and try again
continue
if not chunk.chat_members:
break # No more members left
members.extend(chunk.chat_members)
offset += len(chunk.chat_members)
# Now the "members" list contains all the members of the target chat

View File

@ -1,50 +0,0 @@
"""This is an improved version of get_chat_members.py
Since Telegram will return at most 10.000 members for a single query, this script
repeats the search using numbers ("0" to "9") and all the available ascii letters ("a" to "z").
This can be further improved by also searching for non-ascii characters (e.g.: Japanese script),
as some user names may not contain ascii letters at all.
"""
import time
from string import ascii_lowercase
from pyrogram import Client
from pyrogram.api.errors import FloodWait
app = Client("my_account")
target = "pyrogramchat" # Target channel/supergroup
members = {} # List that will contain all the members of the target chat
limit = 200 # Amount of users to retrieve for each API call (max 200)
# "" + "0123456789" + "abcdefghijklmnopqrstuvwxyz" (as list)
queries = [""] + [str(i) for i in range(10)] + list(ascii_lowercase)
with app:
for q in queries:
print('Searching for "{}"'.format(q))
offset = 0 # For each query, offset restarts from 0
while True:
try:
chunk = app.get_chat_members(target, offset, query=q)
except FloodWait as e: # Very large chats could trigger FloodWait
print("Flood wait: {} seconds".format(e.x))
time.sleep(e.x) # When it happens, wait X seconds and try again
continue
if not chunk.chat_members:
print('Done searching for "{}"'.format(q))
print()
break # No more members left
members.update({i.user.id: i for i in chunk.chat_members})
offset += len(chunk.chat_members)
print("Total members: {}".format(len(members)))
print("Grand total: {}".format(len(members)))
# Now the "members" list contains all the members of the target chat

View File

@ -1,31 +0,0 @@
"""This example shows how to retrieve the full message history of a chat"""
import time
from pyrogram import Client
from pyrogram.api.errors import FloodWait
app = Client("my_account")
target = "me" # "me" refers to your own chat (Saved Messages)
messages = [] # List that will contain all the messages of the target chat
offset_id = 0 # ID of the last message of the chunk
with app:
while True:
try:
m = app.get_history(target, offset_id=offset_id)
except FloodWait as e: # For very large chats the method call can raise a FloodWait
print("waiting {}".format(e.x))
time.sleep(e.x) # Sleep X seconds before continuing
continue
if not m.messages:
break
messages += m.messages
offset_id = m.messages[-1].message_id
print("Messages: {}".format(len(messages)))
# Now the "messages" list contains all the messages sorted by date in
# descending order (from the most recent to the oldest one)

16
examples/hello.py Normal file
View File

@ -0,0 +1,16 @@
"""This example demonstrates a basic API usage"""
from pyrogram import Client
# Create a new Client instance
app = Client("my_account")
with app:
# Send a message, Markdown is enabled by default
app.send_message("me", "Hi there! I'm using **Pyrogram**")
# Send a location
app.send_location("me", 51.500729, -0.124583)
# Send a sticker
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")

View File

@ -1,18 +0,0 @@
"""This example demonstrates a basic API usage"""
from pyrogram import Client
# Create a new Client instance
app = Client("my_account")
# Start the Client before calling any API method
app.start()
# Send a message to yourself, Markdown is enabled by default
app.send_message("me", "Hi there! I'm using **Pyrogram**")
# Send a location to yourself
app.send_location("me", 51.500729, -0.124583)
# Stop the client when you're done
app.stop()

10
examples/history.py Normal file
View File

@ -0,0 +1,10 @@
"""This example shows how to get the full message history of a chat, starting from the latest message"""
from pyrogram import Client
app = Client("my_account")
target = "me" # "me" refers to your own chat (Saved Messages)
with app:
for message in app.iter_history(target):
print(message.text)

59
examples/keyboards.py Normal file
View File

@ -0,0 +1,59 @@
"""This example will show you how to send normal and inline keyboards.
You must log-in as a regular bot in order to send keyboards (use the token from @BotFather).
Any attempt in sending keyboards with a user account will be simply ignored by the server.
send_message() is used as example, but a keyboard can be sent with any other send_* methods,
like send_audio(), send_document(), send_location(), etc...
"""
from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
# Create a client using your bot token
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
with app:
app.send_message(
"haskell", # Edit this
"This is a ReplyKeyboardMarkup example",
reply_markup=ReplyKeyboardMarkup(
[
["A", "B", "C", "D"], # First row
["E", "F", "G"], # Second row
["H", "I"], # Third row
["J"] # Fourth row
],
resize_keyboard=True # Make the keyboard smaller
)
)
app.send_message(
"haskell", # Edit this
"This is a InlineKeyboardMarkup example",
reply_markup=InlineKeyboardMarkup(
[
[ # First row
InlineKeyboardButton( # Generates a callback query when pressed
"Button",
callback_data=b"data"
), # Note how callback_data must be bytes
InlineKeyboardButton( # Opens a web URL
"URL",
url="https://docs.pyrogram.ml"
),
],
[ # Second row
# Opens the inline interface
InlineKeyboardButton(
"Choose chat",
switch_inline_query="pyrogram"
),
InlineKeyboardButton( # Opens the inline interface in the current chat
"Inline here",
switch_inline_query_current_chat="pyrogram"
)
]
]
)
)

View File

@ -1,51 +0,0 @@
"""This example will show you how to send normal and inline keyboards.
You must log-in as a regular bot in order to send keyboards (use the token from @BotFather).
Any attempt in sending keyboards with a user account will be simply ignored by the server.
send_message() is used as example, but a keyboard can be sent with any other send_* methods,
like send_audio(), send_document(), send_location(), etc...
"""
from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
# Create a client using your bot token
app = Client("123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")
app.start()
app.send_message(
"haskell", # Edit this
"This is a ReplyKeyboardMarkup example",
reply_markup=ReplyKeyboardMarkup(
[
["A", "B", "C", "D"], # First row
["E", "F", "G"], # Second row
["H", "I"], # Third row
["J"] # Fourth row
],
resize_keyboard=True # Make the keyboard smaller
)
)
app.send_message(
"haskell", # Edit this
"This is a InlineKeyboardMarkup example",
reply_markup=InlineKeyboardMarkup(
[
[ # First row
# Generates a callback query when pressed
InlineKeyboardButton("Button", callback_data="data"),
# Opens a web URL
InlineKeyboardButton("URL", url="https://docs.pyrogram.ml"),
],
[ # Second row
# Opens the inline interface of a bot in another chat with a pre-defined query
InlineKeyboardButton("Choose chat", switch_inline_query="pyrogram"),
# Same as the button above, but the inline interface is opened in the current chat
InlineKeyboardButton("Inline here", switch_inline_query_current_chat="pyrogram"),
]
]
)
)
app.stop()

View File

@ -6,13 +6,15 @@ to make it only work for specific messages in a specific chat.
from pyrogram import Client, Emoji, Filters
MENTION = "[{}](tg://user?id={})"
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.ml/)'s group chat {}!"
TARGET = "PyrogramChat" # Target chat. Can also be a list of multiple chat ids/usernames
MENTION = "[{}](tg://user?id={})" # User mention markup
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.ml/)'s group chat {}!" # Welcome message
app = Client("my_account")
@app.on_message(Filters.chat("PyrogramChat") & Filters.new_chat_members)
# Filter in only new_chat_members updates generated in TARGET chat
@app.on_message(Filters.chat(TARGET) & Filters.new_chat_members)
def welcome(client, message):
# Build the new members list (with mentions) by using their first_name
new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members]
@ -20,7 +22,7 @@ def welcome(client, message):
# Build the welcome message by using an emoji and the list we built above
text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members))
# Send the welcome message
# Send the welcome message, without the web page preview
message.reply(text, disable_web_page_preview=True)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -18,22 +18,30 @@
import sys
__copyright__ = "Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>".replace(
if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
from .vendor import typing
# 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
__copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>".replace(
"\xe8",
"e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
)
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__version__ = "0.9.2.dev1"
__version__ = "0.12.0.develop"
from .api.errors import Error
from .client.types import (
Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, Update, User, UserStatus,
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, User, UserStatus,
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove,
InlineQuery, InlineQueryResult, InlineQueryResultArticle, InlineQueryResultPhoto, InputTextMessageContent,
InlineQueryResultCachedAudio, InputMessageContent
InlineQueryResultCachedAudio, InputMessageContent, InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton,
ReplyKeyboardMarkup, ReplyKeyboardRemove, Poll, PollOption, ChatPreview, StopPropagation, ContinuePropagation,
Game, CallbackGame, GameHighScore, GameHighScores, ChatPermissions
)
from .client import (
Client, ChatAction, ParseMode, Emoji,

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -19,14 +19,16 @@
from collections import OrderedDict
from datetime import datetime
from io import BytesIO
from json import JSONEncoder, dumps
from ..all import objects
from json import dumps
class Object:
all = {}
__slots__ = []
QUALNAME = "Base"
@staticmethod
def read(b: BytesIO, *args):
return Object.all[int.from_bytes(b.read(4), "little")].read(b, *args)
@ -35,7 +37,7 @@ class Object:
pass
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
@ -62,29 +64,18 @@ def remove_none(obj):
return obj
class Encoder(JSONEncoder):
def default(self, o: Object):
try:
content = o.__dict__
except AttributeError:
if isinstance(o, datetime):
return o.strftime("%d-%b-%Y %H:%M:%S")
else:
return repr(o)
def default(o: "Object"):
try:
content = {i: getattr(o, i) for i in o.__slots__}
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()]
)
return remove_none(
OrderedDict(
[("_", o.QUALNAME)]
+ [i for i in content.items()]
)
)
except AttributeError:
if isinstance(o, datetime):
return o.strftime("%d-%b-%Y %H:%M:%S")
else:
return None
return repr(o)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -22,6 +22,7 @@ from collections import OrderedDict
from queue import Queue
from threading import Thread
import pyrogram
from pyrogram.api import types
from ..ext import utils
from ..handlers import (
@ -43,7 +44,7 @@ class Dispatcher:
types.UpdateEditChannelMessage
)
DELETE_MESSAGE_UPDATES = (
DELETE_MESSAGES_UPDATES = (
types.UpdateDeleteMessages,
types.UpdateDeleteChannelMessages
)
@ -55,34 +56,34 @@ class Dispatcher:
MESSAGE_UPDATES = NEW_MESSAGE_UPDATES + EDIT_MESSAGE_UPDATES
UPDATES = None
def __init__(self, client, workers: int):
self.client = client
self.workers = workers
self.workers_list = []
self.updates = Queue()
self.updates_queue = Queue()
self.groups = OrderedDict()
Dispatcher.UPDATES = {
self.update_parsers = {
Dispatcher.MESSAGE_UPDATES:
lambda upd, usr, cht: (utils.parse_messages(self.client, upd.message, usr, cht), MessageHandler),
lambda upd, usr, cht: (pyrogram.Message._parse(self.client, upd.message, usr, cht), MessageHandler),
Dispatcher.DELETE_MESSAGE_UPDATES:
lambda upd, usr, cht: (utils.parse_deleted_messages(upd), DeletedMessagesHandler),
Dispatcher.DELETE_MESSAGES_UPDATES:
lambda upd, usr, cht: (pyrogram.Messages._parse_deleted(self.client, upd), DeletedMessagesHandler),
Dispatcher.CALLBACK_QUERY_UPDATES:
lambda upd, usr, cht: (utils.parse_callback_query(self.client, upd, usr), CallbackQueryHandler),
lambda upd, usr, cht: (pyrogram.CallbackQuery._parse(self.client, upd, usr), CallbackQueryHandler),
(types.UpdateUserStatus,):
lambda upd, usr, cht: (utils.parse_user_status(upd.status, upd.user_id), UserStatusHandler),
lambda upd, usr, cht: (
pyrogram.UserStatus._parse(self.client, upd.status, upd.user_id), UserStatusHandler
),
(types.UpdateBotInlineQuery,):
lambda upd, usr, cht: (utils.parse_inline_query(self.client, upd, usr), InlineQueryHandler)
}
Dispatcher.UPDATES = {key: value for key_tuple, value in Dispatcher.UPDATES.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}
def start(self):
for i in range(self.workers):
@ -97,7 +98,7 @@ class Dispatcher:
def stop(self):
for _ in range(self.workers):
self.updates.put(None)
self.updates_queue.put(None)
for worker in self.workers_list:
worker.join()
@ -122,7 +123,7 @@ class Dispatcher:
log.debug("{} started".format(name))
while True:
update = self.updates.get()
update = self.updates_queue.get()
if update is None:
break
@ -132,32 +133,39 @@ class Dispatcher:
chats = {i.id: i for i in update[2]}
update = update[0]
parser = Dispatcher.UPDATES.get(type(update), None)
parser = self.update_parsers.get(type(update), None)
if parser is None:
continue
update, handler_type = parser(update, users, chats)
parsed_update, handler_type = (
parser(update, users, chats)
if parser is not None
else (None, type(None))
)
for group in self.groups.values():
for handler in group:
args = None
if isinstance(handler, RawUpdateHandler):
if isinstance(handler, handler_type):
if handler.check(parsed_update):
args = (parsed_update,)
elif isinstance(handler, RawUpdateHandler):
args = (update, users, chats)
elif isinstance(handler, handler_type):
if handler.check(update):
args = (update,)
if args is None:
continue
try:
handler.callback(self.client, *args)
except pyrogram.StopPropagation:
raise
except pyrogram.ContinuePropagation:
continue
except Exception as e:
log.error(e, exc_info=True)
finally:
break
break
except pyrogram.StopPropagation:
pass
except Exception as e:
log.error(e, exc_info=True)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -23,12 +23,13 @@ from threading import Lock
from pyrogram import __version__
from ..style import Markdown, HTML
from ...api.core import Object
from ...session import Session
from ...session.internals import MsgId
class BaseClient:
class StopTransmission(StopIteration):
pass
APP_VERSION = "Pyrogram \U0001f525 {}".format(__version__)
DEVICE_MODEL = "{} {}".format(
@ -67,7 +68,7 @@ class BaseClient:
}
def __init__(self):
self.bot_token = None
self.is_bot = None
self.dc_id = None
self.auth_key = None
self.user_id = None
@ -90,6 +91,8 @@ class BaseClient:
self.is_started = None
self.is_idle = None
self.takeout_id = None
self.updates_queue = Queue()
self.updates_workers_list = []
self.download_queue = Queue()
@ -97,30 +100,32 @@ class BaseClient:
self.disconnect_handler = None
def send(self, data: Object, retries: int = Session.MAX_RETRIES, timeout: float = Session.WAIT_TIMEOUT):
def send(self, *args, **kwargs):
pass
def resolve_peer(self, peer_id: int or str):
def resolve_peer(self, *args, **kwargs):
pass
def add_handler(self, handler, group: int = 0) -> tuple:
def fetch_peers(self, *args, **kwargs):
pass
def save_file(
self,
path: str,
file_id: int = None,
file_part: int = 0,
progress: callable = None,
progress_args: tuple = ()
):
def add_handler(self, *args, **kwargs):
pass
def get_messages(
self,
chat_id: int or str,
message_ids: int or list = None,
reply_to_message_ids: int or list = None,
replies: int = 1
):
def save_file(self, *args, **kwargs):
pass
def get_messages(self, *args, **kwargs):
pass
def get_history(self, *args, **kwargs):
pass
def get_dialogs(self, *args, **kwargs):
pass
def get_chat_members(self, *args, **kwargs):
pass
def get_chat_members_count(self, *args, **kwargs):
pass

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -94,6 +94,7 @@ class Syncer:
auth_key=auth_key,
user_id=client.user_id,
date=int(time.time()),
is_bot=client.is_bot,
peers_by_id={
k: getattr(v, "access_hash", None)
for k, v in client.peers_by_id.copy().items()

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -61,14 +61,17 @@ class Filters:
create = create
me = create("Me", lambda _, m: bool(m.from_user and m.from_user.is_self))
"""Filter messages generated by you yourself."""
bot = create("Bot", lambda _, m: bool(m.from_user and m.from_user.is_bot))
"""Filter messages coming from bots"""
"""Filter messages coming from bots."""
incoming = create("Incoming", lambda _, m: not m.outgoing)
"""Filter incoming messages."""
"""Filter incoming messages. Messages sent to your own chat (Saved Messages) are also recognised as incoming."""
outgoing = create("Outgoing", lambda _, m: m.outgoing)
"""Filter outgoing messages."""
"""Filter outgoing messages. Messages sent to your own chat (Saved Messages) are not recognized as outgoing."""
text = create("Text", lambda _, m: bool(m.text))
"""Filter text messages."""
@ -86,37 +89,49 @@ class Filters:
"""Filter edited messages."""
audio = create("Audio", lambda _, m: bool(m.audio))
"""Filter messages that contain :obj:`Audio <pyrogram.api.types.pyrogram.Audio>` objects."""
"""Filter messages that contain :obj:`Audio <pyrogram.Audio>` objects."""
document = create("Document", lambda _, m: bool(m.document))
"""Filter messages that contain :obj:`Document <pyrogram.api.types.pyrogram.Document>` objects."""
"""Filter messages that contain :obj:`Document <pyrogram.Document>` objects."""
photo = create("Photo", lambda _, m: bool(m.photo))
"""Filter messages that contain :obj:`Photo <pyrogram.api.types.pyrogram.PhotoSize>` objects."""
"""Filter messages that contain :obj:`Photo <pyrogram.PhotoSize>` objects."""
sticker = create("Sticker", lambda _, m: bool(m.sticker))
"""Filter messages that contain :obj:`Sticker <pyrogram.api.types.pyrogram.Sticker>` objects."""
"""Filter messages that contain :obj:`Sticker <pyrogram.Sticker>` objects."""
animation = create("GIF", lambda _, m: bool(m.animation))
"""Filter messages that contain :obj:`Animation <pyrogram.api.types.pyrogram.Animation>` objects."""
animation = create("Animation", lambda _, m: bool(m.animation))
"""Filter messages that contain :obj:`Animation <pyrogram.Animation>` objects."""
game = create("Game", lambda _, m: bool(m.game))
"""Filter messages that contain :obj:`Game <pyrogram.Game>` objects."""
video = create("Video", lambda _, m: bool(m.video))
"""Filter messages that contain :obj:`Video <pyrogram.api.types.pyrogram.Video>` objects."""
"""Filter messages that contain :obj:`Video <pyrogram.Video>` objects."""
media_group = create("MediaGroup", lambda _, m: bool(m.media_group_id))
"""Filter messages containing photos or videos being part of an album."""
voice = create("Voice", lambda _, m: bool(m.voice))
"""Filter messages that contain :obj:`Voice <pyrogram.api.types.pyrogram.Voice>` note objects."""
"""Filter messages that contain :obj:`Voice <pyrogram.Voice>` note objects."""
video_note = create("Voice", lambda _, m: bool(m.video_note))
"""Filter messages that contain :obj:`VideoNote <pyrogram.api.types.pyrogram.VideoNote>` objects."""
"""Filter messages that contain :obj:`VideoNote <pyrogram.VideoNote>` objects."""
contact = create("Contact", lambda _, m: bool(m.contact))
"""Filter messages that contain :obj:`Contact <pyrogram.api.types.pyrogram.Contact>` objects."""
"""Filter messages that contain :obj:`Contact <pyrogram.Contact>` objects."""
location = create("Location", lambda _, m: bool(m.location))
"""Filter messages that contain :obj:`Location <pyrogram.api.types.pyrogram.Location>` objects."""
"""Filter messages that contain :obj:`Location <pyrogram.Location>` objects."""
venue = create("Venue", lambda _, m: bool(m.venue))
"""Filter messages that contain :obj:`Venue <pyrogram.api.types.pyrogram.Venue>` objects."""
"""Filter messages that contain :obj:`Venue <pyrogram.Venue>` objects."""
web_page = create("WebPage", lambda _, m: m.web_page)
"""Filter messages sent with a webpage preview."""
poll = create("Poll", lambda _, m: m.poll)
"""Filter messages that contain :obj:`Poll <pyrogram.Poll>` objects."""
private = create("Private", lambda _, m: bool(m.chat and m.chat.type == "private"))
"""Filter messages sent in private chats."""
@ -160,6 +175,9 @@ class Filters:
pinned_message = create("PinnedMessage", lambda _, m: bool(m.pinned_message))
"""Filter service messages for pinned messages."""
game_high_score = create("GameHighScore", lambda _, m: bool(m.game_high_score))
"""Filter service messages for game high scores."""
reply_keyboard = create("ReplyKeyboard", lambda _, m: isinstance(m.reply_markup, ReplyKeyboardMarkup))
"""Filter messages containing reply keyboard markups"""
@ -169,6 +187,9 @@ class Filters:
mentioned = create("Mentioned", lambda _, m: bool(m.mentioned))
"""Filter messages containing mentions"""
via_bot = create("ViaBot", lambda _, m: bool(m.via_bot))
"""Filter messages sent via inline bots"""
service = create("Service", lambda _, m: bool(m.service))
"""Filter service messages. A service message contains any of the following fields set
@ -181,7 +202,8 @@ class Filters:
- channel_chat_created
- migrate_to_chat_id
- migrate_from_chat_id
- pinned_message"""
- pinned_message
- game_score"""
media = create("Media", lambda _, m: bool(m.media))
"""Filter media messages. A media message contains any of the following fields set
@ -196,7 +218,8 @@ class Filters:
- video_note
- contact
- location
- venue"""
- venue
- poll"""
@staticmethod
def command(command: str or list,
@ -267,7 +290,7 @@ class Filters:
"""
def f(_, m):
m.matches = [i for i in _.p.finditer(m.text or "")]
m.matches = [i for i in _.p.finditer(m.text or m.caption or "")]
return bool(m.matches)
return create("Regex", f, p=re.compile(pattern, flags))

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -45,10 +45,3 @@ class CallbackQueryHandler(Handler):
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
)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -48,8 +48,4 @@ class DeletedMessagesHandler(Handler):
super().__init__(callback, filters)
def check(self, messages):
return (
self.filters(messages.messages[0])
if callable(self.filters)
else True
)
return super().check(messages.messages[0])

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -21,3 +21,10 @@ class Handler:
def __init__(self, callback: callable, filters=None):
self.callback = callback
self.filters = filters
def check(self, update):
return (
self.filters(update)
if callable(self.filters)
else True
)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -46,10 +46,3 @@ class MessageHandler(Handler):
def __init__(self, callback: callable, filters=None):
super().__init__(callback, filters)
def check(self, message):
return (
self.filters(message)
if callable(self.filters)
else True
)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -45,10 +45,3 @@ class UserStatusHandler(Handler):
def __init__(self, callback: callable, filters=None):
super().__init__(callback, filters)
def check(self, user_status):
return (
self.filters(user_status)
if callable(self.filters)
else True
)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -23,7 +23,6 @@ from .decorators import Decorators
from .messages import Messages
from .password import Password
from .users import Users
from .utilities import Utilities
class Methods(
@ -32,7 +31,6 @@ class Methods(
Password,
Chats,
Users,
Utilities,
Messages,
Decorators
):

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -18,9 +18,12 @@
from .answer_callback_query import AnswerCallbackQuery
from .answer_inline_query import AnswerInlineQuery
from .get_game_high_scores import GetGameHighScores
from .get_inline_bot_results import GetInlineBotResults
from .request_callback_answer import RequestCallbackAnswer
from .send_game import SendGame
from .send_inline_bot_result import SendInlineBotResult
from .set_game_score import SetGameScore
class Bots(
@ -28,6 +31,9 @@ class Bots(
AnswerInlineQuery,
GetInlineBotResults,
RequestCallbackAnswer,
SendInlineBotResult
SendInlineBotResult,
SendGame,
SetGameScore,
GetGameHighScores
):
pass

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -21,12 +21,14 @@ from pyrogram.client.ext import BaseClient
class AnswerCallbackQuery(BaseClient):
def answer_callback_query(self,
callback_query_id: str,
text: str = None,
show_alert: bool = None,
url: str = None,
cache_time: int = 0):
def answer_callback_query(
self,
callback_query_id: str,
text: str = None,
show_alert: bool = None,
url: str = None,
cache_time: int = 0
):
"""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.

View File

@ -0,0 +1,68 @@
# 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
import pyrogram
from pyrogram.api import functions
from pyrogram.client.ext import BaseClient
class GetGameHighScores(BaseClient):
def get_game_high_scores(
self,
user_id: Union[int, str],
chat_id: Union[int, str],
message_id: int = None
):
"""Use this method to get data for high score tables.
Args:
user_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
chat_id (``int`` | ``str``, *optional*):
Unique identifier (int) or username (str) of the target chat.
For your personal cloud (Saved Messages) you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).
Required if inline_message_id is not specified.
message_id (``int``, *optional*):
Identifier of the sent message.
Required if inline_message_id is not specified.
Returns:
On success, a :obj:`GameHighScores <pyrogram.GameHighScores>` object is returned.
Raises:
:class:`Error <pyrogram.Error>` in case of a Telegram RPC error.
"""
# TODO: inline_message_id
return pyrogram.GameHighScores._parse(
self,
self.send(
functions.messages.GetGameHighScores(
peer=self.resolve_peer(chat_id),
id=message_id,
user_id=self.resolve_peer(user_id)
)
)
)

Some files were not shown because too many files have changed in this diff Show More