Merge branch 'develop' into session_storage

# Conflicts:
#	pyrogram/client/client.py
#	pyrogram/client/ext/base_client.py
#	pyrogram/client/ext/syncer.py
#	pyrogram/client/methods/contacts/get_contacts.py
This commit is contained in:
Dan 2019-06-15 23:52:34 +02:00
commit 142d5ab335
313 changed files with 9183 additions and 4943 deletions

76
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at dan@pyrogram.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

1
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1 @@
# How to Contribute

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: delivrance
custom: https://docs.pyrogram.org/support-pyrogram

21
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,21 @@
---
name: Bug Report
about: Create a bug report affecting the library
labels: "bug"
---
<!-- WARNING: Ignoring this template could lead to the issue being closed as incomplete -->
## Checklist
- [ ] I am sure the error is coming from Pyrogram's code and not elsewhere.
- [ ] I have searched in the issue tracker for similar bug reports, including closed ones.
- [ ] I ran `pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip` and reproduced the issue using the latest development version.
## Description
A clear and concise description of the problem.
## Steps to Reproduce
[A minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example).
## Traceback
The full traceback (if applicable).

View File

@ -0,0 +1,14 @@
---
name: Feature Request
about: Suggest ideas, new features or enhancements
labels: "enhancement"
---
<!-- WARNING: Ignoring this template could lead to the issue being closed as incomplete -->
## Checklist
- [ ] I believe the idea is awesome and would benefit the library.
- [ ] I have searched in the issue tracker for similar requests, including closed ones.
## Description
A detailed description of the request.

15
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@ -0,0 +1,15 @@
---
name: Ask Question
about: Ask a Pyrogram related question
title: For Q&A purposes, please read this template body
labels: "question"
---
<!-- WARNING: Ignoring this template could lead to the issue being closed as incomplete -->
# Important
This place is for issues about Pyrogram, it's **not a forum**.
If you'd like to post a question, please move to https://stackoverflow.com or join the Telegram community at https://t.me/pyrogram. Useful information on how to ask good questions can be found here: https://stackoverflow.com/help/how-to-ask.
Thanks.

2
.gitignore vendored
View File

@ -3,7 +3,7 @@
config.ini
# Pyrogram generated code
pyrogram/api/errors/exceptions/
pyrogram/errors/exceptions/
pyrogram/api/functions/
pyrogram/api/types/
pyrogram/api/all.py

View File

@ -1,6 +1,7 @@
## Include
include COPYING COPYING.lesser NOTICE requirements.txt
include README.md COPYING COPYING.lesser NOTICE requirements.txt
recursive-include compiler *.py *.tl *.tsv *.txt
recursive-include pyrogram mime.types
## Exclude
prune pyrogram/api/errors/exceptions

85
README.md Normal file
View File

@ -0,0 +1,85 @@
<p align="center">
<a href="https://github.com/pyrogram/pyrogram">
<img src="https://i.imgur.com/BOgY9ai.png" alt="Pyrogram">
</a>
<br>
<b>Telegram MTProto API Framework for Python</b>
<br>
<a href="https://docs.pyrogram.org">
Documentation
</a>
<a href="https://github.com/pyrogram/pyrogram/releases">
Releases
</a>
<a href="https://t.me/Pyrogram">
Community
</a>
</p>
## Pyrogram
``` python
from pyrogram import Client, Filters
app = Client("my_account")
@app.on_message(Filters.private)
def hello(client, message):
message.reply("Hello {}".format(message.from_user.first_name))
app.run()
```
**Pyrogram** is an elegant, easy-to-use [Telegram](https://telegram.org/) client library and framework written from the
ground up in Python and C. It enables you to easily create custom apps for both user and bot identities (bot API alternative) via the [MTProto API](https://core.telegram.org/api#telegram-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**: 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](https://github.com/pyrogram/tgcrypto), a high-performance library
written in pure C.
- **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 make use of the latest Telegram API version and features.
- **Bot API-like**: Similar to the Bot API in its simplicity, but much more powerful and detailed.
- **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
- Python 3.4 or higher.
- A [Telegram API key](https://docs.pyrogram.org/intro/setup#api-keys).
### Installing
``` bash
pip3 install pyrogram
```
### Resources
- The Docs contain lots of resources to help you getting started with Pyrogram: https://docs.pyrogram.org.
- Reading [Examples in this repository](https://github.com/pyrogram/pyrogram/tree/master/examples) is also a good way
for learning how Pyrogram works.
- Seeking extra help? Don't be shy, come join and ask our [Community](https://t.me/PyrogramChat)!
- For other requests you can send an [Email](mailto:dan@pyrogram.org) or a [Message](https://t.me/haskell).
### Contributing
Pyrogram is brand new, and **you are welcome to try it and help make it even better** by either submitting pull
requests or reporting issues/bugs as well as suggesting best practices, ideas, enhancements on both code
and documentation. Any help is appreciated!
### Copyright & License
- 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+)](COPYING.lesser)

View File

@ -1,131 +0,0 @@
|header|
Pyrogram
========
.. code-block:: python
from pyrogram import Client, Filters
app = Client("my_account")
@app.on_message(Filters.private)
def hello(client, message):
message.reply("Hello {}".format(message.from_user.first_name))
app.run()
**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**: 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.
- **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 97 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
------------
- Python 3.4 or higher.
- A `Telegram API key`_.
Installing
----------
.. code:: shell
pip3 install pyrogram
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 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_.
Contributing
------------
Pyrogram is brand new, and **you are welcome to try it and help make it even better** by either submitting pull
requests or reporting issues/bugs as well as suggesting best practices, ideas, enhancements on both code
and documentation. Any help is appreciated!
Copyright & License
-------------------
- 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 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
<h1 align="center">
<a href="https://github.com/pyrogram/pyrogram">
<div><img src="https://raw.githubusercontent.com/pyrogram/logos/master/logos/pyrogram_logo2.png" alt="Pyrogram Logo"></div>
</a>
</h1>
<p align="center">
<b>Telegram MTProto API Framework for Python</b>
<br>
<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%2097-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 Version">
</a>
</p>
.. |logo| image:: https://raw.githubusercontent.com/pyrogram/logos/master/logos/pyrogram_logo2.png
:target: https://pyrogram.ml
:alt: Pyrogram
.. |description| replace:: **Telegram MTProto API Framework for Python**
.. |schema| image:: https://img.shields.io/badge/schema-layer%2097-eda738.svg?longCache=true&colorA=262b30
:target: compiler/api/source/main_api.tl
:alt: Schema Layer
.. |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 Version

View File

@ -53,10 +53,10 @@ def get_docstring_arg_type(t: str, is_list: bool = False, is_pyrogram_type: bool
return "``{}``".format(t.lower())
elif t == "true":
return "``bool``"
elif t == "Object" or t == "X":
return "Any object from :obj:`pyrogram.api.types`"
elif t == "TLObject" or t == "X":
return "Any object from :obj:`~pyrogram.api.types`"
elif t == "!X":
return "Any method from :obj:`pyrogram.api.functions`"
return "Any method from :obj:`~pyrogram.api.functions`"
elif t.startswith("Vector"):
return "List of " + get_docstring_arg_type(t.split("<", 1)[1][:-1], True, is_pyrogram_type)
else:
@ -288,9 +288,9 @@ def start():
sorted_args = sort_args(c.args)
arguments = (
", "
+ ("*, " if c.args else "")
+ (", ".join([get_argument_type(i) for i in sorted_args if i != ("flags", "#")]) if c.args else "")
", "
+ ("*, " if c.args else "")
+ (", ".join([get_argument_type(i) for i in sorted_args if i != ("flags", "#")]) if c.args else "")
)
fields = "\n ".join(
@ -328,15 +328,16 @@ def start():
)
if docstring_args:
docstring_args = "Args:\n " + "\n ".join(docstring_args)
docstring_args = "Parameters:\n " + "\n ".join(docstring_args)
else:
docstring_args = "No parameters required."
docstring_args = "Attributes:\n ID: ``{}``\n\n ".format(c.id) + docstring_args
docstring_args = "Attributes:\n LAYER: ``{}``\n\n ".format(layer) + docstring_args
if c.section == "functions":
docstring_args += "\n\n Raises:\n :obj:`RPCError <pyrogram.RPCError>`"
docstring_args += "\n\n Returns:\n " + get_docstring_arg_type(c.return_type)
else:
references = get_references(".".join(filter(None, [c.namespace, c.name])))
@ -393,7 +394,7 @@ def start():
)
read_types += "\n "
read_types += "{} = Object.read(b{}) if flags & (1 << {}) else []\n ".format(
read_types += "{} = TLObject.read(b{}) if flags & (1 << {}) else []\n ".format(
arg_name, ", {}".format(sub_type.title()) if sub_type in core_types else "", index
)
else:
@ -402,7 +403,7 @@ def start():
write_types += "b.write(self.{}.write())\n ".format(arg_name)
read_types += "\n "
read_types += "{} = Object.read(b) if flags & (1 << {}) else None\n ".format(
read_types += "{} = TLObject.read(b) if flags & (1 << {}) else None\n ".format(
arg_name, index
)
else:
@ -421,7 +422,7 @@ def start():
)
read_types += "\n "
read_types += "{} = Object.read(b{})\n ".format(
read_types += "{} = TLObject.read(b{})\n ".format(
arg_name, ", {}".format(sub_type.title()) if sub_type in core_types else ""
)
else:
@ -429,7 +430,7 @@ def start():
write_types += "b.write(self.{}.write())\n ".format(arg_name)
read_types += "\n "
read_types += "{} = Object.read(b)\n ".format(arg_name)
read_types += "{} = TLObject.read(b)\n ".format(arg_name)
if c.docs:
description = c.docs.split("|")[0].split("§")[1]
@ -462,7 +463,7 @@ def start():
["{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)
qualname="{}.{}{}".format(c.section, "{}.".format(c.namespace) if c.namespace else "", c.name)
)
)

View File

@ -22,10 +22,13 @@ inputPeerSelf#7da07ec9 = InputPeer;
inputPeerChat#179be863 chat_id:int = InputPeer;
inputPeerUser#7b8e7de6 user_id:int access_hash:long = InputPeer;
inputPeerChannel#20adaef8 channel_id:int access_hash:long = InputPeer;
inputPeerUserFromMessage#17bae2e6 peer:InputPeer msg_id:int user_id:int = InputPeer;
inputPeerChannelFromMessage#9c95f7bb peer:InputPeer msg_id:int channel_id:int = InputPeer;
inputUserEmpty#b98886cf = InputUser;
inputUserSelf#f7c1b13f = InputUser;
inputUser#d8292816 user_id:int access_hash:long = InputUser;
inputUserFromMessage#2d117597 peer:InputPeer msg_id:int user_id:int = InputUser;
inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
@ -60,9 +63,12 @@ inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#196683d9 id:long access_hash:long file_reference:bytes = InputFileLocation;
inputDocumentFileLocation#bad07584 id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
inputTakeoutFileLocation#29be5899 = InputFileLocation;
inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputPeerPhotoFileLocation#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation;
inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation;
peerUser#9db1bc6d user_id:int = Peer;
peerChat#bad0e5bb chat_id:int = Peer;
@ -79,14 +85,11 @@ storage.fileMov#4b09ebbc = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;
fileLocationUnavailable#7c596b46 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 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;
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 scam:flags.24?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;
userProfilePhoto#ecd75d8c photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto;
userStatusEmpty#9d05049 = UserStatus;
userStatusOnline#edb93949 expires:int = UserStatus;
@ -98,11 +101,11 @@ userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#9ba2d800 id:int = 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#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;
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 scam:flags.19?true has_link:flags.20?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#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;
chatFull#1b7c9db3 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 folder_id:flags.11?int = ChatFull;
channelFull#9882e516 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 folder_id:flags.11?int linked_chat_id:flags.13?int pts:int = ChatFull;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
@ -112,11 +115,11 @@ chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0?
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
chatPhoto#475cdbd5 photo_small:FileLocation photo_big:FileLocation dc_id:int = 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 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;
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 legacy:flags.19?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 legacy:flags.19?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;
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
@ -147,7 +150,7 @@ messageActionHistoryClear#9fbab604 = MessageAction;
messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
messageActionPhoneCall#80e11a7f flags:# call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionScreenshotTaken#4792929b = MessageAction;
messageActionCustomAction#fae69f56 message:string = MessageAction;
messageActionBotAllowed#abe9affe domain:string = MessageAction;
@ -155,10 +158,11 @@ messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:
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;
dialog#2c171f72 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 folder_id:flags.4?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
photoEmpty#2331b22d id:long = Photo;
photo#9c477dd8 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> = Photo;
photo#d07504a5 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> dc_id:int = Photo;
photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
@ -196,7 +200,7 @@ inputReportReasonChildAbuse#adf44ee3 = ReportReason;
inputReportReasonOther#e1746d0a text:string = ReportReason;
inputReportReasonCopyright#9b89f93a = ReportReason;
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;
userFull#745559cc 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 folder_id:flags.11?int = UserFull;
contact#f911c994 user_id:int mutual:Bool = Contact;
@ -221,7 +225,7 @@ 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#a6c47aaa flags:# inexact:flags.1?true count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#c8edce1e flags:# inexact:flags.1?true count:int next_rate:flags.0?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;
@ -271,14 +275,14 @@ updateNotifySettings#bec268ef peer:NotifyPeer notify_settings:PeerNotifySettings
updateServiceNotification#ebe46819 flags:# popup:flags.0?true inbox_date:flags.1?int type:string message:string media:MessageMedia entities:Vector<MessageEntity> = Update;
updatePrivacy#ee3b272a key:PrivacyKey rules:Vector<PrivacyRule> = Update;
updateUserPhone#12b9417b user_id:int phone:string = Update;
updateReadHistoryInbox#9961fd5c peer:Peer max_id:int pts:int pts_count:int = Update;
updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update;
updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update;
updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update;
updateReadMessagesContents#68c13933 messages:Vector<int> pts:int pts_count:int = Update;
updateChannelTooLong#eb0467fb flags:# channel_id:int pts:flags.0?int = Update;
updateChannel#b6d45656 channel_id:int = Update;
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
updateReadChannelInbox#4214f37f channel_id:int max_id:int = Update;
updateReadChannelInbox#330b5424 flags:# folder_id:flags.0?int channel_id:int max_id:int still_unread_count:int pts: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;
updateChatParticipantAdmin#b6901959 chat_id:int user_id:int is_admin:Bool version:int = Update;
@ -300,8 +304,8 @@ updateRecentStickers#9a422c20 = Update;
updateConfig#a229dd06 = Update;
updatePtsChanged#3354678f = Update;
updateChannelWebPage#40771900 channel_id:int webpage:WebPage pts:int pts_count:int = Update;
updateDialogPinned#19d27f3c flags:# pinned:flags.0?true peer:DialogPeer = Update;
updatePinnedDialogs#ea4cb65b flags:# order:flags.0?Vector<DialogPeer> = Update;
updateDialogPinned#6e6fe51c flags:# pinned:flags.0?true folder_id:flags.1?int peer:DialogPeer = Update;
updatePinnedDialogs#fa0f3ca2 flags:# folder_id:flags.1?int order:flags.0?Vector<DialogPeer> = Update;
updateBotWebhookJSON#8317c0c3 data:DataJSON = Update;
updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update;
updateBotShippingQuery#e0cdc940 query_id:long user_id:int payload:bytes shipping_address:PostAddress = Update;
@ -318,6 +322,7 @@ updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -344,7 +349,7 @@ 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#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;
config#330b4067 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 pinned_infolder_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;
@ -413,6 +418,7 @@ inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
inputPrivacyKeyPhoneNumber#352dafa = InputPrivacyKey;
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
privacyKeyChatInvite#500e6dfa = PrivacyKey;
@ -420,6 +426,7 @@ privacyKeyPhoneCall#3d662b7b = PrivacyKey;
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
privacyKeyForwards#69ec56a3 = PrivacyKey;
privacyKeyProfilePhoto#96151fed = PrivacyKey;
privacyKeyPhoneNumber#d19ae46d = PrivacyKey;
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
@ -427,6 +434,8 @@ inputPrivacyValueAllowUsers#131cc67f users:Vector<InputUser> = InputPrivacyRule;
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
inputPrivacyValueAllowChatParticipants#4c81c1ba chats:Vector<int> = InputPrivacyRule;
inputPrivacyValueDisallowChatParticipants#d82363af chats:Vector<int> = InputPrivacyRule;
privacyValueAllowContacts#fffe1bac = PrivacyRule;
privacyValueAllowAll#65427b82 = PrivacyRule;
@ -434,8 +443,10 @@ privacyValueAllowUsers#4d5bbe0c users:Vector<int> = PrivacyRule;
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
privacyValueDisallowAll#8b73e763 = PrivacyRule;
privacyValueDisallowUsers#c7f49b7 users:Vector<int> = PrivacyRule;
privacyValueAllowChatParticipants#18be796b chats:Vector<int> = PrivacyRule;
privacyValueDisallowChatParticipants#acae0690 chats:Vector<int> = PrivacyRule;
account.privacyRules#554abb6f rules:Vector<PrivacyRule> users:Vector<User> = account.PrivacyRules;
account.privacyRules#50a04e45 rules:Vector<PrivacyRule> chats:Vector<Chat> users:Vector<User> = account.PrivacyRules;
accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;
@ -459,7 +470,6 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess
contactLinkUnknown#5f4f9247 = ContactLink;
contactLinkNone#feedd3ad = ContactLink;
contactLinkHasPhone#268f3f59 = ContactLink;
contactLinkContact#d502c2d0 = ContactLink;
webPageEmpty#eb1477e8 id:long = WebPage;
@ -485,13 +495,13 @@ chatInviteEmpty#69df3769 = ExportedChatInvite;
chatInviteExported#fc2e05bc link:string = ExportedChatInvite;
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#db74f558 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:ChatPhoto participants_count:int participants:flags.4?Vector<User> = ChatInvite;
chatInvite#dfc2f58e flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:Photo participants_count:int participants:flags.4?Vector<User> = ChatInvite;
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
stickerSet#6a90bcb7 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize count:int hash:int = StickerSet;
stickerSet#eeb46f27 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
@ -507,6 +517,8 @@ keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
keyboardButtonGame#50f41ccf text:string = KeyboardButton;
keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton;
inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton;
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
@ -533,13 +545,14 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
inputChannelFromMessage#2a286531 peer:InputPeer msg_id:int channel_id:int = InputChannel;
contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector<Chat> users:Vector<User> = contacts.ResolvedPeer;
messageRange#ae30253 min_id:int max_id:int = MessageRange;
updates.channelDifferenceEmpty#3e11affb flags:# final:flags.0?true pts:int timeout:flags.1?int = updates.ChannelDifference;
updates.channelDifferenceTooLong#6a9d7b35 flags:# final:flags.0?true pts:int timeout:flags.1?int top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
updates.channelDifferenceTooLong#a4bcc6fe flags:# final:flags.0?true timeout:flags.1?int dialog:Dialog messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:flags.1?int new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
@ -628,6 +641,8 @@ topPeerCategoryCorrespondents#637b7ed = TopPeerCategory;
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
topPeerCategoryChannels#161d9628 = TopPeerCategory;
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;
topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;
@ -767,11 +782,11 @@ inputStickerSetItem#ffa0a496 flags:# document:InputDocument emoji:string mask_co
inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall;
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#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;
phoneCallWaiting#1b8f4ad1 flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall;
phoneCallRequested#87eabb53 flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall;
phoneCallAccepted#997c454a flags:# video:flags.5?true id:long access_hash:long date:int admin_id:int participant_id:int g_b:bytes protocol:PhoneCallProtocol = PhoneCall;
phoneCall#8742ae7f 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 connections:Vector<PhoneConnection> start_date:int = PhoneCall;
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.5?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;
@ -797,7 +812,7 @@ langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:fl
channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangePhoto#b82f55c3 prev_photo:ChatPhoto new_photo:ChatPhoto = ChannelAdminLogEventAction;
channelAdminLogEventActionChangePhoto#434bd2af prev_photo:Photo new_photo:Photo = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleInvites#1b7907ae new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction;
@ -812,6 +827,7 @@ channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputSticker
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeLinkedChat#a26f881b prev_value:int new_value:int = ChannelAdminLogEventAction;
channelAdminLogEvent#3b5a3e40 id:long date:int user_id:int action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
@ -843,8 +859,10 @@ inputMessageReplyTo#bad88395 id:int = InputMessage;
inputMessagePinned#86872538 = InputMessage;
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
inputDialogPeerFolder#64600527 folder_id:int = InputDialogPeer;
dialogPeer#e56dbf05 peer:Peer = DialogPeer;
dialogPeerFolder#514519e2 folder_id:int = DialogPeer;
messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
messages.foundStickerSets#5108d648 hash:int sets:Vector<StickerSetCovered> = messages.FoundStickerSets;
@ -1000,6 +1018,22 @@ emojiKeywordsDifference#5cc761bd lang_code:string from_version:int version:int k
emojiURL#a575739d url:string = EmojiURL;
emojiLanguage#b3fb5361 lang_code:string = EmojiLanguage;
fileLocationToBeDeprecated#bc7fc6cd volume_id:long local_id:int = FileLocation;
folder#ff544e65 flags:# autofill_new_broadcasts:flags.0?true autofill_public_groups:flags.1?true autofill_new_correspondents:flags.2?true id:int title:string photo:flags.3?ChatPhoto = Folder;
inputFolderPeer#fbd2c296 peer:InputPeer folder_id:int = InputFolderPeer;
folderPeer#e9baa668 peer:Peer folder_id:int = FolderPeer;
messages.searchCounter#e844ebff flags:# inexact:flags.1?true filter:MessagesFilter count:int = messages.SearchCounter;
urlAuthResultRequest#92d33a0e flags:# request_write_access:flags.0?true bot:User domain:string = UrlAuthResult;
urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult;
urlAuthResultDefault#a9d6db1f = UrlAuthResult;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1098,14 +1132,14 @@ contacts.unblock#e54100bd id:InputUser = Bool;
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
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;
contacts.getTopPeers#d4982db5 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:int = contacts.TopPeers;
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
contacts.resetSaved#879537f1 = Bool;
contacts.getSaved#82f1e39f = Vector<SavedContact>;
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#b098aee6 flags:# exclude_pinned:flags.0?true offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.search#8614ef68 flags:# peer:InputPeer q:string from_id:flags.0?InputUser filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
@ -1152,7 +1186,7 @@ messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_par
messages.getMessagesViews#c4c8a55d peer:InputPeer id:Vector<int> increment:Bool = Vector<int>;
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;
messages.searchGlobal#f79c611 q:string offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
messages.searchGifs#bf9a776b q:string offset:int = messages.FoundGifs;
@ -1185,8 +1219,8 @@ messages.getCommonChats#d0a48c4 user_id:InputUser max_id:int limit:int = message
messages.getAllChats#eba80ff0 except_ids:Vector<int> = messages.Chats;
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
messages.reorderPinnedDialogs#5b51d63f flags:# force:flags.0?true order:Vector<InputDialogPeer> = Bool;
messages.getPinnedDialogs#e254d64e = messages.PeerDialogs;
messages.reorderPinnedDialogs#3b1adf37 flags:# force:flags.0?true folder_id:int order:Vector<InputDialogPeer> = Bool;
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia;
@ -1212,7 +1246,11 @@ messages.editChatAbout#def60797 peer:InputPeer about:string = Bool;
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1281,6 +1319,9 @@ channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
channels.getGroupsForDiscussion#f5dad378 = messages.Chats;
channels.getBroadcastsForDiscussion#1a87f304 = messages.Chats;
channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
@ -1298,11 +1339,11 @@ stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = mes
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
phone.getCallConfig#55451fa9 = DataJSON;
phone.requestCall#5b95b3d4 user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool;
phone.discardCall#78d413a6 peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
@ -1312,4 +1353,10 @@ langpack.getDifference#cd984aa5 lang_pack:string lang_code:string from_version:i
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;
// LAYER 97
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
folders.deleteFolder#1c295881 folder_id:int = Updates;
// LAYER 100
// Ports
channels.exportInvite#c7560885 channel:InputChannel = ExportedChatInvite;

View File

@ -5,7 +5,7 @@ from io import BytesIO
from pyrogram.api.core import *
class {class_name}(Object):
class {class_name}(TLObject):
"""{docstring_args}
"""

View File

@ -18,10 +18,11 @@
import ast
import os
import re
import shutil
HOME = "compiler/docs"
DESTINATION = "docs/source"
DESTINATION = "docs/source/telegram"
FUNCTIONS_PATH = "pyrogram/api/functions"
TYPES_PATH = "pyrogram/api/types"
@ -29,8 +30,10 @@ TYPES_PATH = "pyrogram/api/types"
FUNCTIONS_BASE = "functions"
TYPES_BASE = "types"
shutil.rmtree(TYPES_BASE, ignore_errors=True)
shutil.rmtree(FUNCTIONS_BASE, ignore_errors=True)
def snek(s: str):
s = re.sub(r"(.)([A-Z][a-z]+)", r"\1_\2", s)
return re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", s).lower()
def generate(source_path, base):
@ -50,9 +53,11 @@ def generate(source_path, base):
for node in ast.walk(p):
if isinstance(node, ast.ClassDef):
name = node.name
break
else:
continue
# name = "".join([str(j.title()) for j in os.path.splitext(i)[0].split("_")])
full_path = os.path.basename(path) + "/" + name + ".rst"
full_path = os.path.basename(path) + "/" + snek(name).replace("_", "-") + ".rst"
if level:
full_path = base + "/" + full_path
@ -65,7 +70,7 @@ def generate(source_path, base):
title=name,
title_markup="=" * len(name),
full_class_path="pyrogram.api.{}".format(
os.path.splitext(full_path)[0].replace("/", ".")
".".join(full_path.split("/")[:-1]) + "." + name
)
)
)
@ -82,7 +87,7 @@ def generate(source_path, base):
entities = []
for i in v:
entities.append(i)
entities.append(snek(i).replace("_", "-"))
if k != base:
inner_path = base + "/" + k + "/index" + ".rst"
@ -98,6 +103,7 @@ def generate(source_path, base):
with open(DESTINATION + "/" + inner_path, "w", encoding="utf-8") as f:
if k == base:
f.write(":tocdepth: 1\n\n")
k = "Raw " + k
f.write(
toctree.format(
@ -115,6 +121,8 @@ def start():
global page_template
global toctree
shutil.rmtree(DESTINATION, ignore_errors=True)
with open(HOME + "/template/page.txt", encoding="utf-8") as f:
page_template = f.read()
@ -129,6 +137,6 @@ if "__main__" == __name__:
FUNCTIONS_PATH = "../../pyrogram/api/functions"
TYPES_PATH = "../../pyrogram/api/types"
HOME = "."
DESTINATION = "../../docs/source"
DESTINATION = "../../docs/source/telegram"
start()

View File

@ -1,5 +1,5 @@
{title}
{title_markup}
.. autoclass:: {full_class_path}
.. autoclass:: {full_class_path}()
:members:

View File

@ -96,4 +96,13 @@ EXTERNAL_URL_INVALID The external media URL is invalid
CHAT_NOT_MODIFIED The chat settings were not modified
RESULTS_TOO_MUCH The result contains too many items
RESULT_ID_DUPLICATE The result contains items with duplicated identifiers
ACCESS_TOKEN_INVALID The bot access token is invalid
ACCESS_TOKEN_INVALID The bot access token is invalid
INVITE_HASH_EXPIRED The chat invite link is no longer valid
USER_BANNED_IN_CHANNEL You are limited, check @SpamBot for details
MESSAGE_EDIT_TIME_EXPIRED You can no longer edit this message
FOLDER_ID_INVALID The folder id is invalid
MEGAGROUP_PREHISTORY_HIDDEN The action failed because the supergroup has the pre-history hidden
CHAT_LINK_EXISTS The action failed because the supergroup is linked to a channel
LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target
BROADCAST_ID_INVALID The channel is invalid
MEGAGROUP_ID_INVALID The supergroup is invalid
1 id message
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
99 ACCESS_TOKEN_INVALID The bot access token is invalid
100 INVITE_HASH_EXPIRED The chat invite link is no longer valid
101 USER_BANNED_IN_CHANNEL You are limited, check @SpamBot for details
102 MESSAGE_EDIT_TIME_EXPIRED You can no longer edit this message
103 FOLDER_ID_INVALID The folder id is invalid
104 MEGAGROUP_PREHISTORY_HIDDEN The action failed because the supergroup has the pre-history hidden
105 CHAT_LINK_EXISTS The action failed because the supergroup is linked to a channel
106 LINK_NOT_MODIFIED The chat link was not modified because you tried to link to the same target
107 BROADCAST_ID_INVALID The channel is invalid
108 MEGAGROUP_ID_INVALID The supergroup is invalid

View File

@ -2,6 +2,7 @@ id message
AUTH_KEY_UNREGISTERED The key is not registered in the system
AUTH_KEY_INVALID The key is invalid
USER_DEACTIVATED The user has been deleted/deactivated
USER_DEACTIVATED_BAN The user has been deleted/deactivated
SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions
SESSION_EXPIRED The authorization has expired
ACTIVE_USER_REQUIRED The method is only available to already activated users

1 id message
2 AUTH_KEY_UNREGISTERED The key is not registered in the system
3 AUTH_KEY_INVALID The key is invalid
4 USER_DEACTIVATED The user has been deleted/deactivated
5 USER_DEACTIVATED_BAN The user has been deleted/deactivated
6 SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions
7 SESSION_EXPIRED The authorization has expired
8 ACTIVE_USER_REQUIRED The method is only available to already activated users

View File

@ -2,4 +2,6 @@ id message
CHAT_WRITE_FORBIDDEN You don't have rights to send messages in this chat
RIGHT_FORBIDDEN One or more admin rights can't be applied to this kind of chat (channel/supergroup)
CHAT_ADMIN_INVITE_REQUIRED You don't have rights to invite other users
MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat
MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat
CHAT_SEND_MEDIA_FORBIDDEN You can't send media messages in this chat
MESSAGE_AUTHOR_REQUIRED You are not the author of this message
1 id message
2 CHAT_WRITE_FORBIDDEN You don't have rights to send messages in this chat
3 RIGHT_FORBIDDEN One or more admin rights can't be applied to this kind of chat (channel/supergroup)
4 CHAT_ADMIN_INVITE_REQUIRED You don't have rights to invite other users
5 MESSAGE_DELETE_FORBIDDEN You don't have rights to delete messages in this chat
6 CHAT_SEND_MEDIA_FORBIDDEN You can't send media messages in this chat
7 MESSAGE_AUTHOR_REQUIRED You are not the author of this message

View File

@ -5,4 +5,8 @@ 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
RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later
RANDOM_ID_DUPLICATE Telegram is having internal problems. Please try again later
WORKER_BUSY_TOO_LONG_RETRY Telegram is having internal problems. Please try again later
INTERDC_X_CALL_ERROR Telegram is having internal problems at DC{x}. Please try again later
INTERDC_X_CALL_RICH_ERROR Telegram is having internal problems at DC{x}. Please try again later
FOLDER_DEAC_AUTOFIX_ALL Telegram is having internal problems. Please try again later
1 id message
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
9 WORKER_BUSY_TOO_LONG_RETRY Telegram is having internal problems. Please try again later
10 INTERDC_X_CALL_ERROR Telegram is having internal problems at DC{x}. Please try again later
11 INTERDC_X_CALL_RICH_ERROR Telegram is having internal problems at DC{x}. Please try again later
12 FOLDER_DEAC_AUTOFIX_ALL Telegram is having internal problems. Please try again later

85
docs/releases.py Normal file
View File

@ -0,0 +1,85 @@
# 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/>.
import shutil
from datetime import datetime
from pathlib import Path
import pypandoc
import requests
URL = "https://api.github.com/repos/pyrogram/pyrogram/releases"
DEST = Path("source/releases")
INTRO = """
Release Notes
=============
Release notes for Pyrogram releases will describe what's new in each version, and will also make you aware of any
backwards-incompatible changes made in that version.
When upgrading to a new version of Pyrogram, you will need to check all the breaking changes in order to find
incompatible code in your application, but also to take advantage of new features and improvements.
Releases
--------
""".lstrip("\n")
shutil.rmtree(DEST, ignore_errors=True)
DEST.mkdir(parents=True)
releases = requests.get(URL).json()
with open(DEST / "index.rst", "w") as index:
index.write(INTRO)
tags = []
for release in releases:
tag = release["tag_name"]
title = release["name"]
name = title.split(" - ")[1]
date = datetime.strptime(
release["published_at"],
"%Y-%m-%dT%H:%M:%SZ"
).strftime("%b %d, %Y")
body = pypandoc.convert_text(
release["body"].replace(r"\r\n", "\n"),
"rst",
format="markdown_github",
extra_args=["--wrap=none"]
)
tarball_url = release["tarball_url"]
zipball_url = release["zipball_url"]
index.write("- :doc:`{} <{}>`\n".format(title, tag))
tags.append(tag)
with open(DEST / "{}.rst".format(tag), "w") as page:
page.write("Pyrogram " + tag + "\n" + "=" * (len(tag) + 9) + "\n\n")
page.write("\t\tReleased on " + str(date) + "\n\n")
page.write("- :download:`Source Code (zip) <{}>`\n".format(zipball_url))
page.write("- :download:`Source Code (tar.gz) <{}>`\n\n".format(tarball_url))
page.write(name + "\n" + "-" * len(name) + "\n\n")
page.write(body + "\n\n")
index.write("\n.. toctree::\n :hidden:\n\n")
index.write("\n".join(" {}".format(tag) for tag in tags))

8
docs/robots.txt Normal file
View File

@ -0,0 +1,8 @@
User-agent: *
Allow: /
Disallow: /dev/*
Disallow: /old/*
Sitemap: https://docs.pyrogram.org/sitemap.xml

View File

@ -18,17 +18,17 @@
import datetime
import os
import re
canonical = "https://docs.pyrogram.ml"
canonical = "https://docs.pyrogram.org/"
dirs = {
".": ("weekly", 1.0),
"intro": ("weekly", 0.9),
"start": ("weekly", 0.9),
"resources": ("weekly", 0.8),
"pyrogram": ("weekly", 0.8),
"functions": ("monthly", 0.7),
"types": ("monthly", 0.7),
"errors": ("weekly", 0.6)
"api": ("weekly", 0.8),
"topics": ("weekly", 0.8),
"releases": ("weekly", 0.8),
"telegram": ("weekly", 0.6)
}
@ -37,10 +37,10 @@ def now():
with open("sitemap.xml", "w") as f:
f.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
f.write("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n")
f.write('<?xml version="1.0" encoding="utf-8"?>\n')
f.write('<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n')
urls = [(canonical, now(), "weekly", 1.0)]
urls = []
def search(path):
@ -48,14 +48,27 @@ with open("sitemap.xml", "w") as f:
for j in os.listdir(path):
search("{}/{}".format(path, j))
except NotADirectoryError:
d = path.split("/")[0]
path = "{}/{}".format(canonical, path.split(".")[0])
path = re.sub("^(.+)/index$", "\g<1>", path)
urls.append((path, now(), dirs[d][0], dirs[d][1]))
if not path.endswith(".rst"):
return
path = path.split("/")[1:]
if path[0].endswith(".rst"):
folder = "."
else:
folder = path[0]
path = "{}{}".format(canonical, "/".join(path))[:-len(".rst")]
if path.endswith("index"):
path = path[:-len("index")]
urls.append((path, now(), *dirs[folder]))
for i in dirs.keys():
search(i)
search("source")
urls.sort(key=lambda x: x[3], reverse=True)
for i in urls:
f.write(" <url>\n")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,150 @@
Bound Methods
=============
Some Pyrogram types define what are called bound methods. Bound methods are functions attached to a class which are
accessed via an instance of that class. They make it even easier to call specific methods by automatically inferring
some of the required arguments.
.. code-block:: python
:emphasize-lines: 8
from pyrogram import Client
app = Client("my_account")
@app.on_message()
def hello(client, message)
message.reply("hi")
app.run()
.. currentmodule:: pyrogram
Index
-----
Message
^^^^^^^
.. hlist::
:columns: 3
- :meth:`~Message.click`
- :meth:`~Message.delete`
- :meth:`~Message.download`
- :meth:`~Message.forward`
- :meth:`~Message.pin`
- :meth:`~Message.edit_text`
- :meth:`~Message.edit_caption`
- :meth:`~Message.edit_media`
- :meth:`~Message.edit_reply_markup`
- :meth:`~Message.reply_text`
- :meth:`~Message.reply_animation`
- :meth:`~Message.reply_audio`
- :meth:`~Message.reply_cached_media`
- :meth:`~Message.reply_chat_action`
- :meth:`~Message.reply_contact`
- :meth:`~Message.reply_document`
- :meth:`~Message.reply_game`
- :meth:`~Message.reply_inline_bot_result`
- :meth:`~Message.reply_location`
- :meth:`~Message.reply_media_group`
- :meth:`~Message.reply_photo`
- :meth:`~Message.reply_poll`
- :meth:`~Message.reply_sticker`
- :meth:`~Message.reply_venue`
- :meth:`~Message.reply_video`
- :meth:`~Message.reply_video_note`
- :meth:`~Message.reply_voice`
Chat
^^^^
.. hlist::
:columns: 2
- :meth:`~Chat.archive`
- :meth:`~Chat.unarchive`
User
^^^^
.. hlist::
:columns: 2
- :meth:`~User.archive`
- :meth:`~User.unarchive`
CallbackQuery
^^^^^^^^^^^^^
.. hlist::
:columns: 4
- :meth:`~CallbackQuery.answer`
- :meth:`~CallbackQuery.edit_text`
- :meth:`~CallbackQuery.edit_caption`
- :meth:`~CallbackQuery.edit_media`
- :meth:`~CallbackQuery.edit_reply_markup`
InlineQuery
^^^^^^^^^^^
.. hlist::
:columns: 2
- :meth:`~InlineQuery.answer`
-----
Details
-------
.. Message
.. automethod:: Message.click()
.. automethod:: Message.delete()
.. automethod:: Message.download()
.. automethod:: Message.forward()
.. automethod:: Message.pin()
.. automethod:: Message.edit_text()
.. automethod:: Message.edit_caption()
.. automethod:: Message.edit_media()
.. automethod:: Message.edit_reply_markup()
.. automethod:: Message.reply_text()
.. automethod:: Message.reply_animation()
.. automethod:: Message.reply_audio()
.. automethod:: Message.reply_cached_media()
.. automethod:: Message.reply_chat_action()
.. automethod:: Message.reply_contact()
.. automethod:: Message.reply_document()
.. automethod:: Message.reply_game()
.. automethod:: Message.reply_inline_bot_result()
.. automethod:: Message.reply_location()
.. automethod:: Message.reply_media_group()
.. automethod:: Message.reply_photo()
.. automethod:: Message.reply_poll()
.. automethod:: Message.reply_sticker()
.. automethod:: Message.reply_venue()
.. automethod:: Message.reply_video()
.. automethod:: Message.reply_video_note()
.. automethod:: Message.reply_voice()
.. Chat
.. automethod:: Chat.archive()
.. automethod:: Chat.unarchive()
.. User
.. automethod:: User.archive()
.. automethod:: User.unarchive()
.. CallbackQuery
.. automethod:: CallbackQuery.answer()
.. automethod:: CallbackQuery.edit_text()
.. automethod:: CallbackQuery.edit_caption()
.. automethod:: CallbackQuery.edit_media()
.. automethod:: CallbackQuery.edit_reply_markup()
.. InlineQuery
.. automethod:: InlineQuery.answer()

View File

@ -0,0 +1,19 @@
Pyrogram Client
===============
This is the Client class. It exposes high-level methods for an easy access to the API.
.. code-block:: python
:emphasize-lines: 1-3
from pyrogram import Client
app = Client("my_account")
with app:
app.send_message("me", "Hi!")
Details
-------
.. autoclass:: pyrogram.Client()

View File

@ -0,0 +1,57 @@
Decorators
==========
While still being methods bound to the :class:`~pyrogram.Client` class, decorators are of a special kind and thus
deserve a dedicated page.
Decorators are able to register callback functions for handling updates in a much easier and cleaner way compared to
:doc:`Handlers <handlers>`; they do so by instantiating the correct handler and calling
:meth:`~pyrogram.Client.add_handler`, automatically. All you need to do is adding the decorators on top of your
functions.
.. code-block:: python
:emphasize-lines: 6
from pyrogram import Client
app = Client("my_account")
@app.on_message()
def log(client, message):
print(message)
app.run()
.. currentmodule:: pyrogram
Index
-----
.. hlist::
:columns: 3
- :meth:`~Client.on_message`
- :meth:`~Client.on_callback_query`
- :meth:`~Client.on_inline_query`
- :meth:`~Client.on_deleted_messages`
- :meth:`~Client.on_user_status`
- :meth:`~Client.on_poll`
- :meth:`~Client.on_disconnect`
- :meth:`~Client.on_raw_update`
-----
Details
-------
.. Decorators
.. autodecorator:: pyrogram.Client.on_message()
.. autodecorator:: pyrogram.Client.on_callback_query()
.. autodecorator:: pyrogram.Client.on_inline_query()
.. autodecorator:: pyrogram.Client.on_deleted_messages()
.. autodecorator:: pyrogram.Client.on_user_status()
.. autodecorator:: pyrogram.Client.on_poll()
.. autodecorator:: pyrogram.Client.on_disconnect()
.. autodecorator:: pyrogram.Client.on_raw_update()

View File

@ -0,0 +1,72 @@
RPC Errors
==========
All Pyrogram API errors live inside the ``errors`` sub-package: ``pyrogram.errors``.
The errors ids listed here are shown as *UPPER_SNAKE_CASE*, but the actual exception names to import from Pyrogram
follow the usual *PascalCase* convention.
.. code-block:: python
:emphasize-lines: 1, 5
from pyrogram.errors import FloodWait
try:
...
except FloodWait as e:
...
303 - SeeOther
--------------
.. csv-table::
:file: ../../../compiler/error/source/303_SEE_OTHER.tsv
:delim: tab
:header-rows: 1
400 - BadRequest
----------------
.. csv-table::
:file: ../../../compiler/error/source/400_BAD_REQUEST.tsv
:delim: tab
:header-rows: 1
401 - Unauthorized
------------------
.. csv-table::
:file: ../../../compiler/error/source/401_UNAUTHORIZED.tsv
:delim: tab
:header-rows: 1
403 - Forbidden
---------------
.. csv-table::
:file: ../../../compiler/error/source/403_FORBIDDEN.tsv
:delim: tab
:header-rows: 1
406 - NotAcceptable
-------------------
.. csv-table::
:file: ../../../compiler/error/source/406_NOT_ACCEPTABLE.tsv
:delim: tab
:header-rows: 1
420 - Flood
-----------
.. csv-table::
:file: ../../../compiler/error/source/420_FLOOD.tsv
:delim: tab
:header-rows: 1
500 - InternalServerError
-------------------------
.. csv-table::
:file: ../../../compiler/error/source/500_INTERNAL_SERVER_ERROR.tsv
:delim: tab
:header-rows: 1

View File

@ -1,5 +1,8 @@
Filters
=======
Update Filters
==============
Details
-------
.. autoclass:: pyrogram.Filters
:members:

View File

@ -0,0 +1,56 @@
Update Handlers
===============
Handlers are used to instruct Pyrogram about which kind of updates you'd like to handle with your callback functions.
For a much more convenient way of registering callback functions have a look at :doc:`Decorators <decorators>` instead.
In case you decided to manually create a handler, use :class:`~pyrogram.Client.add_handler` to register
it.
.. code-block:: python
:emphasize-lines: 1, 10
from pyrogram import Client, MessageHandler
app = Client("my_account")
def dump(client, message):
print(message)
app.add_handler(MessageHandler(dump))
app.run()
.. currentmodule:: pyrogram
Index
-----
.. hlist::
:columns: 3
- :class:`MessageHandler`
- :class:`DeletedMessagesHandler`
- :class:`CallbackQueryHandler`
- :class:`InlineQueryHandler`
- :class:`UserStatusHandler`
- :class:`PollHandler`
- :class:`DisconnectHandler`
- :class:`RawUpdateHandler`
-----
Details
-------
.. Handlers
.. autoclass:: MessageHandler()
.. autoclass:: DeletedMessagesHandler()
.. autoclass:: CallbackQueryHandler()
.. autoclass:: InlineQueryHandler()
.. autoclass:: UserStatusHandler()
.. autoclass:: PollHandler()
.. autoclass:: DisconnectHandler()
.. autoclass:: RawUpdateHandler()

290
docs/source/api/methods.rst Normal file
View File

@ -0,0 +1,290 @@
Available Methods
=================
All Pyrogram methods listed here are bound to a :class:`~pyrogram.Client` instance.
.. code-block:: python
:emphasize-lines: 6
from pyrogram import Client
app = Client("my_account")
with app:
app.send_message("haskell", "hi")
.. currentmodule:: pyrogram
Index
-----
Utilities
^^^^^^^^^
.. hlist::
:columns: 4
- :meth:`~Client.start`
- :meth:`~Client.stop`
- :meth:`~Client.restart`
- :meth:`~Client.idle`
- :meth:`~Client.run`
- :meth:`~Client.add_handler`
- :meth:`~Client.remove_handler`
- :meth:`~Client.stop_transmission`
Messages
^^^^^^^^
.. hlist::
:columns: 3
- :meth:`~Client.send_message`
- :meth:`~Client.forward_messages`
- :meth:`~Client.send_photo`
- :meth:`~Client.send_audio`
- :meth:`~Client.send_document`
- :meth:`~Client.send_sticker`
- :meth:`~Client.send_animated_sticker`
- :meth:`~Client.send_video`
- :meth:`~Client.send_animation`
- :meth:`~Client.send_voice`
- :meth:`~Client.send_video_note`
- :meth:`~Client.send_media_group`
- :meth:`~Client.send_location`
- :meth:`~Client.send_venue`
- :meth:`~Client.send_contact`
- :meth:`~Client.send_cached_media`
- :meth:`~Client.edit_message_text`
- :meth:`~Client.edit_message_caption`
- :meth:`~Client.edit_message_media`
- :meth:`~Client.edit_message_reply_markup`
- :meth:`~Client.edit_inline_text`
- :meth:`~Client.edit_inline_caption`
- :meth:`~Client.edit_inline_media`
- :meth:`~Client.edit_inline_reply_markup`
- :meth:`~Client.send_chat_action`
- :meth:`~Client.delete_messages`
- :meth:`~Client.get_messages`
- :meth:`~Client.get_history`
- :meth:`~Client.get_history_count`
- :meth:`~Client.read_history`
- :meth:`~Client.iter_history`
- :meth:`~Client.send_poll`
- :meth:`~Client.vote_poll`
- :meth:`~Client.stop_poll`
- :meth:`~Client.retract_vote`
- :meth:`~Client.download_media`
Chats
^^^^^
.. hlist::
:columns: 3
- :meth:`~Client.join_chat`
- :meth:`~Client.leave_chat`
- :meth:`~Client.kick_chat_member`
- :meth:`~Client.unban_chat_member`
- :meth:`~Client.restrict_chat_member`
- :meth:`~Client.promote_chat_member`
- :meth:`~Client.export_chat_invite_link`
- :meth:`~Client.set_chat_photo`
- :meth:`~Client.delete_chat_photo`
- :meth:`~Client.set_chat_title`
- :meth:`~Client.set_chat_description`
- :meth:`~Client.pin_chat_message`
- :meth:`~Client.unpin_chat_message`
- :meth:`~Client.get_chat`
- :meth:`~Client.get_chat_member`
- :meth:`~Client.get_chat_members`
- :meth:`~Client.get_chat_members_count`
- :meth:`~Client.iter_chat_members`
- :meth:`~Client.get_dialogs`
- :meth:`~Client.iter_dialogs`
- :meth:`~Client.get_dialogs_count`
- :meth:`~Client.restrict_chat`
- :meth:`~Client.update_chat_username`
- :meth:`~Client.archive_chats`
- :meth:`~Client.unarchive_chats`
Users
^^^^^
.. hlist::
:columns: 3
- :meth:`~Client.get_me`
- :meth:`~Client.get_users`
- :meth:`~Client.get_profile_photos`
- :meth:`~Client.get_profile_photos_count`
- :meth:`~Client.iter_profile_photos`
- :meth:`~Client.set_profile_photo`
- :meth:`~Client.delete_profile_photos`
- :meth:`~Client.update_username`
- :meth:`~Client.get_user_dc`
Contacts
^^^^^^^^
.. hlist::
:columns: 3
- :meth:`~Client.add_contacts`
- :meth:`~Client.get_contacts`
- :meth:`~Client.get_contacts_count`
- :meth:`~Client.delete_contacts`
Password
^^^^^^^^
.. hlist::
:columns: 3
- :meth:`~Client.enable_cloud_password`
- :meth:`~Client.change_cloud_password`
- :meth:`~Client.remove_cloud_password`
Bots
^^^^
.. hlist::
:columns: 3
- :meth:`~Client.get_inline_bot_results`
- :meth:`~Client.send_inline_bot_result`
- :meth:`~Client.answer_callback_query`
- :meth:`~Client.answer_inline_query`
- :meth:`~Client.request_callback_answer`
- :meth:`~Client.send_game`
- :meth:`~Client.set_game_score`
- :meth:`~Client.get_game_high_scores`
Advanced Usage (Raw API)
^^^^^^^^^^^^^^^^^^^^^^^^
Learn more about these methods at :doc:`Advanced Usage <../topics/advanced-usage>`.
.. hlist::
:columns: 4
- :meth:`~Client.send`
- :meth:`~Client.resolve_peer`
- :meth:`~Client.save_file`
-----
Details
-------
.. Utilities
.. automethod:: Client.start()
.. automethod:: Client.stop()
.. automethod:: Client.restart()
.. automethod:: Client.idle()
.. automethod:: Client.run()
.. automethod:: Client.add_handler()
.. automethod:: Client.remove_handler()
.. automethod:: Client.stop_transmission()
.. Messages
.. automethod:: Client.send_message()
.. automethod:: Client.forward_messages()
.. automethod:: Client.send_photo()
.. automethod:: Client.send_audio()
.. automethod:: Client.send_document()
.. automethod:: Client.send_sticker()
.. automethod:: Client.send_animated_sticker()
.. automethod:: Client.send_video()
.. automethod:: Client.send_animation()
.. automethod:: Client.send_voice()
.. automethod:: Client.send_video_note()
.. automethod:: Client.send_media_group()
.. automethod:: Client.send_location()
.. automethod:: Client.send_venue()
.. automethod:: Client.send_contact()
.. automethod:: Client.send_cached_media()
.. automethod:: Client.send_chat_action()
.. automethod:: Client.edit_message_text()
.. automethod:: Client.edit_message_caption()
.. automethod:: Client.edit_message_media()
.. automethod:: Client.edit_message_reply_markup()
.. automethod:: Client.edit_inline_text()
.. automethod:: Client.edit_inline_caption()
.. automethod:: Client.edit_inline_media()
.. automethod:: Client.edit_inline_reply_markup()
.. automethod:: Client.delete_messages()
.. automethod:: Client.get_messages()
.. automethod:: Client.get_history()
.. automethod:: Client.get_history_count()
.. automethod:: Client.read_history()
.. automethod:: Client.iter_history()
.. automethod:: Client.send_poll()
.. automethod:: Client.vote_poll()
.. automethod:: Client.stop_poll()
.. automethod:: Client.retract_vote()
.. automethod:: Client.download_media()
.. Chats
.. automethod:: Client.join_chat()
.. automethod:: Client.leave_chat()
.. automethod:: Client.kick_chat_member()
.. automethod:: Client.unban_chat_member()
.. automethod:: Client.restrict_chat_member()
.. automethod:: Client.promote_chat_member()
.. automethod:: Client.export_chat_invite_link()
.. automethod:: Client.set_chat_photo()
.. automethod:: Client.delete_chat_photo()
.. automethod:: Client.set_chat_title()
.. automethod:: Client.set_chat_description()
.. automethod:: Client.pin_chat_message()
.. automethod:: Client.unpin_chat_message()
.. automethod:: Client.get_chat()
.. automethod:: Client.get_chat_member()
.. automethod:: Client.get_chat_members()
.. automethod:: Client.get_chat_members_count()
.. automethod:: Client.iter_chat_members()
.. automethod:: Client.get_dialogs()
.. automethod:: Client.iter_dialogs()
.. automethod:: Client.get_dialogs_count()
.. automethod:: Client.restrict_chat()
.. automethod:: Client.update_chat_username()
.. automethod:: Client.archive_chats()
.. automethod:: Client.unarchive_chats()
.. Users
.. automethod:: Client.get_me()
.. automethod:: Client.get_users()
.. automethod:: Client.get_profile_photos()
.. automethod:: Client.get_profile_photos_count()
.. automethod:: Client.iter_profile_photos()
.. automethod:: Client.set_profile_photo()
.. automethod:: Client.delete_profile_photos()
.. automethod:: Client.update_username()
.. automethod:: Client.get_user_dc()
.. Contacts
.. automethod:: Client.add_contacts()
.. automethod:: Client.get_contacts()
.. automethod:: Client.get_contacts_count()
.. automethod:: Client.delete_contacts()
.. Password
.. automethod:: Client.enable_cloud_password()
.. automethod:: Client.change_cloud_password()
.. automethod:: Client.remove_cloud_password()
.. Bots
.. automethod:: Client.get_inline_bot_results()
.. automethod:: Client.send_inline_bot_result()
.. automethod:: Client.answer_callback_query()
.. automethod:: Client.answer_inline_query()
.. automethod:: Client.request_callback_answer()
.. automethod:: Client.send_game()
.. automethod:: Client.set_game_score()
.. automethod:: Client.get_game_high_scores()
.. Advanced Usage
.. automethod:: Client.send()
.. automethod:: Client.resolve_peer()
.. automethod:: Client.save_file()

170
docs/source/api/types.rst Normal file
View File

@ -0,0 +1,170 @@
Available Types
===============
All Pyrogram types listed here are accessible through the main package directly.
.. code-block:: python
:emphasize-lines: 1
from pyrogram import User, Message, ...
.. note::
**Optional** fields may not exist when irrelevant -- i.e.: they will contain the value of ``None`` and aren't shown
when, for example, using ``print()``.
.. currentmodule:: pyrogram
Index
-----
Users & Chats
^^^^^^^^^^^^^
.. hlist::
:columns: 5
- :class:`User`
- :class:`UserStatus`
- :class:`Chat`
- :class:`ChatPreview`
- :class:`ChatPhoto`
- :class:`ChatMember`
- :class:`ChatPermissions`
- :class:`Dialog`
Messages & Media
^^^^^^^^^^^^^^^^
.. hlist::
:columns: 5
- :class:`Message`
- :class:`MessageEntity`
- :class:`Photo`
- :class:`Thumbnail`
- :class:`Audio`
- :class:`Document`
- :class:`Animation`
- :class:`Video`
- :class:`Voice`
- :class:`VideoNote`
- :class:`Contact`
- :class:`Location`
- :class:`Venue`
- :class:`Sticker`
- :class:`Game`
- :class:`Poll`
- :class:`PollOption`
Bots & Keyboards
^^^^^^^^^^^^^^^^
.. hlist::
:columns: 4
- :class:`ReplyKeyboardMarkup`
- :class:`KeyboardButton`
- :class:`ReplyKeyboardRemove`
- :class:`InlineKeyboardMarkup`
- :class:`InlineKeyboardButton`
- :class:`ForceReply`
- :class:`CallbackQuery`
- :class:`GameHighScore`
- :class:`CallbackGame`
Input Media
^^^^^^^^^^^
.. hlist::
:columns: 4
- :class:`InputMedia`
- :class:`InputMediaPhoto`
- :class:`InputMediaVideo`
- :class:`InputMediaAudio`
- :class:`InputMediaAnimation`
- :class:`InputMediaDocument`
- :class:`InputPhoneContact`
Inline Mode
^^^^^^^^^^^
.. hlist::
:columns: 3
- :class:`InlineQuery`
- :class:`InlineQueryResult`
- :class:`InlineQueryResultArticle`
InputMessageContent
^^^^^^^^^^^^^^^^^^^
.. hlist::
:columns: 3
- :class:`InputMessageContent`
- :class:`InputTextMessageContent`
-----
Details
-------
.. User & Chats
.. autoclass:: User()
.. autoclass:: UserStatus()
.. autoclass:: Chat()
.. autoclass:: ChatPreview()
.. autoclass:: ChatPhoto()
.. autoclass:: ChatMember()
.. autoclass:: ChatPermissions()
.. autoclass:: Dialog()
.. Messages & Media
.. autoclass:: Message()
.. autoclass:: MessageEntity()
.. autoclass:: Photo()
.. autoclass:: Thumbnail()
.. autoclass:: Audio()
.. autoclass:: Document()
.. autoclass:: Animation()
.. autoclass:: Video()
.. autoclass:: Voice()
.. autoclass:: VideoNote()
.. autoclass:: Contact()
.. autoclass:: Location()
.. autoclass:: Venue()
.. autoclass:: Sticker()
.. autoclass:: Game()
.. autoclass:: Poll()
.. autoclass:: PollOption()
.. Bots & Keyboards
.. autoclass:: ReplyKeyboardMarkup()
.. autoclass:: KeyboardButton()
.. autoclass:: ReplyKeyboardRemove()
.. autoclass:: InlineKeyboardMarkup()
.. autoclass:: InlineKeyboardButton()
.. autoclass:: ForceReply()
.. autoclass:: CallbackQuery()
.. autoclass:: GameHighScore()
.. autoclass:: CallbackGame()
.. Input Media
.. autoclass:: InputMedia()
.. autoclass:: InputMediaPhoto()
.. autoclass:: InputMediaVideo()
.. autoclass:: InputMediaAudio()
.. autoclass:: InputMediaAnimation()
.. autoclass:: InputMediaDocument()
.. autoclass:: InputPhoneContact()
.. Inline Mode
.. autoclass:: InlineQuery()
.. autoclass:: InlineQueryResult()
.. autoclass:: InlineQueryResultArticle()
.. InputMessageContent
.. autoclass:: InputMessageContent()
.. autoclass:: InputTextMessageContent()

View File

@ -1,198 +1,68 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>
#
# Pyrogram documentation build configuration file, created by
# sphinx-quickstart on Fri Dec 29 11:35:55 2017.
# This file is part of Pyrogram.
#
# This file is execfile()d with the current directory set to its
# containing dir.
# 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.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
# 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.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
sys.path.insert(0, os.path.abspath('../..'))
sys.path.insert(0, os.path.abspath("../.."))
# Import after sys.path.insert() to avoid issues
from pyrogram import __version__
from pygments.styles.friendly import FriendlyStyle
FriendlyStyle.background_color = "#f3f2f1"
# -- General configuration ------------------------------------------------
project = "Pyrogram"
copyright = "2017-2019, Dan"
author = "Dan"
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.autosummary'
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx.ext.autosummary"
]
# Don't show source files on docs
html_show_sourcelink = True
master_doc = "index"
source_suffix = ".rst"
autodoc_member_order = "bysource"
# Order by source, not alphabetically
autodoc_member_order = 'bysource'
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Pyrogram'
copyright = '2017-2019, Dan Tès'
author = 'Dan Tès'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = "version " + __version__
# The full version, including alpha/beta/rc tags.
version = __version__
release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = []
napoleon_use_rtype = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'friendly'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
pygments_style = "friendly"
html_title = "Pyrogram Documentation"
# Overridden by template
html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]
html_show_sourcelink = True
html_show_copyright = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
html_theme_options = {
'canonical_url': "https://docs.pyrogram.ml/",
'collapse_navigation': False,
'sticky_navigation': False,
'logo_only': True,
'display_version': True
"canonical_url": "https://docs.pyrogram.org/",
"collapse_navigation": True,
"sticky_navigation": True,
"logo_only": True,
"display_version": True,
"style_external_links": True
}
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = '_images/logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = '_images/favicon.ico'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
]
}
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Pyrogramdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Pyrogram.tex', 'Pyrogram Documentation',
'Dan Tès', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'pyrogram', 'Pyrogram Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Pyrogram', 'Pyrogram Documentation',
author, 'Pyrogram', 'One line description of project.',
'Miscellaneous'),
]
html_logo = "_images/pyrogram.png"
html_favicon = "_images/favicon.ico"

View File

@ -1,7 +0,0 @@
400 - Bad Request
=================
.. module:: pyrogram.errors.BadRequest
.. automodule:: pyrogram.errors.exceptions.bad_request_400
:members:

View File

@ -1,7 +0,0 @@
420 - Flood
===========
.. module:: pyrogram.errors.Flood
.. automodule:: pyrogram.errors.exceptions.flood_420
:members:

View File

@ -1,7 +0,0 @@
403 - Forbidden
===============
.. module:: pyrogram.errors.Forbidden
.. automodule:: pyrogram.errors.exceptions.forbidden_403
:members:

View File

@ -1,7 +0,0 @@
500 - Internal Server Error
===========================
.. module:: pyrogram.errors.InternalServerError
.. automodule:: pyrogram.errors.exceptions.internal_server_error_500
:members:

View File

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

View File

@ -1,7 +0,0 @@
303 - See Other
===============
.. module:: pyrogram.errors.SeeOther
.. automodule:: pyrogram.errors.exceptions.see_other_303
:members:

View File

@ -1,7 +0,0 @@
401 - Unauthorized
==================
.. module:: pyrogram.errors.Unauthorized
.. automodule:: pyrogram.errors.exceptions.unauthorized_401
:members:

View File

@ -1,7 +0,0 @@
520 - Unknown Error
===================
.. module:: pyrogram.errors.UnknownError
.. autoexception:: pyrogram.errors.rpc_error.UnknownError
:members:

273
docs/source/faq.rst Normal file
View File

@ -0,0 +1,273 @@
Pyrogram FAQ
============
This FAQ page provides answers to common questions about Pyrogram and, to some extent, Telegram in general.
.. tip::
If you think something interesting could be added here, feel free to propose it by opening a `Feature Request`_.
.. contents:: Contents
:backlinks: none
:local:
:depth: 1
What is Pyrogram?
-----------------
**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 applications for both user and bot identities (bot API alternative) via the
:doc:`MTProto API <topics/mtproto-vs-botapi>` with the Python programming language.
.. _Telegram: https://telegram.org
Where does the name come from?
------------------------------
The name "Pyrogram" is composed by **pyro**, which comes from the Greek word *πῦρ (pyr)*, meaning fire, and **gram**,
from *Telegram*. The word *pyro* itself is built from *Python*, **py** for short, and the suffix **ro** to come up with
the word *fire*, which also inspired the project logo.
How old is Pyrogram?
--------------------
Pyrogram was first released on December 12, 2017. The actual work on the framework began roughly three months prior the
initial public release on `GitHub`_.
.. _GitHub: https://github.com/pyrogram/pyrogram
Why Pyrogram?
-------------
- **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.
- **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 make use of the latest Telegram API version and features.
- **Bot API-like**: Similar to the Bot API in its simplicity, but much more powerful and detailed.
- **Pluggable**: The :doc:`Smart Plugin <topics/smart-plugins>` system allows to write components with minimal
boilerplate code.
- **Comprehensive**: Execute any :doc:`advanced action <topics/advanced-usage>` an official client is able to do, and
even more.
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
How stable and reliable is Pyrogram?
------------------------------------
So far, since its first public release, Pyrogram has always shown itself to be quite reliable in handling client-server
interconnections and just as stable when keeping long running applications online. The only annoying issues faced are
actually coming from Telegram servers internal errors and down times, from which Pyrogram is able to recover itself
automatically.
To challenge the framework, the creator is constantly keeping a public
`welcome bot <https://github.com/pyrogram/pyrogram/blob/develop/examples/welcomebot.py>`_ online 24/7 on his own,
relatively-busy account for well over a year now.
In addition to that, about six months ago, one of the most popular Telegram bot has been rewritten
:doc:`using Pyrogram <powered-by>` and is serving more than 200,000 Monthly Active Users since
then, uninterruptedly and without any need for restarting it.
What can MTProto do more than the Bot API?
------------------------------------------
For a detailed answer, please refer to the :doc:`MTProto vs. Bot API <topics/mtproto-vs-botapi>` page.
Why do I need an API key for bots?
----------------------------------
Requests against the official bot API endpoint are made via JSON/HTTP, but are handled by an intermediate server
application that implements the MTProto protocol -- just like Pyrogram -- and uses its own API key, which is always
required, but hidden to the public.
.. figure:: https://i.imgur.com/C108qkX.png
:align: center
Using MTProto is the only way to communicate with the actual Telegram servers, and the main API requires developers to
identify applications by means of a unique key; the bot token identifies a bot as a user and replaces the user's phone
number only.
Can I use the same file_id across different accounts?
-----------------------------------------------------
No, Telegram doesn't allow this.
File ids are personal and bound to a specific user/bot -- and an attempt in using a foreign file id will result in
errors such as ``[400 MEDIA_EMPTY]``.
The only exception are stickers' file ids; you can use them across different accounts without any problem, like this
one: ``CAADBAADyg4AAvLQYAEYD4F7vcZ43AI``.
Can I use Bot API's file_ids in Pyrogram?
-----------------------------------------
Definitely! All file ids you might have taken from the Bot API are 100% compatible and re-usable in Pyrogram...
...at least for now.
Telegram is slowly changing some server's internals and it's doing it in such a way that file ids are going to break
inevitably. Not only this, but it seems that the new, hypothetical, file ids could also possibly expire at anytime, thus
losing the *persistence* feature.
This change will most likely affect the official :doc:`Bot API <topics/mtproto-vs-botapi>` too (unless Telegram
implements some workarounds server-side to keep backwards compatibility, which Pyrogram could in turn make use of) and
we can expect a proper notice from Telegram.
Can I use multiple clients at once on the same account?
-------------------------------------------------------
Yes, you can. Both user and bot accounts are able to run multiple sessions in parallel (up to 10 per account). However,
you must pay attention and not use the *same* exact session in more than one client at the same time. In other words:
- Avoid copying your session file: even if you rename the file, the copied sessions will still point to a specific one
stored in the server.
- Make sure that only one instance of your script runs, using your session file.
If you -- even accidentally -- fail to do so, all the previous session copies will immediately stop receiving updates
and eventually the server will start throwing the error ``[406 AUTH_KEY_DUPLICATED]``, inviting you to login again.
Why is that so? Because the server has recognized two identical sessions are running in two different locations, and
concludes it could possibly be due to a cloned/stolen device. Having the session ended in such occasions will protect
the user's privacy.
So, the only correct way to run multiple clients on the same account is authorizing your account (either user or bot)
from the beginning every time, and use one separate session for each parallel client you are going to use.
I started a client and nothing happens!
---------------------------------------
If you are connecting from Russia, China or Iran :doc:`you need a proxy <topics/proxy>`, because Telegram could be
partially or totally blocked in those countries.
Another possible cause might be network issues, either yours or Telegram's. To confirm this, add the following code on
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable network
in a bunch of seconds:
.. code-block:: python
import logging
logging.basicConfig(level=logging.INFO)
Another way to confirm you aren't able to connect to Telegram is by pinging the IP addresses below and see whether ping
fails or not.
What are the IP addresses of Telegram Data Centers?
---------------------------------------------------
The Telegram cloud is currently composed by a decentralized, multi-DC infrastructure (each of which can work
independently) spread in 5 different locations. However, some of the less busy DCs have been lately dismissed and their
IP addresses are now kept as aliases.
.. csv-table:: Production Environment
:header: ID, Location, IPv4, IPv6
:widths: auto
:align: center
DC1, "MIA, Miami FL, USA", ``149.154.175.50``, ``2001:b28:f23d:f001::a``
DC2, "AMS, Amsterdam, NL", ``149.154.167.51``, ``2001:67c:4e8:f002::a``
DC3*, "MIA, Miami FL, USA", ``149.154.175.100``, ``2001:b28:f23d:f003::a``
DC4, "AMS, Amsterdam, NL", ``149.154.167.91``, ``2001:67c:4e8:f004::a``
DC5, "SIN, Singapore, SG", ``91.108.56.149``, ``2001:b28:f23f:f005::a``
.. csv-table:: Test Environment
:header: ID, Location, IPv4, IPv6
:widths: auto
:align: center
DC1, "MIA, Miami FL, USA", ``149.154.175.10``, ``2001:b28:f23d:f001::e``
DC2, "AMS, Amsterdam, NL", ``149.154.167.40``, ``2001:67c:4e8:f002::e``
DC3*, "MIA, Miami FL, USA", ``149.154.175.117``, ``2001:b28:f23d:f003::e``
***** Alias DC
More info about the Test Environment can be found :doc:`here <topics/test-servers>`.
I want to migrate my account from DCX to DCY.
---------------------------------------------
This question is often asked by people who find their account(s) always being connected to DC1 - USA (for example), but
are connecting from a place far away (e.g DC4 - Europe), thus resulting in slower interactions when using the API
because of the great physical distance between the user and its associated DC.
When registering an account for the first time, is up to Telegram to decide which DC the new user is going to be created
in, based on the phone number origin.
Even though Telegram `documentations <https://core.telegram.org/api/datacenter#user-migration>`_ state the server might
decide to automatically migrate a user in case of prolonged usages from a distant, unusual location and albeit this
mechanism is also `confirmed <https://twitter.com/telegram/status/427131446655197184>`_ to exist by Telegram itself,
it's currently not possible to have your account migrated, in any way, simply because the feature was once planned but
not yet implemented.
I keep getting PEER_ID_INVALID error!
-------------------------------------
The error in question is ``[400 PEER_ID_INVALID]``, and could mean several things:
- The chat id you tried to use is simply wrong, double check it.
- The chat id refers to a group or channel you are not a member of.
- The chat id refers to a user you have't seen yet (from contacts, groups in common, forwarded messages or private
chats).
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
UnicodeEncodeError: '<encoding>' codec can't encode …
-----------------------------------------------------
Where ``<encoding>`` might be *ascii*, *cp932*, *charmap* or anything else other than **utf-8**. This error usually
shows up when you try to print something and has very little to do with Pyrogram itself as it is strictly related to
your own terminal. To fix it, either find a way to change the encoding settings of your terminal to UTF-8 or switch to a
better one.
My verification code expires immediately!
-----------------------------------------
That is because you likely shared it across any of your Telegram chats. Yes, that's right: the server keeps scanning the
messages you send and if an active verification code is found it will immediately expire, automatically.
The reason behind this is to protect unaware users from giving their account access to any potential scammer, but if you
legitimately want to share your account(s) verification codes, consider scrambling them, e.g. ``12345````1-2-3-4-5``.
My account has been deactivated/limited!
----------------------------------------
First of all, you should understand that Telegram wants to be a safe place for people to stay in, and to pursue this
goal there are automatic protection systems running to prevent flood and spam, as well as a moderation team of humans
who review reports.
.. centered:: Pyrogram is a tool at your commands; it only does what you tell it to do, the rest is up to you.
Having said that, here's a list of what Telegram definitely doesn't like:
- Flood, abusing the API.
- Spam, sending unsolicited messages or adding people to unwanted groups and channels.
- Virtual/VoIP and cheap real numbers, because they are relatively easy to get and likely used for spam/flood.
And here's a good explanation of how, probably, the system works:
.. raw:: html
<script
async src="https://telegram.org/js/telegram-widget.js?5"
data-telegram-post="PyrogramChat/69424"
data-width="100%">
</script>
.. centered:: Join the discussion at `@Pyrogram <https://t.me/pyrogram>`_
However, you might be right, and your account was deactivated/limited without any good reason. This could happen because
of mistakes by either the automatic systems or a moderator. In such cases you can kindly email Telegram at
recover@telegram.org, contact `@smstelegram`_ on Twitter or use `this form`_.
Are there any secret easter eggs?
---------------------------------
Yes. If you found one, `let me know`_!
.. _let me know: https://t.me/pyrogram
.. _@smstelegram: https://twitter.com/smstelegram
.. _this form: https://telegram.org/support
.. _Bug Report: https://github.com/pyrogram/pyrogram/issues/new?labels=bug&template=bug_report.md
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md

79
docs/source/glossary.rst Normal file
View File

@ -0,0 +1,79 @@
Pyrogram Glossary
=================
This page contains a list of common words with brief explanations related to Pyrogram and, to some extent, Telegram in
general. Some words may as well link to dedicated articles in case the topic is covered in a more detailed fashion.
.. tip::
If you think something interesting could be added here, feel free to propose it by opening a `Feature Request`_.
Terms
-----
.. glossary::
:sorted:
API
Application Programming Interface: a set of methods, protocols and tools that make it easier to develop programs
by providing useful building blocks to the developer.
API key
A secret code used to authenticate and/or authorize a specific application to Telegram in order for it to
control how the API is being used, for example, to prevent abuses of the API.
:doc:`More on API keys <intro/setup>`.
DC
Also known as *data center*, is a place where lots of computer systems are housed and used together in order to
achieve high quality and availability for services.
RPC
Acronym for Remote Procedure call, that is, a function which gets executed at some remote place (i.e. Telegram
server) and not in your local machine.
RPCError
An error caused by an RPC which must be returned in place of the successful result in order to let the caller
know something went wrong. :doc:`More on RPCError <start/errors>`.
MTProto
The name of the custom-made, open and encrypted protocol by Telegram, implemented in Pyrogram.
:doc:`More on MTProto <topics/mtproto-vs-botapi>`.
MTProto API
The Telegram main API Pyrogram makes use of, which is able to connect both users and normal bots to Telegram
using MTProto as application layer protocol and execute any method Telegram provides from its public TL-schema.
:doc:`More on MTProto API <topics/mtproto-vs-botapi>`.
Bot API
The Telegram Bot API that is able to only connect normal bots only to Telegram using HTTP as application layer
protocol and allows to execute a sub-set of the main Telegram API.
:doc:`More on Bot API <topics/mtproto-vs-botapi>`.
Pyrogrammer
A developer that uses Pyrogram to build Telegram applications.
Userbot
Also known as *user bot* or *ubot* for short, is a user logged in by third-party Telegram libraries --- such as
Pyrogram --- to automate some behaviours, like sending messages or reacting to text commands or any other event.
Session
Also known as *login session*, is a strictly personal piece of information created and held by both parties
(client and server) which is used to grant permission into a single account without having to start a new
authorization process from scratch.
Callback
Also known as *callback function*, is a user-defined generic function that *can be* registered to and then
called-back by the framework when specific events occurs.
Handler
An object that wraps around a callback function that is *actually meant* to be registered into the framework,
which will then be able to handle a specific kind of events, such as a new incoming message, for example.
:doc:`More on Handlers <start/updates>`.
Decorator
Also known as *function decorator*, in Python, is a callable object that is used to modify another function.
Decorators in Pyrogram are used to automatically register callback functions for handling updates.
:doc:`More on Decorators <start/updates>`.
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md

View File

@ -4,8 +4,8 @@ Welcome to Pyrogram
.. raw:: html
<div align="center">
<a href="https://docs.pyrogram.ml">
<div><img src="_static/logo.png" alt="Pyrogram Logo"></div>
<a href="/">
<div><img src="_static/pyrogram.png" alt="Pyrogram Logo" width="420"></div>
</a>
</div>
@ -13,26 +13,17 @@ Welcome to Pyrogram
<b>Telegram MTProto API Framework for Python</b>
<br>
<a href="https://docs.pyrogram.ml">
Documentation
<a href="https://github.com/pyrogram/pyrogram">
Source Code
</a>
<a href="https://github.com/pyrogram/pyrogram/releases">
Changelog
Releases
</a>
<a href="https://t.me/PyrogramChat">
<a href="https://t.me/Pyrogram">
Community
</a>
<br>
<a href="compiler/api/source/main_api.tl">
<img src="https://img.shields.io/badge/schema-layer%2097-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 Version">
</a>
</p>
.. code-block:: python
@ -49,73 +40,122 @@ Welcome to Pyrogram
app.run()
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.
**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 for both user and bot identities (bot API alternative) via the
:doc:`MTProto API <topics/mtproto-vs-botapi>`.
About
-----
.. _Telegram: https://telegram.org
**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`_.
How the Documentation is Organized
----------------------------------
Features
--------
Contents are organized into self-contained topics and can be all accessed from the sidebar, or by following them in
order using the :guilabel:`Next` button at the end of each page. Here below you can, instead, find a list of the most
relevant pages for a quick access.
- **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.
- **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 97 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.
First Steps
-----------
To get started, press the Next button.
.. hlist::
:columns: 2
- :doc:`Quick Start <intro/quickstart>`: Overview to get you started quickly.
- :doc:`Calling Methods <start/invoking>`: How to call Pyrogram's methods.
- :doc:`Handling Updates <start/updates>`: How to handle Telegram updates.
- :doc:`Error Handling <start/errors>`: How to handle API errors correctly.
API Reference
-------------
.. hlist::
:columns: 2
- :doc:`Pyrogram Client <api/client>`: Reference details about the Client class.
- :doc:`Available Methods <api/methods>`: List of available high-level methods.
- :doc:`Available Types <api/types>`: List of available high-level types.
- :doc:`Bound Methods <api/bound-methods>`: List of convenient bound methods.
Meta
----
.. hlist::
:columns: 2
- :doc:`Pyrogram FAQ <faq>`: Answers to common Pyrogram questions.
- :doc:`Pyrogram Glossary <glossary>`: List of words with brief explanations.
- :doc:`Powered by Pyrogram <powered-by>`: Collection of Pyrogram Projects.
- :doc:`Support Pyrogram <support-pyrogram>`: Ways to show your appreciation.
- :doc:`About the License <license>`: Information about the Project license.
- :doc:`Release Notes <releases/index>`: Release notes for Pyrogram releases.
.. toctree::
:hidden:
:caption: Quick Start
:caption: Introduction
start/Installation
start/Setup
start/Usage
intro/quickstart
intro/install
intro/setup
.. toctree::
:hidden:
:caption: Resources
:caption: Getting Started
resources/UpdateHandling
resources/UsingFilters
resources/MoreOnUpdates
resources/ConfigurationFile
resources/SmartPlugins
resources/AutoAuthorization
resources/CustomizeSessions
resources/TgCrypto
resources/TextFormatting
resources/SOCKS5Proxy
resources/BotsInteraction
resources/ErrorHandling
resources/TestServers
resources/AdvancedUsage
resources/VoiceCalls
resources/Changelog
start/auth
start/invoking
start/updates
start/errors
.. toctree::
:hidden:
:caption: Main Package
:caption: API Reference
pyrogram/index
api/client
api/methods
api/types
api/bound-methods
api/handlers
api/decorators
api/filters
api/errors
.. toctree::
:hidden:
:caption: Topic Guides
topics/use-filters
topics/create-filters
topics/more-on-updates
topics/config-file
topics/smart-plugins
topics/auto-auth
topics/session-settings
topics/tgcrypto
topics/text-formatting
topics/serialize
topics/proxy
topics/bots-interaction
topics/mtproto-vs-botapi
topics/debugging
topics/test-servers
topics/advanced-usage
topics/voice-calls
.. toctree::
:hidden:
:caption: Meta
faq
glossary
powered-by
support-pyrogram
license
releases/index
.. toctree::
:hidden:
:caption: Telegram API
functions/index
types/index
telegram/functions/index
telegram/types/index
.. _`Telegram`: https://telegram.org
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
.. _`MTProto API`: https://core.telegram.org/api#telegram-api
.. _`MTProto 2.0`: https://core.telegram.org/mtproto
Last updated on |today|

View File

@ -1,8 +1,8 @@
Installation
============
Install Guide
=============
Being a Python library, **Pyrogram** requires Python to be installed in your system.
We recommend using the latest version of Python 3 and pip.
We recommend using the latest versions of both Python 3 and pip.
- Get **Python 3** from https://www.python.org/downloads/ (or with your package manager)
- Get **pip** by following the instructions at https://pip.pypa.io/en/latest/installing/.
@ -20,7 +20,7 @@ Install Pyrogram
$ pip3 install -U pyrogram
- or, with TgCrypto_ as extra requirement (recommended):
- or, with :doc:`TgCrypto <../topics/tgcrypto>` as extra requirement (recommended):
.. code-block:: text
@ -29,12 +29,12 @@ Install Pyrogram
Bleeding Edge
-------------
Things are constantly evolving in Pyrogram, although new releases are published only when enough changes are added,
but this doesn't mean you can't try new features right now!
Pyrogram is always evolving, although new releases on PyPI are published only when enough changes are added, but this
doesn't mean you can't try new features right now!
In case you would like to try out the latest Pyrogram features and additions, the `GitHub repo`_ is always kept updated
with new changes; you can install the development version straight from the ``develop`` branch using this command
(note "develop.zip" in the link):
In case you'd like to try out the latest Pyrogram features, the `GitHub repo`_ is always kept updated with new changes;
you can install the development version straight from the ``develop`` branch using this command (note "develop.zip" in
the link):
.. code-block:: text
@ -44,7 +44,8 @@ Asynchronous
------------
Pyrogram heavily depends on IO-bound network code (it's a cloud-based messaging framework after all), and here's
where asyncio shines the most by providing extra performance while running on a single OS-level thread only.
where asyncio shines the most by providing extra performance and efficiency while running on a single OS-level thread
only.
**A fully asynchronous variant of Pyrogram is therefore available** (Python 3.5.3+ required).
Use this command to install (note "asyncio.zip" in the link):
@ -54,7 +55,7 @@ Use this command to install (note "asyncio.zip" in the link):
$ 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
Pyrogram's API remains the same and features are kept up to date from the non-async, default develop branch, but you
are obviously required Python asyncio knowledge in order to take full advantage of it.
@ -82,11 +83,10 @@ Verifying
To verify that Pyrogram is correctly installed, open a Python shell and import it.
If no error shows up you are good to go.
.. code-block:: python
.. parsed-literal::
>>> import pyrogram
>>> pyrogram.__version__
'0.12.0'
'|version|'
.. _TgCrypto: https://docs.pyrogram.ml/resources/TgCrypto
.. _`Github repo`: http://github.com/pyrogram/pyrogram

View File

@ -0,0 +1,49 @@
Quick Start
===========
The next few steps serve as a quick start for all new Pyrogrammers that want to get something done as fast as possible.
Let's go!
Get Pyrogram Real Fast
----------------------
1. Install Pyrogram with ``pip3 install -U pyrogram``.
2. Get your own Telegram API key from https://my.telegram.org/apps.
3. Open your best text editor and paste the following:
.. code-block:: python
from pyrogram import Client
api_id = 12345
api_hash = "0123456789abcdef0123456789abcdef"
with Client("my_account", api_id, api_hash) as app:
app.send_message("me", "Greetings from **Pyrogram**!")
4. Replace *api_id* and *api_hash* values with your own.
5. Save the file as ``pyro.py``.
6. Run the script with ``python3 pyro.py``
7. Follow the instructions on your terminal to login.
8. Watch Pyrogram send a message to yourself.
9. Join our `community`_.
10. Say, "hi!".
Enjoy the API
-------------
That was just a quick overview that barely scratched the surface!
In the next few pages of the introduction, we'll take a much more in-depth look of what we have just done above.
Feeling eager to continue? You can take a shortcut to :doc:`Calling Methods <../start/invoking>` and come back later to
learn some more details.
.. _community: //t.me/Pyrogram

View File

@ -0,0 +1,59 @@
Project Setup
=============
We have just :doc:`installed Pyrogram <install>`. In this page we'll discuss what you need to do in order to set up a
project with the library. Let's see how it's done.
API Keys
--------
The very first step requires you to obtain a valid Telegram API key (API id/hash pair):
#. Visit https://my.telegram.org/apps and log in with your Telegram Account.
#. Fill out the form to register a new Telegram application.
#. Done! The API key consists of two parts: **api_id** and **api_hash**.
.. important::
The API key is personal and must be kept secret.
.. note::
The API key is unique for each user, but defines a token for a Telegram *application* you are going to build. This
means that you are able to authorize multiple users (and bots too) to access the Telegram database through the
MTProto API by a single API key.
Configuration
-------------
Having the API key from the previous step in handy, we can now begin to configure a Pyrogram project.
There are two ways to do so, and you can choose what fits better for you:
- First option (recommended): create a new ``config.ini`` file at the root of your working directory, copy-paste the
following and replace the **api_id** and **api_hash** values with your own. This is the preferred method because
allows you to keep your credentials out of your code without having to deal with how to load them:
.. code-block:: ini
[pyrogram]
api_id = 12345
api_hash = 0123456789abcdef0123456789abcdef
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash* parameters of the
Client class. This way you can have full control on how to store and load your credentials (e.g., you can load the
credentials from the environment variables and directly pass the values into Pyrogram):
.. code-block:: python
from pyrogram import Client
app = Client(
"my_account",
api_id=12345,
api_hash="0123456789abcdef0123456789abcdef"
)
.. note::
To keep code snippets clean and concise, from now on it is assumed you are making use of the ``config.ini`` file,
thus, the *api_id* and *api_hash* parameters usage won't be shown anymore.

15
docs/source/license.rst Normal file
View File

@ -0,0 +1,15 @@
About the License
=================
.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png
:align: right
Pyrogram is free software and is currently licensed under the terms of the
`GNU Lesser General Public License v3 or later (LGPLv3+)`_. In short: you may use, redistribute and/or modify it
provided that modifications are described and licensed for free under LGPLv3+.
In other words: you can use and integrate Pyrogram into your own code --- either open source, under the same or a
different license, or even proprietary --- without being required to release the source code of your own applications.
However, any modifications to the library itself are required to be published for free under the same LGPLv3+ license.
.. _GNU Lesser General Public License v3 or later (LGPLv3+): https://github.com/pyrogram/pyrogram/blob/develop/COPYING.lesser

View File

@ -0,0 +1,69 @@
Powered by Pyrogram
===================
This is a collection of remarkable projects made with Pyrogram.
.. A collection of Pyrojects :^)
.. tip::
If you'd like to propose a project that's worth being listed here, feel free to open a `Feature Request`_.
Projects Showcase
-----------------
`YTAudioBot <https://t.me/ytaudio>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **A YouTube audio downloader on Telegram, serving over 200k MAU.**
| --- by `Dan <https://t.me/haskell>`_
- Main: https://t.me/ytaudiobot
- Mirror: https://t.me/ytaudio_bot
- Website: https://ytaudiobot.ml
-----
`Pyrogram Assistant <https://github.com/pyrogram/assistant>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **The assistant bot that helps people with Pyrogram directly on Telegram**
| --- by `Dan <https://t.me/haskell>`_
- Bot: https://t.me/pyrogrambot
- Source Code: https://github.com/pyrogram/assistant
-----
`PyroBot <https://git.colinshark.de/PyroBot/PyroBot>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **A Telegram userbot based on Pyrogram**
| --- by `Colin <https://t.me/ColinShark>`_
- Source Code: https://git.colinshark.de/PyroBot/PyroBot
-----
`TgIntegration <https://github.com/JosXa/tgintegration>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **Integration Test Library for Telegram Messenger Bots in Python**
| --- by `JosXa <https://t.me/JosXa>`_
- Source Code: https://github.com/JosXa/tgintegration
-----
`BotListBot <https://t.me/botlist>`_
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| **A bot which partly uses Pyrogram to check if other bots are still alive**
| --- by `JosXa <https://t.me/JosXa>`_
- Source Code: https://github.com/JosXa/BotListBot
-----
.. _Feature Request: https://github.com/pyrogram/pyrogram/issues/new?labels=enhancement&template=feature_request.md

View File

@ -1,5 +0,0 @@
ChatAction
==========
.. autoclass:: pyrogram.ChatAction
:members:

View File

@ -1,158 +0,0 @@
Client
======
.. currentmodule:: pyrogram.Client
.. autoclass:: pyrogram.Client
Utilities
---------
.. autosummary::
:nosignatures:
start
stop
restart
idle
run
add_handler
remove_handler
send
resolve_peer
save_file
stop_transmission
Decorators
----------
.. autosummary::
:nosignatures:
on_message
on_callback_query
on_inline_query
on_deleted_messages
on_user_status
on_disconnect
on_raw_update
Messages
--------
.. autosummary::
:nosignatures:
send_message
forward_messages
send_photo
send_audio
send_document
send_sticker
send_video
send_animation
send_voice
send_video_note
send_media_group
send_location
send_venue
send_contact
send_cached_media
send_chat_action
edit_message_text
edit_message_caption
edit_message_reply_markup
edit_message_media
delete_messages
get_messages
get_history
iter_history
send_poll
vote_poll
close_poll
retract_vote
download_media
Chats
-----
.. autosummary::
:nosignatures:
join_chat
leave_chat
kick_chat_member
unban_chat_member
restrict_chat_member
promote_chat_member
export_chat_invite_link
set_chat_photo
delete_chat_photo
set_chat_title
set_chat_description
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
restrict_chat
update_chat_username
Users
-----
.. autosummary::
:nosignatures:
get_me
get_users
get_user_profile_photos
set_user_profile_photo
delete_user_profile_photos
update_username
Contacts
--------
.. autosummary::
:nosignatures:
add_contacts
get_contacts
delete_contacts
Password
--------
.. autosummary::
:nosignatures:
enable_cloud_password
change_cloud_password
remove_cloud_password
Bots
----
.. autosummary::
:nosignatures:
get_inline_bot_results
send_inline_bot_result
answer_callback_query
answer_inline_query
request_callback_answer
send_game
set_game_score
get_game_high_scores
answer_inline_query
.. autoclass:: pyrogram.Client
:inherited-members:
:members:

View File

@ -1,37 +0,0 @@
Handlers
========
.. currentmodule:: pyrogram
.. autosummary::
:nosignatures:
MessageHandler
DeletedMessagesHandler
CallbackQueryHandler
InlineQueryHandler
UserStatusHandler
DisconnectHandler
RawUpdateHandler
.. autoclass:: MessageHandler
:members:
.. autoclass:: DeletedMessagesHandler
:members:
.. autoclass:: CallbackQueryHandler
:members:
.. autoclass:: InlineQueryHandler
:members:
.. autoclass:: UserStatusHandler
:members:
.. autoclass:: DisconnectHandler
:members:
.. autoclass:: RawUpdateHandler
:members:

View File

@ -1,6 +0,0 @@
ParseMode
=========
.. autoclass:: pyrogram.ParseMode
:members:
:undoc-members:

View File

@ -1,15 +0,0 @@
RPCError
========
.. autoexception:: pyrogram.RPCError
:members:
.. toctree::
../errors/SeeOther
../errors/BadRequest
../errors/Unauthorized
../errors/Forbidden
../errors/NotAcceptable
../errors/Flood
../errors/InternalServerError
../errors/UnknownError

View File

@ -1,263 +0,0 @@
Types
=====
.. currentmodule:: pyrogram
Users & Chats
-------------
.. autosummary::
:nosignatures:
User
UserStatus
Chat
ChatPreview
ChatPhoto
ChatMember
ChatMembers
ChatPermissions
Dialog
Dialogs
Messages & Media
----------------
.. autosummary::
:nosignatures:
Message
Messages
MessageEntity
Photo
PhotoSize
UserProfilePhotos
Audio
Document
Animation
Video
Voice
VideoNote
Contact
Location
Venue
Sticker
Poll
PollOption
Bots
----
.. autosummary::
:nosignatures:
ReplyKeyboardMarkup
KeyboardButton
ReplyKeyboardRemove
InlineKeyboardMarkup
InlineKeyboardButton
ForceReply
CallbackQuery
Game
Input Media
-----------
.. autosummary::
:nosignatures:
InputMedia
InputMediaPhoto
InputMediaVideo
InputMediaAudio
InputMediaAnimation
InputMediaDocument
InputPhoneContact
Inline Mode
------------
.. autosummary::
:nosignatures:
InlineQuery
InlineQueryResult
InlineQueryResultArticle
InputMessageContent
-------------------
.. autosummary::
:nosignatures:
InputMessageContent
InputTextMessageContent
.. User & Chats
------------
.. autoclass:: User
:members:
.. autoclass:: UserStatus
:members:
.. autoclass:: Chat
:members:
.. autoclass:: ChatPreview
:members:
.. autoclass:: ChatPhoto
:members:
.. autoclass:: ChatMember
:members:
.. autoclass:: ChatMembers
:members:
.. autoclass:: ChatPermissions
:members:
.. autoclass:: Dialog
:members:
.. autoclass:: Dialogs
:members:
.. Messages & Media
----------------
.. autoclass:: Message
:members:
.. autoclass:: Messages
:members:
.. autoclass:: MessageEntity
:members:
.. autoclass:: Photo
:members:
.. autoclass:: PhotoSize
:members:
.. autoclass:: UserProfilePhotos
:members:
.. autoclass:: Audio
:members:
.. autoclass:: Document
:members:
.. autoclass:: Animation
:members:
.. autoclass:: Video
:members:
.. autoclass:: Voice
:members:
.. autoclass:: VideoNote
:members:
.. autoclass:: Contact
:members:
.. autoclass:: Location
:members:
.. autoclass:: Venue
:members:
.. autoclass:: Sticker
:members:
.. autoclass:: Poll
:members:
.. autoclass:: PollOption
:members:
.. Bots
----
.. autoclass:: ReplyKeyboardMarkup
:members:
.. autoclass:: KeyboardButton
:members:
.. autoclass:: ReplyKeyboardRemove
:members:
.. autoclass:: InlineKeyboardMarkup
:members:
.. autoclass:: InlineKeyboardButton
:members:
.. autoclass:: ForceReply
:members:
.. autoclass:: CallbackQuery
:members:
.. autoclass:: Game
:members:
.. autoclass:: GameHighScore
:members:
.. autoclass:: GameHighScores
:members:
.. Input Media
-----------
.. autoclass:: InputMedia
:members:
.. autoclass:: InputMediaPhoto
:members:
.. autoclass:: InputMediaVideo
:members:
.. autoclass:: InputMediaAudio
:members:
.. autoclass:: InputMediaAnimation
:members:
.. autoclass:: InputMediaDocument
:members:
.. autoclass:: InputPhoneContact
:members:
.. Inline Mode
-----------
.. autoclass:: InlineQuery
:members:
.. autoclass:: InlineQueryResult
:members:
.. autoclass:: InlineQueryResultArticle
:members:
.. InputMessageContent
-------------------
.. autoclass:: InputMessageContent
:members:
.. autoclass:: InputTextMessageContent
:members:

View File

@ -1,20 +0,0 @@
Pyrogram
========
In this section you can find a detailed description of the Pyrogram package and its API.
:class:`Client <pyrogram.Client>` is the main class. It exposes easy-to-use methods that are named
after the well established `Telegram Bot API`_ methods, thus offering a familiar look to Bot developers.
.. toctree::
:maxdepth: 1
Client
Types
Handlers
Filters
ChatAction
ParseMode
RPCError
.. _Telegram Bot API: https://core.telegram.org/bots/api#available-methods

View File

@ -1,11 +0,0 @@
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

@ -1,59 +0,0 @@
Error Handling
==============
Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks.
There are many errors that Telegram could return, but they all fall in one of these categories
(which are in turn children of the :obj:`RPCError <pyrogram.RPCError>` superclass):
- :obj:`303 - See Other <pyrogram.errors.SeeOther>`
- :obj:`400 - Bad Request <pyrogram.errors.BadRequest>`
- :obj:`401 - Unauthorized <pyrogram.errors.Unauthorized>`
- :obj:`403 - Forbidden <pyrogram.errors.Forbidden>`
- :obj:`406 - Not Acceptable <pyrogram.errors.NotAcceptable>`
- :obj:`420 - Flood <pyrogram.errors.Flood>`
- :obj:`500 - Internal Server Error <pyrogram.errors.InternalServerError>`
As stated above, there are really many (too many) errors, and in case Pyrogram does not know anything yet about a
specific one, it raises a special :obj:`520 Unknown Error <pyrogram.errors.UnknownError>` exception and logs it
in the ``unknown_errors.txt`` file. Users are invited to report these unknown errors; in later versions of Pyrogram
some kind of automatic error reporting module might be implemented.
Examples
--------
.. code-block:: python
from pyrogram.errors import (
BadRequest, Flood, InternalServerError,
SeeOther, Unauthorized, UnknownError
)
try:
...
except BadRequest:
pass
except Flood:
pass
except InternalServerError:
pass
except SeeOther:
pass
except Unauthorized:
pass
except UnknownError:
pass
Exception objects may also contain some informative values.
E.g.: :obj:`FloodWait <pyrogram.errors.exceptions.flood_420.FloodWait>` holds the amount of seconds you have to wait
before you can try again. The value is always stored in the ``x`` field of the returned exception object:
.. code-block:: python
import time
from pyrogram.errors import FloodWait
try:
...
except FloodWait as e:
time.sleep(e.x)

View File

@ -1,72 +0,0 @@
Update Handling
===============
Let's now dive right into the core of the framework.
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
and are handled by registering one or more callback functions in your app using `Handlers <../pyrogram/Handlers.html>`_.
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
function will be called.
Registering an Handler
----------------------
To explain how handlers work let's have a look at the most used one, the
:obj:`MessageHandler <pyrogram.MessageHandler>`, which will be in charge for handling :obj:`Message <pyrogram.Message>`
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
settings them up once you learn from this section.
Using add_handler()
-------------------
The :meth:`add_handler() <pyrogram.Client.add_handler>` method takes any handler instance that wraps around your defined
callback function and registers it in your Client. Here's a full example that prints out the content of a message as
soon as it arrives:
.. code-block:: python
from pyrogram import Client, MessageHandler
def my_function(client, message):
print(message)
app = Client("my_account")
my_handler = MessageHandler(my_function)
app.add_handler(my_handler)
app.run()
Using Decorators
----------------
A much nicer way to register a MessageHandler is by decorating your callback function with the
:meth:`on_message() <pyrogram.Client.on_message>` decorator, which will still make use of add_handler() under the hood.
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
@app.on_message()
def my_handler(client, message):
print(message)
app.run()
.. note::
Due to how these decorators work in Pyrogram, they will wrap your defined callback function in a tuple consisting of
``(handler, group)``; this will be the value held by your function identifier (e.g.: *my_function* from the example
above).
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
tuple.

View File

@ -1,194 +0,0 @@
Using Filters
=============
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
but there's much more than that to come.
Here we'll discuss about :class:`Filters <pyrogram.Filters>`. Filters enable a fine-grain control over what kind of
updates are allowed or not to be passed in your callback functions, based on their inner details.
Let's start right away with a simple example:
- This example will show you how to **only** handle messages containing an :obj:`Audio <pyrogram.Audio>` object and
ignore any other message. Filters are passed as the first argument of the decorator:
.. code-block:: python
:emphasize-lines: 4
from pyrogram import Filters
@app.on_message(Filters.audio)
def my_handler(client, message):
print(message)
- or, without decorators. Here filters are passed as the second argument of the handler constructor:
.. code-block:: python
:emphasize-lines: 8
from pyrogram import Filters, MessageHandler
def my_handler(client, message):
print(message)
app.add_handler(MessageHandler(my_handler, Filters.audio))
Combining Filters
-----------------
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
operators ``~``, ``&`` and ``|``:
- Use ``~`` to invert a filter (behaves like the ``not`` operator).
- Use ``&`` and ``|`` to merge two filters (behave like ``and``, ``or`` operators respectively).
Here are some examples:
- Message is a **text** message **and** is **not edited**.
.. code-block:: python
@app.on_message(Filters.text & ~Filters.edited)
def my_handler(client, message):
print(message)
- Message is a **sticker** **and** is coming from a **channel or** a **private** chat.
.. code-block:: python
@app.on_message(Filters.sticker & (Filters.channel | Filters.private))
def my_handler(client, message):
print(message)
Advanced Filters
----------------
Some filters, like :meth:`command() <pyrogram.Filters.command>` or :meth:`regex() <pyrogram.Filters.regex>`
can also accept arguments:
- Message is either a */start* or */help* **command**.
.. code-block:: python
@app.on_message(Filters.command(["start", "help"]))
def my_handler(client, message):
print(message)
- Message is a **text** message or a media **caption** matching the given **regex** pattern.
.. code-block:: python
@app.on_message(Filters.regex("pyrogram"))
def my_handler(client, message):
print(message)
More handlers using different filters can also live together.
.. code-block:: python
@app.on_message(Filters.command("start"))
def start_command(client, message):
print("This is the /start command")
@app.on_message(Filters.command("help"))
def help_command(client, message):
print("This is the /help command")
@app.on_message(Filters.chat("PyrogramChat"))
def from_pyrogramchat(client, message):
print("New message in @PyrogramChat")
Custom Filters
--------------
Pyrogram already provides lots of built-in :class:`Filters <pyrogram.Filters>` to work with, but in case you can't find
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
for example) you can use :meth:`Filters.create() <pyrogram.Filters.create>`.
.. note::
At the moment, the built-in filters are intended to be used with the :obj:`MessageHandler <pyrogram.MessageHandler>`
only.
An example to demonstrate how custom filters work is to show how to create and use one for the
:obj:`CallbackQueryHandler <pyrogram.CallbackQueryHandler>`. Note that callback queries updates are only received by
bots; create and `authorize your bot <../start/Setup.html#bot-authorization>`_, then send a message with an inline
keyboard to yourself. This allows you to test your filter by pressing the inline button:
.. code-block:: python
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
app.send_message(
"username", # Change this to your username or id
"Pyrogram's custom filter test",
reply_markup=InlineKeyboardMarkup(
[[InlineKeyboardButton("Press me", b"pyrogram")]]
)
)
Basic Filters
^^^^^^^^^^^^^
For this basic filter we will be using only the first two parameters of :meth:`Filters.create() <pyrogram.Filters.create>`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
equals to ``b"Pyrogram"``.
.. code-block:: python
static_data = Filters.create(
name="StaticdData",
func=lambda flt, callback_query: callback_query.data == b"Pyrogram"
)
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python
def func(flt, callback_query):
return callback_query.data == b"Pyrogram"
static_data = Filters.create(
name="StaticData",
func=func
)
The filter usage remains the same:
.. code-block:: python
@app.on_callback_query(static_data)
def pyrogram_data(client, callback_query):
client.answer_callback_query(callback_query.id, "it works!")
Filters with Arguments
^^^^^^^^^^^^^^^^^^^^^^
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
A dynamic filter like this will make use of the third parameter of :meth:`Filters.create() <pyrogram.Filters.create>`.
This is how a dynamic custom filter looks like:
.. code-block:: python
def dynamic_data(data):
return Filters.create(
name="DynamicData",
func=lambda flt, callback_query: flt.data == callback_query.data,
data=data # "data" kwarg is accessed with "filter.data"
)
And its usage:
.. code-block:: python
@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

@ -1,120 +0,0 @@
Setup
=====
Once you successfully `installed Pyrogram`_, you will still have to follow a few steps before you can actually use
the library to make API calls. This section provides all the information you need in order to set up a project
with Pyrogram.
API Keys
--------
The very first step requires you to obtain a valid Telegram API key (API id/hash pair).
If you already have one you can skip this step, otherwise:
#. Visit https://my.telegram.org/apps and log in with your Telegram Account.
#. Fill out the form to register a new Telegram application.
#. Done. The API key consists of two parts: **App api_id** and **App api_hash**.
.. important::
This API key is personal and must be kept secret.
Configuration
-------------
The API key obtained in the `previous step <#api-keys>`_ defines a token for your application allowing you to access
the Telegram database using the MTProto API — **it is therefore required for all authorizations of both users and bots**.
Having it handy, it's time to configure your Pyrogram project. There are two ways to do so, and you can choose what
fits better for you:
- Create a new ``config.ini`` file at the root of your working directory, copy-paste the following and replace the
**api_id** and **api_hash** values with your own. This is the preferred method because allows you to keep your
credentials out of your code without having to deal with how to load them:
.. code-block:: ini
[pyrogram]
api_id = 12345
api_hash = 0123456789abcdef0123456789abcdef
- Alternatively, you can pass your API key to Pyrogram by simply using the *api_id* and *api_hash* parameters of the
Client class. This way you can have full control on how to store and load your credentials:
.. code-block:: python
from pyrogram import Client
app = Client(
"my_account",
api_id=12345,
api_hash="0123456789abcdef0123456789abcdef"
)
.. note::
From now on, the code snippets assume you are using the ``config.ini`` file, thus they won't show the *api_id* and
*api_hash* parameters usage to keep them as clean as possible.
User Authorization
------------------
In order to use the API, Telegram requires that users be authorized via their phone numbers.
Pyrogram automatically manages this access, all you need to do is create an instance of the
:class:`Client <pyrogram.Client>` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
the :meth:`run() <pyrogram.Client.run>` method:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
app.run()
This starts an interactive shell asking you to input your **phone number** (including your `Country Code`_)
and the **phone code** you will receive:
.. code-block:: text
Enter phone number: +39**********
Is "+39**********" correct? (y/n): y
Enter phone code: 32768
Logged in successfully as Dan
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram
executing API calls with your identity. This file will be loaded again when you restart your app, and as long as you
keep the session alive, Pyrogram won't ask you again to enter your phone number.
.. important::
Your ``*.session`` files are personal and must be kept secret.
.. note::
The code above does nothing except asking for credentials and keeping the client online, hit ``CTRL+C`` now to stop
your application and keep reading.
Bot Authorization
-----------------
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
BotFather_. Bot tokens replace the users' phone numbers only — you still need to
`configure a Telegram API key <#configuration>`_ with Pyrogram, even when using bots.
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
after the session name, which will be ``pyrogrambot.session`` for the example below.
.. code-block:: python
from pyrogram import Client
app = Client(
"pyrogrambot",
bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
)
app.run()
.. _installed Pyrogram: Installation.html
.. _`Country Code`: https://en.wikipedia.org/wiki/List_of_country_calling_codes
.. _BotFather: https://t.me/botfather

View File

@ -1,51 +0,0 @@
Usage
=====
Having your `project set up`_ and your account authorized_, it's time to start playing with the API. Let's start!
High-level API
--------------
The easiest and recommended way to interact with Telegram is via the high-level Pyrogram methods_ and types_, which are
named after the `Telegram Bot API`_.
Here's a simple example:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
app.start()
print(app.get_me())
app.send_message("me", "Hi there! I'm using **Pyrogram**")
app.send_location("me", 51.500729, -0.124583)
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
app.stop()
You can also use Pyrogram in a context manager with the ``with`` statement. The Client will automatically
:meth:`start <pyrogram.Client.start>` and :meth:`stop <pyrogram.Client.stop>` gracefully, even in case of unhandled
exceptions in your code:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
with app:
print(app.get_me())
app.send_message("me", "Hi there! I'm using **Pyrogram**")
app.send_location("me", 51.500729, -0.124583)
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
.. _project set up: Setup.html
.. _authorized: Setup.html#user-authorization
.. _Telegram Bot API: https://core.telegram.org/bots/api
.. _methods: ../pyrogram/Client.html#messages
.. _types: ../pyrogram/Types.html

View File

@ -0,0 +1,68 @@
Authorization
=============
Once a :doc:`project is set up <../intro/setup>`, you will still have to follow a few steps before you can actually use Pyrogram to make
API calls. This section provides all the information you need in order to authorize yourself as user or bot.
User Authorization
------------------
In order to use the API, Telegram requires that users be authorized via their phone numbers.
Pyrogram automatically manages this process, all you need to do is create an instance of the
:class:`~pyrogram.Client` class by passing to it a ``session_name`` of your choice (e.g.: "my_account") and call
the :meth:`~pyrogram.Client.run` method:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
app.run()
This starts an interactive shell asking you to input your **phone number** (including your `Country Code`_) and the
**phone code** you will receive in your devices that are already authorized or via SMS:
.. code-block:: text
Enter phone number: +39**********
Is "+39**********" correct? (y/n): y
Enter phone code: 32768
Logged in successfully as Dan
After successfully authorizing yourself, a new file called ``my_account.session`` will be created allowing Pyrogram to
execute API calls with your identity. This file will be loaded again when you restart your app, and as long as you
keep the session alive, Pyrogram won't ask you again to enter your phone number.
.. important::
Your ``*.session`` files are personal and must be kept secret.
.. note::
The code above does nothing except asking for credentials and keeping the client online, hit :guilabel:`CTRL+C` now
to stop your application and keep reading.
Bot Authorization
-----------------
Bots are a special kind of users that are authorized via their tokens (instead of phone numbers), which are created by
the `Bot Father`_. Bot tokens replace the users' phone numbers only — you still need to
:doc:`configure a Telegram API key <../intro/setup>` with Pyrogram, even when using bots.
The authorization process is automatically managed. All you need to do is choose a ``session_name`` (can be anything,
usually your bot username) and pass your bot token using the ``bot_token`` parameter. The session file will be named
after the session name, which will be ``my_bot.session`` for the example below.
.. code-block:: python
from pyrogram import Client
app = Client(
"my_bot",
bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
)
app.run()
.. _Country Code: https://en.wikipedia.org/wiki/List_of_country_calling_codes
.. _Bot Father: https://t.me/botfather

View File

@ -0,0 +1,91 @@
Error Handling
==============
Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks in order
to control the behaviour of your application. Pyrogram errors all live inside the ``errors`` package:
.. code-block:: python
from pyrogram import errors
RPCError
--------
The father of all errors is named ``RPCError``. This error exists in form of a Python exception which is directly
subclass-ed from Python's main ``Exception`` and is able to catch all Telegram API related errors. This error is raised
every time a method call against Telegram's API was unsuccessful.
.. code-block:: python
from pyrogram.errors import RPCError
.. warning::
It must be noted that catching this error is bad practice, especially when no feedback is given (i.e. by
logging/printing the full error traceback), because it makes it impossible to understand what went wrong.
Error Categories
----------------
The ``RPCError`` packs together all the possible errors Telegram could raise, but to make things tidier, Pyrogram
provides categories of errors, which are named after the common HTTP errors and subclass-ed from the RPCError:
.. code-block:: python
from pyrogram.errors import BadRequest, Forbidden, ...
- `303 - SeeOther <../api/errors#seeother>`_
- `400 - BadRequest <../api/errors#badrequest>`_
- `401 - Unauthorized <../api/errors#unauthorized>`_
- `403 - Forbidden <../api/errors#forbidden>`_
- `406 - NotAcceptable <../api/errors#notacceptable>`_
- `420 - Flood <../api/errors#flood>`_
- `500 - InternalServerError <../api/errors#internalservererror>`_
Single Errors
-------------
For a fine-grained control over every single error, Pyrogram does also expose errors that deal each with a specific
issue. For example:
.. code-block:: python
from pyrogram.errors import FloodWait
These errors subclass directly from the category of errors they belong to, which in turn subclass from the father
RPCError, thus building a class of error hierarchy such as this:
- RPCError
- BadRequest
- ``MessageEmpty``
- ``UsernameOccupied``
- ``...``
- InternalServerError
- ``RpcCallFail``
- ``InterDcCallError``
- ``...``
- ``...``
.. _Errors: api/errors
Unknown Errors
--------------
In case Pyrogram does not know anything yet about a specific error, it raises a special ``520 - UnknownError`` exception
and logs it in the ``unknown_errors.txt`` file. Users are invited to report these unknown errors.
Errors with Values
------------------
Exception objects may also contain some informative values. For example, ``FloodWait`` holds the amount of seconds you
have to wait before you can try again. The value is always stored in the ``x`` field of the returned exception object:
.. code-block:: python
import time
from pyrogram.errors import FloodWait
try:
...
except FloodWait as e:
time.sleep(e.x) # Wait before trying again

View File

@ -0,0 +1,81 @@
Calling Methods
===============
At this point, we have successfully :doc:`installed Pyrogram <../intro/install>` and :doc:`authorized <auth>` our
account; we are now aiming towards the core of the library. It's time to start playing with the API!
Basic Usage
-----------
Making API method calls with Pyrogram is very simple. Here's an example we are going to examine:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
app.start()
print(app.get_me())
app.send_message("me", "Hi, it's me!")
app.send_location("me", 51.500729, -0.124583)
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
app.stop()
#. Let's begin by importing the Client class from the Pyrogram package:
.. code-block:: python
from pyrogram import Client
#. Now instantiate a new Client object, "my_account" is a session name of your choice:
.. code-block:: python
app = Client("my_account")
#. To actually make use of any method, the client has to be started first:
.. code-block:: python
app.start()
#. Now, you can call any method you like:
.. code-block:: python
print(app.get_me()) # Print information about yourself
# Send messages to yourself:
app.send_message("me", "Hi!") # Text message
app.send_location("me", 51.500729, -0.124583) # Location
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI") # Sticker
#. Finally, when done, simply stop the client:
.. code-block:: python
app.stop()
Context Manager
---------------
You can also use Pyrogram's Client in a context manager with the ``with`` statement. The client will automatically
:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop` gracefully, even in case of unhandled exceptions in
your code. The example above can be therefore rewritten in a much nicer way:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
with app:
print(app.get_me())
app.send_message("me", "Hi there! I'm using **Pyrogram**")
app.send_location("me", 51.500729, -0.124583)
app.send_sticker("me", "CAADBAADyg4AAvLQYAEYD4F7vcZ43AI")
More examples can be found on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.

View File

@ -0,0 +1,109 @@
Handling Updates
================
Calling :doc:`API methods <invoking>` sequentially is cool, but how to react when, for example, a new message arrives?
This page deals with updates and how to handle such events in Pyrogram. Let's have a look at how they work.
Defining Updates
----------------
First, let's define what are these updates. As hinted already, updates are simply events that happen in your Telegram
account (incoming messages, new members join, bot button presses, etc...), which are meant to notify you about a new
specific state that has changed. These updates are handled by registering one or more callback functions in your app
using :doc:`Handlers <../api/handlers>`.
Each handler deals with a specific event and once a matching update arrives from Telegram, your registered callback
function will be called back by the framework and its body executed.
Registering a Handler
---------------------
To explain how handlers work let's have a look at the most used one, the :class:`~pyrogram.MessageHandler`, which will
be in charge for handling :class:`~pyrogram.Message` updates coming from all around your chats. Every other handler shares
the same setup logic; you should not have troubles settings them up once you learn from this section.
Using add_handler()
-------------------
The :meth:`~pyrogram.Client.add_handler` method takes any handler instance that wraps around your defined callback
function and registers it in your Client. Here's a full example that prints out the content of a message as soon as it
arrives:
.. code-block:: python
from pyrogram import Client, MessageHandler
def my_function(client, message):
print(message)
app = Client("my_account")
my_handler = MessageHandler(my_function)
app.add_handler(my_handler)
app.run()
#. Let's examine these four new pieces. First one: a callback function we defined which accepts two arguments -
*(client, message)*. This will be the function that gets executed every time a new message arrives and Pyrogram will
call that function by passing the client instance and the new message instance as argument.
.. code-block:: python
def my_function(client, message):
print(message)
#. Second one: the :class:`~pyrogram.MessageHandler`. This object tells Pyrogram the function we defined above must
only handle updates that are in form of a :class:`~pyrogram.Message`:
.. code-block:: python
my_handler = MessageHandler(my_function)
#. Third: the method :meth:`~pyrogram.Client.add_handler`. This method is used to actually register the handler and let
Pyrogram know it needs to be taken into consideration when new updates arrive and the internal dispatching phase
begins.
.. code-block:: python
app.add_handler(my_handler)
#. Last one, the :meth:`~pyrogram.Client.run` method. What this does is simply call :meth:`~pyrogram.Client.start` and
a special method :meth:`~pyrogram.Client.idle` that keeps your main scripts alive until you press ``CTRL+C``; the
client will be automatically stopped after that.
.. code-block:: python
app.run()
Using Decorators
----------------
All of the above will become quite verbose, especially in case you have lots of handlers to register. A much nicer way
to do so is by decorating your callback function with the :meth:`~pyrogram.Client.on_message` decorator.
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
@app.on_message()
def my_handler(client, message):
print(message)
app.run()
.. note::
Due to how these decorators work in Pyrogram, they will wrap your defined callback function in a tuple consisting of
``(handler, group)``; this will be the value held by your function identifier (e.g.: *my_function* from the example
above).
In case, for some reason, you want to get your own function back after it has been decorated, you need to access
``my_function[0].callback``, that is, the *callback* field of the *handler* object which is the first element in the
tuple, accessed by bracket notation *[0]*.

View File

@ -0,0 +1,27 @@
Support Pyrogram
================
Pyrogram is free and open source software, and thus powered by your love and support! If you like the project and have
found it to be useful, give Pyrogram a `Star on GitHub`_. Your appreciation means a lot and helps staying motivated.
.. raw:: html
<a class="github-button" href="https://github.com/pyrogram/pyrogram" data-size="large" data-show-count="true" aria-label="Star pyrogram/pyrogram on GitHub">Star</a>
<br><br>
Donate
------
As a developer, you probably understand that "open source" doesn't mean "free work". A lot of time and resources has
been put into the project and if you'd like to tip me for Pyrogram -- or any of my `other works`_ -- you can use the
PayPal button below. Thank you!
.. image:: https://i.imgur.com/fasFTzK.png
:target: https://paypal.me/delivrance
:width: 128
--- `Dan`_
.. _Star on GitHub: https://github.com/pyrogram/pyrogram
.. _other works: https://github.com/delivrance
.. _Dan: https://t.me/haskell

View File

@ -1,8 +1,9 @@
Advanced Usage
==============
Pyrogram's API, which consists of well documented convenience methods_ and facade types_, exists to provide a much
easier interface to the undocumented and often confusing Telegram API.
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods>` and facade
:doc:`types <../api/types>`, exists to provide a much easier interface to the undocumented and often confusing Telegram
API.
In this section, you'll be shown the alternative way of communicating with Telegram using Pyrogram: the main "raw"
Telegram API with its functions and types.
@ -11,7 +12,7 @@ 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>`.
Telegram API, you have to use the raw :mod:`~pyrogram.api.functions` and :mod:`~pyrogram.api.types`.
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
@ -21,24 +22,25 @@ some pitfalls to take into consideration when working with the raw API.
Every available high-level methods in Pyrogram is built on top of these raw functions.
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API (yet much more
powerful).
Nothing stops you from using the raw functions only, but they are rather complex and
:doc:`plenty of them <../api/methods>` are already re-implemented by providing a much simpler and cleaner interface
which is very similar to the Bot API (yet much more powerful).
If you think a raw function should be wrapped and added as a high-level method, feel free to ask in our Community_!
Invoking Functions
^^^^^^^^^^^^^^^^^^
Unlike the methods_ found in Pyrogram's API, which can be called in the usual simple way, functions to be invoked from
the raw Telegram API have a different way of usage and are more complex.
Unlike the :doc:`methods <../api/methods>` found in Pyrogram's API, which can be called in the usual simple way,
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
First of all, both `raw functions`_ and `raw types`_ live in their respective packages (and sub-packages):
``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python classes, meaning you need to create an
instance of each every time you need them and fill them in with the correct values using named arguments.
First of all, both :doc:`raw functions <../telegram/functions/index>` and :doc:`raw types <../telegram/types/index>` live in their
respective packages (and sub-packages): ``pyrogram.api.functions``, ``pyrogram.api.types``. They all exist as Python
classes, meaning you need to create an instance of each every time you need them and fill them in with the correct
values using named arguments.
Next, to actually invoke the raw function you have to use the :meth:`send() <pyrogram.Client.send>` method provided by
the Client class and pass the function object you created.
Next, to actually invoke the raw function you have to use the :meth:`~pyrogram.Client.send` method provided by the
Client class and pass the function object you created.
Here's some examples:
@ -101,12 +103,12 @@ sending messages with IDs only thanks to cached access hashes.
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
- :class:`~pyrogram.api.types.InputPeerUser` - Users
- :class:`~pyrogram.api.types.InputPeerChat` - Basic Chats
- :class:`~pyrogram.api.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
:meth:`~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
@ -118,19 +120,11 @@ 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*
- ``+ID`` User: *123456789*
- ``-ID`` Chat: *-123456789*
- ``-100ID`` Channel or 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.
.. _methods: ../pyrogram/Client.html#messages
.. _types: ../pyrogram/Types.html
.. _plenty of them: ../pyrogram/Client.html#messages
.. _raw functions: ../pyrogram/functions
.. _raw types: ../pyrogram/types
.. _Community: https://t.me/PyrogramChat
.. _Community: https://t.me/Pyrogram

View File

@ -3,7 +3,7 @@ Auto Authorization
Manually writing phone number, phone code and password on the terminal every time you want to login can be tedious.
Pyrogram is able to automate both **Log In** and **Sign Up** processes, all you need to do is pass the relevant
parameters when creating a new :class:`Client <pyrogram.Client>`.
parameters when creating a new :class:`~pyrogram.Client`.
.. note:: If you omit any of the optional parameter required for the authorization, Pyrogram will ask you to
manually write it. For instance, if you don't want to set a ``last_name`` when creating a new account you

View File

@ -7,8 +7,7 @@ Inline Bots
-----------
- If a bot accepts inline queries, you can call it by using
:meth:`get_inline_bot_results() <pyrogram.Client.get_inline_bot_results>` to get the list of its inline results
for a query:
:meth:`~pyrogram.Client.get_inline_bot_results` to get the list of its inline results for a query:
.. code-block:: python
@ -24,7 +23,7 @@ Inline Bots
results list.
- After you retrieved the bot results, you can use
:meth:`send_inline_bot_result() <pyrogram.Client.send_inline_bot_result>` to send a chosen result to any chat:
:meth:`~pyrogram.Client.send_inline_bot_result` to send a chosen result to any chat:
.. code-block:: python

View File

@ -1,14 +1,14 @@
Configuration File
==================
As already mentioned in previous sections, Pyrogram can be configured by the use of an INI file.
This page explains how this file is structured in Pyrogram, how to use it and why.
As already mentioned in previous pages, Pyrogram can be configured by the use of an INI file.
This page explains how this file is structured, how to use it and why.
Introduction
------------
The idea behind using a configuration file is to help keeping your code free of private settings information such as
the API Key and Proxy without having you to even deal with how to load such settings. The configuration file, usually
the API Key and Proxy, without having you to even deal with how to load such settings. The configuration file, usually
referred as ``config.ini`` file, is automatically loaded from the root of your working directory; all you need to do is
fill in the necessary parts.
@ -54,7 +54,7 @@ The ``[pyrogram]`` section contains your Telegram API credentials: *api_id* and
api_id = 12345
api_hash = 0123456789abcdef0123456789abcdef
`More info about API Key. <../start/Setup.html#configuration>`_
`More info about API Key. <../intro/setup#api-keys>`_
Proxy
^^^^^
@ -70,7 +70,7 @@ The ``[proxy]`` section contains settings about your SOCKS5 proxy.
username = <your_username>
password = <your_password>
`More info about SOCKS5 Proxy. <SOCKS5Proxy.html>`_
`More info about SOCKS5 Proxy. <proxy>`_
Plugins
^^^^^^^
@ -87,4 +87,4 @@ The ``[plugins]`` section contains settings about Smart Plugins.
exclude =
module fn2
`More info about Smart Plugins. <SmartPlugins.html>`_
`More info about Smart Plugins. <smart-plugins>`_

View File

@ -0,0 +1,93 @@
Creating Filters
================
Pyrogram already provides lots of built-in :class:`~pyrogram.Filters` to work with, but in case you can't find
a specific one for your needs or want to build a custom filter by yourself (to be used in a different kind of handler,
for example) you can use :meth:`~pyrogram.Filters.create`.
.. note::
At the moment, the built-in filters are intended to be used with the :class:`~pyrogram.MessageHandler` only.
Custom Filters
--------------
An example to demonstrate how custom filters work is to show how to create and use one for the
:class:`~pyrogram.CallbackQueryHandler`. Note that callback queries updates are only received by bots as result of a
user pressing an inline button attached to the bot's message; create and :doc:`authorize your bot <../start/auth>`,
then send a message with an inline keyboard to yourself. This allows you to test your filter by pressing the inline
button:
.. code-block:: python
from pyrogram import InlineKeyboardMarkup, InlineKeyboardButton
app.send_message(
"username", # Change this to your username or id
"Pyrogram's custom filter test",
reply_markup=InlineKeyboardMarkup(
[[InlineKeyboardButton("Press me", "pyrogram")]]
)
)
Basic Filters
-------------
For this basic filter we will be using only the first two parameters of :meth:`~pyrogram.Filters.create`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries
containing "Pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data
equals to ``"Pyrogram"``.
.. code-block:: python
static_data = Filters.create(
name="StaticdData",
func=lambda flt, query: query.data == "Pyrogram"
)
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python
def func(flt, query):
return query.data == "Pyrogram"
static_data = Filters.create(
name="StaticData",
func=func
)
The filter usage remains the same:
.. code-block:: python
@app.on_callback_query(static_data)
def pyrogram_data(_, query):
query.answer("it works!")
Filters with Arguments
----------------------
A much cooler filter would be one that accepts "Pyrogram" or any other data as argument at usage time.
A dynamic filter like this will make use of the third parameter of :meth:`~pyrogram.Filters.create`.
This is how a dynamic custom filter looks like:
.. code-block:: python
def dynamic_data(data):
return Filters.create(
name="DynamicData",
func=lambda flt, query: flt.data == query.data,
data=data # "data" kwarg is accessed with "flt.data"
)
And its usage:
.. code-block:: python
@app.on_callback_query(dynamic_data("Pyrogram"))
def pyrogram_data(_, query):
query.answer("it works!")

View File

@ -0,0 +1,135 @@
Debugging
=========
When working with the API, chances are you'll stumble upon bugs, get stuck and start wondering how to continue. Nothing
to actually worry about -- that's normal -- and luckily for you, Pyrogram provides some commodities to help you in this.
Caveman Debugging
-----------------
*The most effective debugging tool is still careful thought, coupled with judiciously placed print statements.*
-- Brian Kernighan, "Unix for Beginners" (1979)
Adding ``print()`` statements in crucial parts of your code is by far the most ancient, yet efficient technique for
debugging programs, especially considering the concurrent nature of the framework itself. Pyrogram goodness in this
respect comes with the fact that any object can be nicely printed just by calling ``print(obj)``, thus giving to you
an insight of all its inner details.
Consider the following code:
.. code-block:: python
dan = app.get_users("haskell")
print(dan) # User
This will show a JSON representation of the object returned by :meth:`~pyrogram.Client.get_users`, which is a
:class:`~pyrogram.User` instance, in this case. The output on your terminal will be something similar to this:
.. code-block:: json
{
"_": "pyrogram.User",
"id": 23122162,
"is_self": false,
"is_contact": false,
"is_mutual_contact": false,
"is_deleted": false,
"is_bot": false,
"is_verified": false,
"is_restricted": false,
"is_support": false,
"is_scam": false,
"first_name": "Dan",
"status": {
"_": "pyrogram.UserStatus",
"user_id": 23122162,
"recently": true
},
"username": "haskell",
"language_code": "en",
"photo": {
"_": "pyrogram.ChatPhoto",
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
}
}
As you've probably guessed already, Pyrogram objects can be nested. That's how compound data are built, and nesting
keeps going until we are left with base data types only, such as ``str``, ``int``, ``bool``, etc.
Accessing Attributes
--------------------
Even though you see a JSON output, it doesn't mean we are dealing with dictionaries; in fact, all Pyrogram types are
full-fledged Python objects and the correct way to access any attribute of them is by using the dot notation ``.``:
.. code-block:: python
dan_photo = dan.photo
print(dan_photo) # ChatPhoto
.. code-block:: json
{
"_": "pyrogram.ChatPhoto",
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
}
However, the bracket notation ``[]`` is also supported, but its usage is discouraged:
.. warning::
Bracket notation in Python is not commonly used for getting/setting object attributes. While it works for Pyrogram
objects, it might not work for anything else and you should not rely on this.
.. code-block:: python
dan_photo_big = dan["photo"]["big_file_id"]
print(dan_photo_big) # str
.. code-block:: text
AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg
Checking an Object's Type
-------------------------
Another thing worth talking about is how to tell and check for an object's type.
As you noticed already, when printing an object you'll see the special attribute ``"_"``. This is just a visual thing
useful to show humans the object type, but doesn't really exist anywhere; any attempt in accessing it will lead to an
error. The correct way to get the object type is by using the built-in function ``type()``:
.. code-block:: python
dan_status = dan.status
print(type(dan_status))
.. code-block:: text
<class 'pyrogram.UserStatus'>
And to check if an object is an instance of a given class, you use the built-in function ``isinstance()``:
.. code-block:: python
:name: this-py
from pyrogram import UserStatus
dan_status = dan.status
print(isinstance(dan_status, UserStatus))
.. code-block:: text
True
.. raw:: html
<script>
var e = document.querySelector("blockquote p.attribution");
var s = e.innerHTML;
e.innerHTML = s[0] + " " + s.slice(1);
</script>

View File

@ -1,7 +1,8 @@
More on Updates
===============
Here we'll show some advanced usages when working with `update handlers`_ and `filters`_.
Here we'll show some advanced usages when working with :doc:`update handlers <../start/updates>` and
:doc:`filters <use-filters>`.
Handler Groups
--------------
@ -28,7 +29,7 @@ For example, take these two handlers:
print("Just Text")
Here, ``just_text`` is never executed because ``text_or_sticker``, which has been registered first, already handles
texts (``Filters.text`` is shared and conflicting). To enable it, register the function using a different group:
texts (``Filters.text`` is shared and conflicting). To enable it, register the handler using a different group:
.. code-block:: python
@ -36,7 +37,7 @@ texts (``Filters.text`` is shared and conflicting). To enable it, register the f
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``):
Or, if you want ``just_text`` to be executed *before* ``text_or_sticker`` (note ``-1``, which is less than ``0``):
.. code-block:: python
@ -44,7 +45,7 @@ Or, if you want ``just_text`` to be fired *before* ``text_or_sticker`` (note ``-
def just_text(client, message):
print("Just Text")
With :meth:`add_handler() <pyrogram.Client.add_handler>` (without decorators) the same can be achieved with:
With :meth:`~pyrogram.Client.add_handler` (without decorators) the same can be achieved with:
.. code-block:: python
@ -151,9 +152,9 @@ 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 same 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:
**the same group** despite having conflicting filters in the next registered handler. 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).
@ -217,6 +218,3 @@ The output of both (equivalent) examples will be:
0
1
2
.. _`update handlers`: UpdateHandling.html
.. _`filters`: UsingFilters.html

View File

@ -0,0 +1,110 @@
MTProto vs. Bot API
===================
Pyrogram is a framework that acts as a fully-fledged Telegram client based on MTProto, and this very feature makes it
already superior to, what is usually called, the official Bot API, in many respects. This page will therefore show you
why Pyrogram might be a better choice for your project by comparing the two APIs, but first, let's make it clear what
actually is the MTProto and the Bot API.
What is the MTProto API?
------------------------
`MTProto`_, took alone, is the name of the custom-made, open and encrypted communication protocol created by Telegram
itself --- it's the only protocol used to exchange information between a client and the actual Telegram servers.
The MTProto **API** on the other hand, is what people, for convenience, call the main Telegram API as a whole. This API
is able to authorize both users and bots and is built on top of the MTProto encryption protocol by means of
`binary data serialized`_ in a specific way, as described by the `TL language`_, and delivered using UDP, TCP or even
HTTP as transport-layer protocol.
.. _MTProto: https://core.telegram.org/mtproto
.. _binary data serialized: https://core.telegram.org/mtproto/serialize
.. _TL language: https://core.telegram.org/mtproto/TL
What is the Bot API?
--------------------
The `Bot API`_ is an HTTP(S) interface for building normal bots using a sub-set of the main MTProto API. Bots are special
accounts that are authorized via tokens instead of phone numbers. The Bot API is built yet again on top of the main
Telegram API, but runs on an intermediate server application that in turn communicates with the actual Telegram servers
using MTProto.
.. figure:: https://i.imgur.com/C108qkX.png
:align: center
.. _Bot API: https://core.telegram.org/bots/api
Advantages of the MTProto API
-----------------------------
Here is a list of all the advantages in using MTProto-based libraries -- such as Pyrogram -- instead of the official
HTTP Bot API. Using Pyrogram you can:
.. hlist::
:columns: 1
- :guilabel:`+` **Authorize both user and bot identities**
- :guilabel:`--` The Bot API only allows bot accounts
.. hlist::
:columns: 1
- :guilabel:`+` **Upload & download any file, up to 1500 MB each (~1.5 GB)**
- :guilabel:`--` The Bot API allows uploads and downloads of files only up to 50 MB / 20 MB in size (respectively).
.. hlist::
:columns: 1
- :guilabel:`+` **Has less overhead due to direct connections to Telegram**
- :guilabel:`--` The Bot API uses an intermediate server to handle HTTP requests before they are sent to the actual
Telegram servers.
.. hlist::
:columns: 1
- :guilabel:`+` **Run multiple sessions at once, up to 10 per account (either bot or user)**
- :guilabel:`--` The Bot API intermediate server will terminate any other session in case you try to use the same
bot again in a parallel connection.
.. hlist::
:columns: 1
- :guilabel:`+` **Has much more detailed types and powerful methods**
- :guilabel:`--` The Bot API types often miss some useful information about Telegram entities and some of the
methods are limited as well.
.. hlist::
:columns: 1
- :guilabel:`+` **Get information about any public chat by usernames, even if not a member**
- :guilabel:`--` The Bot API simply doesn't support this
.. hlist::
:columns: 1
- :guilabel:`+` **Obtain information about any message existing in a chat using their ids**
- :guilabel:`--` The Bot API simply doesn't support this
.. hlist::
:columns: 1
- :guilabel:`+` **Retrieve the whole chat members list of either public or private chats**
- :guilabel:`--` The Bot API simply doesn't support this
.. hlist::
:columns: 1
- :guilabel:`+` **Receive extra updates, such as the one about a user name change**
- :guilabel:`--` The Bot API simply doesn't support this
.. hlist::
:columns: 1
- :guilabel:`+` **Has more meaningful errors in case something went wrong**
- :guilabel:`--` The Bot API reports less detailed errors
.. hlist::
:columns: 1
- :guilabel:`+` **Get API version updates, and thus new features, sooner**
- :guilabel:`--` The Bot API is simply slower in implementing new features

View File

@ -0,0 +1,52 @@
Object Serialization
====================
Serializing means converting a Pyrogram object, which exists as Python class instance, to a text string that can be
easily shared and stored anywhere. Pyrogram provides two formats for serializing its objects: one good looking for
humans and another more compact for machines that is able to recover the original structures.
For Humans - str(obj)
---------------------
If you want a nicely formatted, human readable JSON representation of any object in the API -- namely, any object from
:doc:`Pyrogram types <../api/types>`, :doc:`raw functions <../telegram/functions/index>` and
:doc:`raw types <../telegram/types/index>` -- you can use use ``str(obj)``.
.. code-block:: python
...
with app:
r = app.get_chat("haskell")
print(str(r))
.. tip::
When using ``print()`` you don't actually need to use ``str()`` on the object because it is called automatically, we
have done that above just to show you how to explicitly convert a Pyrogram object to JSON.
For Machines - repr(obj)
------------------------
If you want to share or store objects for future references in a more compact way, you can use ``repr(obj)``. While
still pretty much readable, this format is not intended for humans. The advantage of this format is that once you
serialize your object, you can use ``eval()`` to get back the original structure; just make sure to ``import pyrogram``,
as the process requires the package to be in scope.
.. code-block:: python
import pyrogram
...
with app:
r = app.get_chat("haskell")
print(repr(r))
print(eval(repr(r)) == r) # True
.. note::
Type definitions are subject to changes between versions. You should make sure to store and load objects using the
same Pyrogram version.

View File

@ -1,24 +1,23 @@
Customize Sessions
==================
Session Settings
================
As you may probably know, Telegram allows users (and bots) having more than one session (authorizations) registered
in the system at the same time.
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
app (or by invoking `GetAuthorizations <../functions/account/GetAuthorizations.html>`_ with Pyrogram). They store some
useful information such as the client who's using them and from which country and IP address.
app (or by invoking :class:`~pyrogram.api.functions.account.GetAuthorizations` with Pyrogram). They
store some useful information such as the client who's using them and from which country and IP address.
.. figure:: https://i.imgur.com/lzGPCdZ.png
:width: 70%
.. figure:: https://i.imgur.com/YaqtMLO.png
:width: 600
:align: center
**A Pyrogram session running on Linux, Python 3.6.**
**A Pyrogram session running on Linux, Python 3.7.**
That's how a session looks like on the Android app, showing the three main pieces of information.
- ``app_version``: **Pyrogram 🔥 0.7.5**
- ``device_model``: **CPython 3.6.5**
- ``app_version``: **Pyrogram 0.13.0**
- ``device_model``: **CPython 3.7.2**
- ``system_version``: **Linux 4.15.0-23-generic**
Set Custom Values

View File

@ -30,7 +30,7 @@ after importing your modules, like this:
handlers.py
main.py
- ``handlers.py``
- ``handlers.py``
.. code-block:: python
@ -41,7 +41,7 @@ after importing your modules, like this:
def echo_reversed(client, message):
message.reply(message.text[::-1])
- ``main.py``
- ``main.py``
.. code-block:: python
@ -65,8 +65,8 @@ after importing your modules, like this:
app.run()
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
manually ``import``, manually :meth:`~pyrogram.Client.add_handler` and manually instantiate each
:class:`~pyrogram.MessageHandler` object because **you can't use those cool decorators** for your
functions. So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
Using Smart Plugins
@ -80,7 +80,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
.. note::
This is the same example application `as shown above <#introduction>`_, written using the Smart Plugin system.
This is the same example application as shown above, written using the Smart Plugin system.
.. code-block:: text
:emphasize-lines: 2, 3
@ -91,7 +91,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
config.ini
main.py
- ``plugins/handlers.py``
- ``plugins/handlers.py``
.. code-block:: python
:emphasize-lines: 4, 9
@ -108,14 +108,14 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
def echo_reversed(client, message):
message.reply(message.text[::-1])
- ``config.ini``
- ``config.ini``
.. code-block:: ini
[plugins]
root = plugins
- ``main.py``
- ``main.py``
.. code-block:: python
@ -156,7 +156,7 @@ found inside each module will be, instead, loaded in the order they are defined,
.. 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>`_.
filters included a second time will not work. Learn more at :doc:`More on Updates <more-on-updates>`.
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``
@ -199,8 +199,8 @@ also organized in subfolders:
...
...
- Load every handler from every module, namely *plugins0.py*, *plugins1.py* and *plugins2.py* in alphabetical order
(files) and definition order (handlers inside files):
- 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:
@ -217,7 +217,7 @@ also organized in subfolders:
Client("my_account", plugins=plugins).run()
- Load only handlers defined inside *plugins2.py* and *plugins0.py*, in this order:
- Load only handlers defined inside *plugins2.py* and *plugins0.py*, in this order:
Using *config.ini* file:
@ -243,7 +243,7 @@ also organized in subfolders:
Client("my_account", plugins=plugins).run()
- Load everything except the handlers inside *plugins2.py*:
- Load everything except the handlers inside *plugins2.py*:
Using *config.ini* file:
@ -264,7 +264,7 @@ also organized in subfolders:
Client("my_account", plugins=plugins).run()
- Load only *fn3*, *fn1* and *fn2* (in this order) from *plugins1.py*:
- Load only *fn3*, *fn1* and *fn2* (in this order) from *plugins1.py*:
Using *config.ini* file:
@ -288,16 +288,15 @@ also organized in subfolders:
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 plugin at runtime.
In the previous section 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 plugin 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``
- ``plugins/handlers.py``
.. code-block:: python
:emphasize-lines: 5, 6
@ -318,10 +317,10 @@ 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
relevant module and call :meth:`~pyrogram.Client.remove_handler` Client's method with your function
name preceded by the star ``*`` operator as argument. Example:
- ``main.py``
- ``main.py``
.. code-block:: python
@ -343,9 +342,9 @@ 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:
using :meth:`~pyrogram.Client.add_handler` instead. Example:
- ``main.py``
- ``main.py``
.. code-block:: python

View File

@ -11,8 +11,8 @@ Beside bold, italic, and pre-formatted code, **Pyrogram does also support inline
Markdown Style
--------------
To use this mode, pass :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or "markdown" in the *parse_mode* field when using
:obj:`send_message() <pyrogram.Client.send_message>`. Use the following syntax in your message:
To use this mode, pass "markdown" in the *parse_mode* field when using
:meth:`~pyrogram.Client.send_message`. Use the following syntax in your message:
.. code-block:: text
@ -20,7 +20,7 @@ To use this mode, pass :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or "markdow
__italic text__
[inline URL](https://docs.pyrogram.ml/)
[inline URL](https://docs.pyrogram.org/)
[inline mention of a user](tg://user?id=23122162)
@ -34,8 +34,8 @@ To use this mode, pass :obj:`MARKDOWN <pyrogram.ParseMode.MARKDOWN>` or "markdow
HTML Style
----------
To use this mode, pass :obj:`HTML <pyrogram.ParseMode.HTML>` or "html" in the *parse_mode* field when using
:obj:`send_message() <pyrogram.Client.send_message>`. The following tags are currently supported:
To use this mode, pass "html" in the *parse_mode* field when using :meth:`~pyrogram.Client.send_message`.
The following tags are currently supported:
.. code-block:: text
@ -43,7 +43,7 @@ To use this mode, pass :obj:`HTML <pyrogram.ParseMode.HTML>` or "html" in the *p
<i>italic</i>, <em>italic</em>
<a href="http://docs.pyrogram.ml/">inline URL</a>
<a href="http://docs.pyrogram.org/">inline URL</a>
<a href="tg://user?id=23122162">inline mention of a user</a>
@ -66,7 +66,7 @@ Examples
"**bold**, "
"__italic__, "
"[mention](tg://user?id=23122162), "
"[URL](https://docs.pyrogram.ml), "
"[URL](https://docs.pyrogram.org), "
"`code`, "
"```"
"for i in range(10):\n"
@ -84,7 +84,7 @@ Examples
"<b>bold</b>, "
"<i>italic</i>, "
"<a href=\"tg://user?id=23122162\">mention</a>, "
"<a href=\"https://pyrogram.ml/\">URL</a>, "
"<a href=\"https://pyrogram.org/\">URL</a>, "
"<code>code</code>, "
"<pre>"
"for i in range(10):\n"

View File

@ -2,7 +2,7 @@ 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.
Library specifically written in C for Pyrogram [1]_ as a Python extension.
TgCrypto is a replacement for the much slower PyAES and implements the crypto algorithms Telegram requires, namely
**AES-IGE 256 bit** (used in MTProto v2.0) and **AES-CTR 256 bit** (used for CDN encrypted files).
@ -28,5 +28,5 @@ what you should do next:
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
.. [#f1] Although TgCrypto is intended for Pyrogram, it is shipped as a standalone package and can thus be used for
.. [1] Although TgCrypto is intended for Pyrogram, it is shipped as a standalone package and can thus be used for
other Python projects too.

View File

@ -0,0 +1,108 @@
Using Filters
=============
So far we've seen how to register a callback function that executes every time a specific update comes from the server,
but there's much more than that to come.
Here we'll discuss about :class:`~pyrogram.Filters`. Filters enable a fine-grain control over what kind of
updates are allowed or not to be passed in your callback functions, based on their inner details.
Single Filters
--------------
Let's start right away with a simple example:
- This example will show you how to **only** handle messages containing an :class:`~pyrogram.Audio` object and
ignore any other message. Filters are passed as the first argument of the decorator:
.. code-block:: python
:emphasize-lines: 4
from pyrogram import Filters
@app.on_message(Filters.audio)
def my_handler(client, message):
print(message)
- or, without decorators. Here filters are passed as the second argument of the handler constructor; the first is the
callback function itself:
.. code-block:: python
:emphasize-lines: 8
from pyrogram import Filters, MessageHandler
def my_handler(client, message):
print(message)
app.add_handler(MessageHandler(my_handler, Filters.audio))
Combining Filters
-----------------
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
operators ``~``, ``&`` and ``|``:
- Use ``~`` to invert a filter (behaves like the ``not`` operator).
- Use ``&`` and ``|`` to merge two filters (behave like ``and``, ``or`` operators respectively).
Here are some examples:
- Message is a **text** message **and** is **not edited**.
.. code-block:: python
@app.on_message(Filters.text & ~Filters.edited)
def my_handler(client, message):
print(message)
- Message is a **sticker** **and** is coming from a **channel or** a **private** chat.
.. code-block:: python
@app.on_message(Filters.sticker & (Filters.channel | Filters.private))
def my_handler(client, message):
print(message)
Advanced Filters
----------------
Some filters, like :meth:`~pyrogram.Filters.command` or :meth:`~pyrogram.Filters.regex`
can also accept arguments:
- Message is either a */start* or */help* **command**.
.. code-block:: python
@app.on_message(Filters.command(["start", "help"]))
def my_handler(client, message):
print(message)
- Message is a **text** message or a media **caption** matching the given **regex** pattern.
.. code-block:: python
@app.on_message(Filters.regex("pyrogram"))
def my_handler(client, message):
print(message)
More handlers using different filters can also live together.
.. code-block:: python
@app.on_message(Filters.command("start"))
def start_command(client, message):
print("This is the /start command")
@app.on_message(Filters.command("help"))
def help_command(client, message):
print("This is the /help command")
@app.on_message(Filters.chat("PyrogramChat"))
def from_pyrogramchat(client, message):
print("New message in @PyrogramChat")

View File

@ -12,12 +12,12 @@ Example | Description
---: | :---
[**hello_world**](hello_world.py) | Demonstration of basic API usage
[**echobot**](echobot.py) | Echo 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
[**using_inline_bots**](using_inline_bots.py) | Query an inline bot (as user) and send a result to a chat
[**keyboards**](keyboards.py) | Send normal and inline keyboards using regular bots
[**callback_queries**](callback_queries.py) | Handle queries coming from inline button presses
[**inline_queries**](inline_queries.py) | Handle inline queries
[**welcomebot**](welcomebot.py) | The Welcome Bot in [@PyrogramChat](https://t.me/pyrogramchat)
[**get_history**](get_history.py) | Get the full message history of a chat
[**get_chat_members**](get_chat_members.py) | Get all the members of a chat
[**get_dialogs**](get_dialogs.py) | Get all of your dialog chats
[**callback_queries**](callback_queries.py) | Handle callback queries (as bot) coming from inline button presses
[**inline_queries**](inline_queries.py) | Handle inline queries (as bot) and answer with results
[**use_inline_bots**](use_inline_bots.py) | Query an inline bot (as user) and send a result to a chat
[**bot_keyboards**](bot_keyboards.py) | Send normal and inline keyboards using regular bots
[**raw_updates**](raw_updates.py) | Handle raw updates (old, should be avoided)

View File

@ -1,4 +1,4 @@
"""This example will show you how to send normal and inline keyboards.
"""This example will show you how to send normal and inline keyboards (as bot).
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.
@ -39,7 +39,7 @@ with app:
),
InlineKeyboardButton( # Opens a web URL
"URL",
url="https://docs.pyrogram.ml"
url="https://docs.pyrogram.org"
),
],
[ # Second row

View File

@ -1,4 +1,4 @@
"""This example shows how to get the full dialogs list of a user."""
"""This example shows how to get the full dialogs list (as user)."""
from pyrogram import Client

View File

@ -22,12 +22,12 @@ def answer(client, inline_query):
input_message_content=InputTextMessageContent(
"Here's how to install **Pyrogram**"
),
url="https://docs.pyrogram.ml/start/Installation",
url="https://docs.pyrogram.org/intro/install",
description="How to install Pyrogram",
thumb_url="https://i.imgur.com/JyxrStE.png",
reply_markup=InlineKeyboardMarkup(
[
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.ml/start/Installation")]
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.org/intro/install")]
]
)
),
@ -37,12 +37,12 @@ def answer(client, inline_query):
input_message_content=InputTextMessageContent(
"Here's how to use **Pyrogram**"
),
url="https://docs.pyrogram.ml/start/Usage",
url="https://docs.pyrogram.org/start/invoking",
description="How to use Pyrogram",
thumb_url="https://i.imgur.com/JyxrStE.png",
reply_markup=InlineKeyboardMarkup(
[
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.ml/start/Usage")]
[InlineKeyboardButton("Open website", url="https://docs.pyrogram.org/start/invoking")]
]
)
)

View File

@ -0,0 +1,13 @@
"""This example shows how to query an inline bot (as user)"""
from pyrogram import Client
# Create a new Client
app = Client("my_account")
with app:
# Get bot results for "Fuzz Universe" from the inline bot @vid
bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
# Send the first result (bot_results.results[0]) to your own chat (Saved Messages)
app.send_inline_bot_result("me", bot_results.query_id, bot_results.results[0].id)

View File

@ -1,17 +0,0 @@
"""This example shows how to query an inline bot"""
from pyrogram import Client
# Create a new Client
app = Client("my_account")
# Start the Client
app.start()
# Get bot results for "Fuzz Universe" from the inline bot @vid
bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
# Send the first result (bot_results.results[0]) to your own chat (Saved Messages)
app.send_inline_bot_result("me", bot_results.query_id, bot_results.results[0].id)
# Stop the client
app.stop()

View File

@ -8,7 +8,7 @@ from pyrogram import Client, Emoji, Filters
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
MESSAGE = "{} Welcome to [Pyrogram](https://docs.pyrogram.org/)'s group chat {}!" # Welcome message
app = Client("my_account")

View File

@ -24,11 +24,9 @@ if sys.version_info[:3] in [(3, 5, 0), (3, 5, 1), (3, 5, 2)]:
# Monkey patch the standard "typing" module because Python versions from 3.5.0 to 3.5.2 have a broken one.
sys.modules["typing"] = typing
__version__ = "0.12.0"
__version__ = "0.15.0-develop"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-2019 Dan Tès <https://github.com/delivrance>".replace(
"\xe8", "e" if sys.getfilesystemencoding() != "utf-8" else "\xe8"
)
__copyright__ = "Copyright (C) 2017-2019 Dan <https://github.com/delivrance>"
from .errors import RPCError
from .client import *

View File

@ -19,8 +19,8 @@
from importlib import import_module
from .all import objects
from .core.object import Object
from .core.tl_object import TLObject
for k, v in objects.items():
path, name = v.rsplit(".", 1)
Object.all[k] = getattr(import_module(path), name)
TLObject.all[k] = getattr(import_module(path), name)

View File

@ -19,10 +19,11 @@
from .future_salt import FutureSalt
from .future_salts import FutureSalts
from .gzip_packed import GzipPacked
from .list import List
from .message import Message
from .msg_container import MsgContainer
from .object import Object
from .primitives import (
Bool, BoolTrue, BoolFalse, Bytes, Double,
Int, Long, Int128, Int256, Null, String, Vector
)
from .tl_object import TLObject

View File

@ -16,29 +16,28 @@
# 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 datetime import datetime
from io import BytesIO
from .object import Object
from .primitives import Int, Long
from .tl_object import TLObject
class FutureSalt(Object):
class FutureSalt(TLObject):
ID = 0x0949d9dc
__slots__ = ["valid_since", "valid_until", "salt"]
QUALNAME = "FutureSalt"
def __init__(self, valid_since: int or datetime, valid_until: int or datetime, salt: int):
def __init__(self, valid_since: int, valid_until: int, salt: int):
self.valid_since = valid_since
self.valid_until = valid_until
self.salt = salt
@staticmethod
def read(b: BytesIO, *args) -> "FutureSalt":
valid_since = datetime.fromtimestamp(Int.read(b))
valid_until = datetime.fromtimestamp(Int.read(b))
valid_since = Int.read(b)
valid_until = Int.read(b)
salt = Long.read(b)
return FutureSalt(valid_since, valid_until, salt)

View File

@ -16,22 +16,21 @@
# 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 datetime import datetime
from io import BytesIO
from . import FutureSalt
from .object import Object
from .primitives import Int, Long
from .tl_object import TLObject
class FutureSalts(Object):
class FutureSalts(TLObject):
ID = 0xae500895
__slots__ = ["req_msg_id", "now", "salts"]
QUALNAME = "FutureSalts"
def __init__(self, req_msg_id: int, now: int or datetime, salts: list):
def __init__(self, req_msg_id: int, now: int, salts: list):
self.req_msg_id = req_msg_id
self.now = now
self.salts = salts
@ -39,7 +38,7 @@ class FutureSalts(Object):
@staticmethod
def read(b: BytesIO, *args) -> "FutureSalts":
req_msg_id = Long.read(b)
now = datetime.fromtimestamp(Int.read(b))
now = Int.read(b)
count = Int.read(b)
salts = [FutureSalt.read(b) for _ in range(count)]

View File

@ -19,24 +19,24 @@
from gzip import compress, decompress
from io import BytesIO
from .object import Object
from .primitives import Int, Bytes
from .tl_object import TLObject
class GzipPacked(Object):
class GzipPacked(TLObject):
ID = 0x3072cfa1
__slots__ = ["packed_data"]
QUALNAME = "GzipPacked"
def __init__(self, packed_data: Object):
def __init__(self, packed_data: TLObject):
self.packed_data = packed_data
@staticmethod
def read(b: BytesIO, *args) -> "GzipPacked":
# Return the Object itself instead of a GzipPacked wrapping it
return Object.read(
return TLObject.read(
BytesIO(
decompress(
Bytes.read(b)

View File

@ -16,14 +16,13 @@
# 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 .tl_object import TLObject
class ParseMode:
"""This class provides a convenient access to Parse Modes.
Parse Modes are intended to be used with any method that accepts the optional argument **parse_mode**.
"""
HTML = "html"
"""Set the parse mode to HTML style"""
class List(list, TLObject):
__slots__ = []
MARKDOWN = "markdown"
"""Set the parse mode to Markdown style"""
def __repr__(self):
return "pyrogram.api.core.List([{}])".format(
",".join(TLObject.__repr__(i) for i in self)
)

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