Compare commits

..

1 Commits

Author SHA1 Message Date
Dan
e3f1642797 Fix reading vectors of bare longs 2021-09-10 20:33:09 +02:00
436 changed files with 2749 additions and 3949 deletions

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

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

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

@ -0,0 +1,28 @@
---
name: Bug Report
about: Create a bug report affecting the library or the documentation
---
<!-- WARNING: Ignoring or altering this template could lead to the issue being closed as invalid -->
## 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/master.zip` and reproduced the issue using the latest development version.
## Description
A **clear** and **concise** description of the problem. Code snippets must be
[minimal, reproducible](https://stackoverflow.com/help/minimal-reproducible-example) and properly formatted.
``` python
from pyrogram import Client
...
```
## Traceback
The full traceback (if applicable).
```
Traceback (most recent call last):
File "main.py", line 1, in <module>
```

View File

@ -1,51 +0,0 @@
name: Bug report
description: Report issues affecting the framework or the documentation
body:
- type: checkboxes
attributes:
label: Checklist
options:
- label: I am sure the error is coming from Pyrogram's code and not elsewhere
required: true
- label: I have searched in the issue tracker for similar bug reports, including closed ones
required: true
- label: I ran `pip3 install -U https://github.com/pyrogram/pyrogram/archive/master.zip` and reproduced the issue using the latest development version
required: true
- type: textarea
attributes:
label: Description
description: Provide a clear and concise description of the issue
placeholder: Description...
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: Explain precisely how to reproduce the issue
placeholder: |
1.
2.
3.
validations:
required: true
- type: textarea
attributes:
label: Code example
description: Provide a [minimal, reproducible](https://stackoverflow.com/help/minimal-reproducible-example) and properly formatted example (if applicable)
placeholder: |
from pyrogram import Client
...
render: python
- type: textarea
attributes:
label: Logs
description: Provide the complete traceback (if applicable)
placeholder: |
Traceback (most recent call last):
File "main.py", line 1, in <module>
...
render: shell

View File

@ -2,7 +2,7 @@ blank_issues_enabled: false
contact_links:
- name: Ask Pyrogram related questions
url: https://stackoverflow.com/questions/tagged/pyrogram
about: This place is only for reporting issues about Pyrogram. You can ask questions at StackOverflow.
- name: Join the Telegram channel
about: This place is for issues about Pyrogram. If you'd like to ask a question, please do so at StackOverflow.
- name: Join the Telegram community
url: https://t.me/pyrogram
about: Join the official channel and stay tuned for news, updates and announcements.
about: Join the official channel to stay tuned for news and updates.

View File

@ -0,0 +1,14 @@
---
name: Feature Request
about: Suggest ideas, new features or enhancements
labels: "enhancement"
---
<!-- WARNING: Ignoring or altering this template could lead to the issue being closed as invalid -->
## 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.

View File

@ -1,20 +0,0 @@
name: Feature request
description: Suggest ideas, new features or enhancements
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: Checklist
options:
- label: I believe the idea is awesome and would benefit the framework
required: true
- label: I have searched in the issue tracker for similar requests, including closed ones
required: true
- type: textarea
attributes:
label: Description
description: Provide a detailed description of the request
placeholder: Description...
validations:
required: true

View File

@ -1,68 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ mtpager ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ mtpager ]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -1,6 +1,6 @@
name: Pyrogram
on: [push, pull_request]
on: [ push, pull_request ]
jobs:
build:
@ -8,8 +8,8 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [3.7, 3.8, 3.9, "3.10", "pypy-3.7", "pypy-3.8"]
os: [ ubuntu-latest, macos-latest, windows-latest ]
python-version: [ 3.6, 3.7, 3.8, 3.9 ]
steps:
- uses: actions/checkout@v2

View File

@ -1,11 +1,10 @@
## Include
include README.md COPYING COPYING.lesser NOTICE requirements.txt
recursive-include compiler *.py *.tl *.tsv *.txt
recursive-include tests *.py
## Exclude
prune pyrogram/errors/exceptions
prune pyrogram/raw/functions
prune pyrogram/raw/types
prune pyrogram/raw/base
exclude pyrogram/raw/all.py
exclude pyrogram/raw/all.py

2
NOTICE
View File

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

View File

@ -1,6 +1,6 @@
<p align="center">
<a href="https://github.com/pyrogram/pyrogram">
<img src="https://docs.pyrogram.org/_static/pyrogram.png" alt="Pyrogram" width="128">
<img src="https://i.imgur.com/BOgY9ai.png" alt="Pyrogram">
</a>
<br>
<b>Telegram MTProto API Framework for Python</b>
@ -9,19 +9,17 @@
Documentation
</a>
<a href="https://docs.pyrogram.org/releases">
<a href="https://github.com/pyrogram/pyrogram/releases">
Releases
</a>
<a href="https://t.me/pyrogram">
News
<a href="https://t.me/Pyrogram">
Community
</a>
</p>
## Pyrogram
> Elegant, modern and asynchronous Telegram MTProto API framework in Python for users and bots
``` python
from pyrogram import Client, filters
@ -30,33 +28,34 @@ app = Client("my_account")
@app.on_message(filters.private)
async def hello(client, message):
await message.reply("Hello from Pyrogram!")
await message.reply_text(f"Hello {message.from_user.mention}")
app.run()
```
**Pyrogram** is a modern, elegant and asynchronous [MTProto API](https://docs.pyrogram.org/topics/mtproto-vs-botapi)
framework. It enables you to easily interact with the main Telegram API through a user account (custom client) or a bot
identity (bot API alternative) using Python.
**Pyrogram** is a modern, elegant and easy-to-use [Telegram](https://telegram.org/) client library framework written
from the ground up in Python and C. It enables you to easily create custom Telegram client applications for both user
and bot identities (bot API alternative) via the [MTProto API](https://docs.pyrogram.org/topics/mtproto-vs-botapi).
### Support
### Features
If you'd like to support Pyrogram, you can consider:
- [Become a GitHub sponsor](https://github.com/sponsors/delivrance).
- [Become a LiberaPay patron](https://liberapay.com/delivrance).
- [Become an OpenCollective backer](https://opencollective.com/pyrogram).
### Key Features
- **Ready**: Install Pyrogram with pip and start building your applications right away.
- **Easy**: Makes the Telegram API simple and intuitive, while still allowing advanced usages.
- **Elegant**: Low-level details are abstracted and re-presented in a more convenient way.
- **Fast**: Boosted up by [TgCrypto](https://github.com/pyrogram/tgcrypto), a high-performance crypto library written in pure C.
- **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.
- **Asynchronous**: Allows both synchronous and asynchronous models to fit all usage needs.
- **Documented**: API methods, types and public interfaces are all [well documented](https://docs.pyrogram.org).
- **Type-hinted**: Types and methods are all type-hinted, enabling excellent editor support.
- **Async**: Fully asynchronous (also usable synchronously if wanted, for convenience).
- **Powerful**: Full access to Telegram's API to execute any official client action and more.
- **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.6 or higher.
- A [Telegram API key](https://docs.pyrogram.org/intro/setup#api-keys).
### Installing
@ -66,6 +65,11 @@ pip3 install pyrogram
### Resources
- Check out the docs at https://docs.pyrogram.org to learn more about Pyrogram, get started right
away and discover more in-depth material for building your client applications.
- Join the official channel at https://t.me/pyrogram and stay tuned for news, updates and announcements.
- The docs contain lots of resources to help you get started with Pyrogram: https://docs.pyrogram.org.
- Seeking extra help? Come join and ask our community: https://t.me/pyrogram.
- For other kind of inquiries, you can send a [message](https://t.me/haskell) or an [e-mail](mailto:dan@pyrogram.org).
### Copyright & License
- Copyright (C) 2017-2021 Dan <<https://github.com/delivrance>>
- Licensed under the terms of the [GNU Lesser General Public License v3 or later (LGPLv3+)](COPYING.lesser)

View File

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

View File

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

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -199,12 +199,12 @@ def start(format: bool = False):
shutil.rmtree(DESTINATION_PATH / "base", ignore_errors=True)
with open(HOME_PATH / "source/auth_key.tl") as f1, \
open(HOME_PATH / "source/sys_msgs.tl") as f2, \
open(HOME_PATH / "source/main_api.tl") as f3:
open(HOME_PATH / "source/sys_msgs.tl") as f2, \
open(HOME_PATH / "source/main_api.tl") as f3:
schema = (f1.read() + f2.read() + f3.read()).splitlines()
with open(HOME_PATH / "template/type.txt") as f1, \
open(HOME_PATH / "template/combinator.txt") as f2:
open(HOME_PATH / "template/combinator.txt") as f2:
type_tmpl = f1.read()
combinator_tmpl = f2.read()
@ -345,11 +345,11 @@ def start(format: bool = False):
sorted_args = sort_args(c.args)
arguments = (
(", *, " if c.args else "") +
(", ".join(
[f"{i[0]}: {get_type_hint(i[1])}"
for i in sorted_args]
) if sorted_args else "")
(", *, " if c.args else "") +
(", ".join(
[f"{i[0]}: {get_type_hint(i[1])}"
for i in sorted_args]
) if sorted_args else "")
)
fields = "\n ".join(
@ -408,7 +408,7 @@ def start(format: bool = False):
flag = FLAGS_RE_2.match(i[1])
if flag:
if flag.group(2) == "true" or flag.group(2).startswith("Vector"):
if flag.group(2) == "true":
write_flags.append(f"flags |= (1 << {flag.group(1)}) if self.{i[0]} else 0")
else:
write_flags.append(f"flags |= (1 << {flag.group(1)}) if self.{i[0]} is not None else 0")
@ -441,7 +441,7 @@ def start(format: bool = False):
sub_type = arg_type.split("<")[1][:-1]
write_types += "\n "
write_types += f"if self.{arg_name}:\n "
write_types += f"if self.{arg_name} is not None:\n "
write_types += "b.write(Vector(self.{}{}))\n ".format(
arg_name, f", {sub_type.title()}" if sub_type in CORE_TYPES else ""
)

View File

@ -101,13 +101,13 @@ userStatusLastWeek#7bf09fc = UserStatus;
userStatusLastMonth#77ebc742 = UserStatus;
chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long 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;
chat#41cbf256 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true id:long 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#6592a1a7 id:long title:string = Chat;
channel#8261ac61 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 has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channel#8261ac61 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 has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
chatFull#d18ee226 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> available_reactions:flags.18?Vector<string> = ChatFull;
channelFull#e13c3d20 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_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:long 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:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long 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.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer available_reactions:flags.30?Vector<string> = ChatFull;
chatFull#4dbdc099 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string = ChatFull;
channelFull#e9b27a17 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_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:long 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:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long 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.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string = ChatFull;
chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
@ -120,7 +120,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
message#38116ee0 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 edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
message#85d6cbe2 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 edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
messageService#2b085862 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?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction ttl_period:flags.25?int = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@ -166,9 +166,8 @@ messageActionInviteToGroupCall#502f92f7 call:InputGroupCall users:Vector<long> =
messageActionSetMessagesTTL#aa1afbfd period:int = MessageAction;
messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int = MessageAction;
messageActionSetChatTheme#aa786345 emoticon:string = MessageAction;
messageActionChatJoinedByRequest#ebbca3cb = MessageAction;
dialog#a8edd0f5 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 unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = 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;
@ -186,7 +185,7 @@ geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radiu
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
auth.authorization#33fb7bb8 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int user:User = auth.Authorization;
auth.authorization#cd050916 flags:# tmp_sessions:flags.0?int user:User = auth.Authorization;
auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;
auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization;
@ -200,7 +199,7 @@ inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags
peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings;
peerSettings#a518110d flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true autoarchived:flags.7?true invite_members:flags.8?true request_chat_broadcast:flags.10?true geo_distance:flags.6?int request_chat_title:flags.9?string request_chat_date:flags.9?int = PeerSettings;
peerSettings#733f2961 flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true autoarchived:flags.7?true invite_members:flags.8?true geo_distance:flags.6?int = PeerSettings;
wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
wallPaperNoFile#e0804116 id:long flags:# default:flags.1?true dark:flags.4?true settings:flags.2?WallPaperSettings = WallPaper;
@ -214,7 +213,7 @@ inputReportReasonCopyright#9b89f93a = ReportReason;
inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
inputReportReasonFake#f5ddd6e7 = ReportReason;
userFull#cf366521 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true id:long about:flags.1?string settings:PeerSettings 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 ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string = UserFull;
userFull#d697ff05 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true user:User about:flags.1?string settings:PeerSettings 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 ttl_period:flags.14?int theme_emoticon:flags.15?string = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact;
@ -357,9 +356,6 @@ updateChannelParticipant#985d3abb flags:# channel_id:long date:int actor_id:long
updateBotStopped#c4870a49 user_id:long date:int stopped:Bool qts:int = Update;
updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJSON = Update;
updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector<BotCommand> = Update;
updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector<long> = Update;
updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update;
updateMessageReactions#154798c3 peer:Peer msg_id:int reactions:MessageReactions = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -449,7 +445,7 @@ sendMessageUploadRoundAction#243e1c66 progress:int = SendMessageAction;
speakingInGroupCallAction#d92c2285 = SendMessageAction;
sendMessageHistoryImportAction#dbda9246 progress:int = SendMessageAction;
sendMessageChooseStickerAction#b05ac6b1 = SendMessageAction;
sendMessageEmojiInteraction#25972bcb emoticon:string msg_id:int interaction:DataJSON = SendMessageAction;
sendMessageEmojiInteraction#6a3233b6 emoticon:string interaction:DataJSON = SendMessageAction;
sendMessageEmojiInteractionSeen#b665902e emoticon:string = SendMessageAction;
contacts.found#b3134d9d my_results:Vector<Peer> results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;
@ -517,9 +513,9 @@ webPagePending#c586da1c id:long date:int = WebPage;
webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector<WebPageAttribute> = WebPage;
webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector<Authorization> = account.Authorizations;
account.authorizations#1250abde authorizations:Vector<Authorization> = account.Authorizations;
account.password#185b184f flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int = account.Password;
@ -531,10 +527,10 @@ auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;
chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int title:flags.8?string = ExportedChatInvite;
chatInviteExported#b18105e8 flags:# revoked:flags.0?true permanent:flags.5?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int = ExportedChatInvite;
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#300c44c1 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true title:string about:flags.5?string photo:Photo 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;
chatInvitePeek#61695cb0 chat:Chat expires:int = ChatInvite;
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
@ -542,12 +538,10 @@ inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
inputStickerSetAnimatedEmojiAnimations#cde3739 = InputStickerSet;
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true gifs:flags.6?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
messages.stickerSetNotModified#d3f924eb = messages.StickerSet;
botCommand#c27ac8c7 command:string description:string = BotCommand;
@ -564,8 +558,6 @@ 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;
keyboardButtonRequestPoll#bbc7515d flags:# quiz:flags.0?Bool text:string = KeyboardButton;
inputKeyboardButtonUserProfile#e988037b text:string user_id:InputUser = KeyboardButton;
keyboardButtonUserProfile#308660c1 text:string user_id:long = KeyboardButton;
keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
@ -593,7 +585,6 @@ messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity;
messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;
messageEntitySpoiler#32ca960f offset:int length:int = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel;
@ -611,7 +602,7 @@ channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:Vector<MessageRange> = ChannelMessagesFilter;
channelParticipant#c00c07c0 user_id:long date:int = ChannelParticipant;
channelParticipantSelf#35a8bfa7 flags:# via_request:flags.0?true user_id:long inviter_id:long date:int = ChannelParticipant;
channelParticipantSelf#28a8bc67 user_id:long inviter_id:long date:int = ChannelParticipant;
channelParticipantCreator#2fe601d3 flags:# user_id:long admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
channelParticipantAdmin#34c3bb53 flags:# can_edit:flags.0?true self:flags.1?true user_id:long inviter_id:flags.1?long promoted_by:long date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
channelParticipantBanned#6df8014e flags:# left:flags.0?true peer:Peer kicked_by:long date:int banned_rights:ChatBannedRights = ChannelParticipant;
@ -668,13 +659,11 @@ messageFwdHeader#5f777dce flags:# imported:flags.7?true from_id:flags.0?Peer fro
auth.codeTypeSms#72a3158c = auth.CodeType;
auth.codeTypeCall#741cd3e3 = auth.CodeType;
auth.codeTypeFlashCall#226ccefb = auth.CodeType;
auth.codeTypeMissedCall#d61ad6ee = auth.CodeType;
auth.sentCodeTypeApp#3dbb5986 length:int = auth.SentCodeType;
auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType;
auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType;
auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeType;
messages.botCallbackAnswer#36585ea4 flags:# alert:flags.1?true has_url:flags.3?true native_ui:flags.4?true message:flags.0?string url:flags.2?string cache_time:int = messages.BotCallbackAnswer;
@ -896,16 +885,13 @@ channelAdminLogEventActionExportedInviteRevoke#410a134e invite:ExportedChatInvit
channelAdminLogEventActionExportedInviteEdit#e90ebb59 prev_invite:ExportedChatInvite new_invite:ExportedChatInvite = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantVolume#3e7f6847 participant:GroupCallParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeHistoryTTL#6e941a38 prev_value:int new_value:int = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantJoinByRequest#afb6144a invite:ExportedChatInvite approved_by:long = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleNoForwards#cb2ac766 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionSendMessage#278f2868 message:Message = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeAvailableReactions#9cf7f76a prev_value:Vector<string> new_value:Vector<string> = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeTheme#fe69018d prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent;
channels.adminLogResults#ed8af74d events:Vector<ChannelAdminLogEvent> chats:Vector<Chat> users:Vector<User> = channels.AdminLogResults;
channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?true invite:flags.2?true ban:flags.3?true unban:flags.4?true kick:flags.5?true unkick:flags.6?true promote:flags.7?true demote:flags.8?true info:flags.9?true settings:flags.10?true pinned:flags.11?true edit:flags.12?true delete:flags.13?true group_call:flags.14?true invites:flags.15?true send:flags.16?true = ChannelAdminLogEventsFilter;
channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?true invite:flags.2?true ban:flags.3?true unban:flags.4?true kick:flags.5?true unkick:flags.6?true promote:flags.7?true demote:flags.8?true info:flags.9?true settings:flags.10?true pinned:flags.11?true edit:flags.12?true delete:flags.13?true group_call:flags.14?true invites:flags.15?true = ChannelAdminLogEventsFilter;
popularContact#5ce14175 client_id:long importers:int = PopularContact;
@ -1074,7 +1060,7 @@ inputWallPaperNoFile#967a462e id:long = InputWallPaper;
account.wallPapersNotModified#1c199183 = account.WallPapers;
account.wallPapers#cdc3858c hash:long wallpapers:Vector<WallPaper> = account.WallPapers;
codeSettings#8a6469c2 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true logout_tokens:flags.6?Vector<bytes> = CodeSettings;
codeSettings#debebe83 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true = CodeSettings;
wallPaperSettings#1dc1bca4 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings;
@ -1114,7 +1100,7 @@ restrictionReason#d072acb4 platform:string reason:string text:string = Restricti
inputTheme#3c5693e9 id:long access_hash:long = InputTheme;
inputThemeSlug#f5890df1 slug:string = InputTheme;
theme#a00e67d6 flags:# creator:flags.0?true default:flags.1?true for_chat:flags.5?true id:long access_hash:long slug:string title:string document:flags.2?Document settings:flags.3?Vector<ThemeSettings> emoticon:flags.6?string installs_count:flags.4?int = Theme;
theme#e802b8dc flags:# creator:flags.0?true default:flags.1?true for_chat:flags.5?true id:long access_hash:long slug:string title:string document:flags.2?Document settings:flags.3?ThemeSettings installs_count:flags.4?int = Theme;
account.themesNotModified#f41eb622 = account.Themes;
account.themes#9a3d8c6d hash:long themes:Vector<Theme> = account.Themes;
@ -1226,7 +1212,7 @@ messages.historyImportParsed#5e0fb7b9 flags:# pm:flags.0?true group:flags.1?true
messages.affectedFoundMessages#ef8d3e6c pts:int pts_count:int offset:int messages:Vector<int> = messages.AffectedFoundMessages;
chatInviteImporter#8c5adfd9 flags:# requested:flags.0?true user_id:long date:int about:flags.2?string approved_by:flags.1?long = ChatInviteImporter;
chatInviteImporter#b5cd5f4 user_id:long date:int = ChatInviteImporter;
messages.exportedChatInvites#bdc62dcc count:int invites:Vector<ExportedChatInvite> users:Vector<User> = messages.ExportedChatInvites;
@ -1263,42 +1249,15 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
sponsoredMessage#3a836df8 flags:# random_id:bytes from_id:flags.3?Peer chat_invite:flags.4?ChatInvite chat_invite_hash:flags.4?string channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector<MessageEntity> = SponsoredMessage;
chatTheme#ed0b5c33 emoticon:string theme:Theme dark_theme:Theme = ChatTheme;
account.chatThemesNotModified#e011e1c4 = account.ChatThemes;
account.chatThemes#fe4cbebd hash:int themes:Vector<ChatTheme> = account.ChatThemes;
sponsoredMessage#2a3c381f flags:# random_id:bytes from_id:Peer start_param:flags.0?string message:string entities:flags.1?Vector<MessageEntity> = SponsoredMessage;
messages.sponsoredMessages#65a4c7d5 messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
searchResultsCalendarPeriod#c9b0539f date:int min_msg_id:int max_msg_id:int count:int = SearchResultsCalendarPeriod;
messages.searchResultsCalendar#147ee23c flags:# inexact:flags.0?true count:int min_date:int min_msg_id:int offset_id_offset:flags.1?int periods:Vector<SearchResultsCalendarPeriod> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SearchResultsCalendar;
searchResultPosition#7f648b67 msg_id:int date:int offset:int = SearchResultsPosition;
messages.searchResultsPositions#53b22baf count:int positions:Vector<SearchResultsPosition> = messages.SearchResultsPositions;
channels.sendAsPeers#8356cda9 peers:Vector<Peer> chats:Vector<Chat> users:Vector<User> = channels.SendAsPeers;
users.userFull#3b6d152e full_user:UserFull chats:Vector<Chat> users:Vector<User> = users.UserFull;
messages.peerSettings#6880b94d settings:PeerSettings chats:Vector<Chat> users:Vector<User> = messages.PeerSettings;
auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut;
reactionCount#6fb250d1 flags:# chosen:flags.0?true reaction:string count:int = ReactionCount;
messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> = MessageReactions;
messages.messageReactionsList#31bd492d flags:# count:int reactions:Vector<MessagePeerReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
availableReaction#c077ec01 flags:# inactive:flags.0?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document around_animation:flags.1?Document center_icon:flags.1?Document = AvailableReaction;
messages.availableReactionsNotModified#9f071957 = messages.AvailableReactions;
messages.availableReactions#768e3aad hash:int reactions:Vector<AvailableReaction> = messages.AvailableReactions;
messages.translateNoResult#67ca4737 = messages.TranslatedText;
messages.translateResultText#a214f7d0 text:string = messages.TranslatedText;
messagePeerReaction#51b67eff flags:# big:flags.0?true unread:flags.1?true peer_id:Peer reaction:string = MessagePeerReaction;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1312,7 +1271,7 @@ invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;
auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode;
auth.signUp#80eee427 phone_number:string phone_code_hash:string first_name:string last_name:string = auth.Authorization;
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
auth.logOut#3e72ba19 = auth.LoggedOut;
auth.logOut#5717da40 = Bool;
auth.resetAuthorizations#9fab0d1a = Bool;
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
auth.importAuthorization#a57a7dad id:long bytes:bytes = auth.Authorization;
@ -1385,10 +1344,10 @@ account.resetWallPapers#bb3b9804 = Bool;
account.getAutoDownloadSettings#56da0b3f = account.AutoDownloadSettings;
account.saveAutoDownloadSettings#76f36233 flags:# low:flags.0?true high:flags.1?true settings:AutoDownloadSettings = Bool;
account.uploadTheme#1c3db333 flags:# file:InputFile thumb:flags.0?InputFile file_name:string mime_type:string = Document;
account.createTheme#652e4400 flags:# slug:string title:string document:flags.2?InputDocument settings:flags.3?Vector<InputThemeSettings> = Theme;
account.updateTheme#2bf40ccc flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument settings:flags.3?Vector<InputThemeSettings> = Theme;
account.createTheme#8432c21f flags:# slug:string title:string document:flags.2?InputDocument settings:flags.3?InputThemeSettings = Theme;
account.updateTheme#5cb367d5 flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument settings:flags.3?InputThemeSettings = Theme;
account.saveTheme#f257106c theme:InputTheme unsave:Bool = Bool;
account.installTheme#c727bb3b flags:# dark:flags.0?true theme:flags.1?InputTheme format:flags.2?string base_theme:flags.3?BaseTheme = Bool;
account.installTheme#7ae43737 flags:# dark:flags.0?true format:flags.1?string theme:flags.1?InputTheme = Bool;
account.getTheme#8d9d742b format:string theme:InputTheme document_id:long = Theme;
account.getThemes#7206e458 format:string hash:long = account.Themes;
account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool;
@ -1399,12 +1358,10 @@ account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = Globa
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
account.resetPassword#9308ce1b = account.ResetPasswordResult;
account.declinePasswordReset#4c9409f6 = Bool;
account.getChatThemes#d638de89 hash:long = account.Themes;
account.setAuthorizationTTL#bf899aa0 authorization_ttl_days:int = Bool;
account.changeAuthorizationSettings#40f48462 flags:# hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;
account.getChatThemes#d6d71d7b hash:int = account.ChatThemes;
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;
contacts.getContactIDs#7adc669d hash:long = Vector<int>;
@ -1433,15 +1390,15 @@ messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags
messages.getHistory#4423e6c5 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
messages.search#a0fda762 flags:# peer:InputPeer q:string from_id:flags.0?InputPeer top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int = messages.AffectedHistory;
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.forwardMessages#cc30290b flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.sendMessage#520c3870 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int = Updates;
messages.sendMedia#3491eba9 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int = Updates;
messages.forwardMessages#d9fee60e flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer schedule_date:flags.10?int = Updates;
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
messages.getPeerSettings#3672e09c peer:InputPeer = PeerSettings;
messages.report#8953ab4e peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
messages.getChats#49e9528f id:Vector<long> = messages.Chats;
messages.getFullChat#aeb00b34 chat_id:long = messages.ChatFull;
@ -1465,10 +1422,10 @@ messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages
messages.getStickers#d5a5d3a1 emoticon:string hash:long = messages.Stickers;
messages.getAllStickers#b8a0a1a8 hash:long = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#a02ce5d5 flags:# legacy_revoke_permanent:flags.2?true request_needed:flags.3?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int title:flags.4?string = ExportedChatInvite;
messages.exportChatInvite#14b9bcd7 flags:# legacy_revoke_permanent:flags.2?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#c8a0ec74 stickerset:InputStickerSet hash:int = messages.StickerSet;
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates;
@ -1482,7 +1439,7 @@ messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool;
messages.sendInlineBotResult#7aa11297 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.sendInlineBotResult#220815b0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string schedule_date:flags.10?int = Updates;
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
messages.editMessage#48f71778 flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.15?int = Updates;
messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
@ -1518,7 +1475,7 @@ messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool;
messages.getUnreadMentions#46578472 peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readMentions#f0189d3 peer:InputPeer = messages.AffectedHistory;
messages.getRecentLocations#702a40e0 peer:InputPeer limit:int hash:long = messages.Messages;
messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.sendMultiMedia#cc0110cb flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int = Updates;
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
@ -1529,6 +1486,7 @@ messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
messages.getStatsURL#812c2ae6 flags:# dark:flags.0?true peer:InputPeer params:string = StatsURL;
messages.editChatAbout#def60797 peer:InputPeer about:string = Bool;
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
@ -1562,30 +1520,15 @@ messages.uploadImportedMedia#2a862092 peer:InputPeer import_id:long file_name:st
messages.startHistoryImport#b43df344 peer:InputPeer import_id:long = Bool;
messages.getExportedChatInvites#a2b5a3f6 flags:# revoked:flags.3?true peer:InputPeer admin_id:InputUser offset_date:flags.2?int offset_link:flags.2?string limit:int = messages.ExportedChatInvites;
messages.getExportedChatInvite#73746f5c peer:InputPeer link:string = messages.ExportedChatInvite;
messages.editExportedChatInvite#bdca2f75 flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int request_needed:flags.3?Bool title:flags.4?string = messages.ExportedChatInvite;
messages.editExportedChatInvite#2e4ffbe flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int = messages.ExportedChatInvite;
messages.deleteRevokedExportedChatInvites#56987bd5 peer:InputPeer admin_id:InputUser = Bool;
messages.deleteExportedChatInvite#d464a42b peer:InputPeer link:string = Bool;
messages.getAdminsWithInvites#3920e6ef peer:InputPeer = messages.ChatAdminsWithInvites;
messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.getChatInviteImporters#26fb7289 peer:InputPeer link:string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.setHistoryTTL#b80e5fe4 peer:InputPeer period:int = Updates;
messages.checkHistoryImportPeer#5dc60f03 peer:InputPeer = messages.CheckedHistoryImportPeer;
messages.setChatTheme#e63be13f peer:InputPeer emoticon:string = Updates;
messages.getMessageReadParticipants#2c6f97b7 peer:InputPeer msg_id:int = Vector<long>;
messages.getSearchResultsCalendar#49f0bde9 peer:InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsCalendar;
messages.getSearchResultsPositions#6e9583a3 peer:InputPeer filter:MessagesFilter offset_id:int limit:int = messages.SearchResultsPositions;
messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPeer user_id:InputUser = Updates;
messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates;
messages.toggleNoForwards#b11eafa2 peer:InputPeer enabled:Bool = Updates;
messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
messages.sendReaction#25690ce4 flags:# big:flags.1?true peer:InputPeer msg_id:int reaction:flags.0?string = Updates;
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
messages.getMessageReactionsList#e0ee6b77 flags:# peer:InputPeer id:int reaction:flags.0?string offset:flags.1?string limit:int = messages.MessageReactionsList;
messages.setChatAvailableReactions#14050ea6 peer:InputPeer available_reactions:Vector<string> = Updates;
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
messages.setDefaultReaction#d960c4d4 reaction:string = Bool;
messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText;
messages.getUnreadReactions#e85bae1a peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readReactions#82e251d7 peer:InputPeer = messages.AffectedHistory;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1630,7 +1573,8 @@ help.getCountriesList#735787a8 lang_code:string hash:int = help.CountriesList;
channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
channels.reportSpam#f44a8315 channel:InputChannel participant:InputPeer id:Vector<int> = Bool;
channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = messages.AffectedHistory;
channels.reportSpam#fe087810 channel:InputChannel user_id:InputUser id:Vector<int> = Bool;
channels.getMessages#ad8c9a23 channel:InputChannel id:Vector<InputMessage> = messages.Messages;
channels.getParticipants#77ced9d0 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int hash:long = channels.ChannelParticipants;
channels.getParticipant#a0ab6cc6 channel:InputChannel participant:InputPeer = channels.ChannelParticipant;
@ -1665,8 +1609,6 @@ channels.getInactiveChannels#11e831ee = messages.InactiveChats;
channels.convertToGigagroup#b290c69 channel:InputChannel = Updates;
channels.viewSponsoredMessage#beaedb94 channel:InputChannel random_id:bytes = Bool;
channels.getSponsoredMessages#ec210fbf channel:InputChannel = messages.SponsoredMessages;
channels.getSendAs#dc770ee peer:InputPeer = channels.SendAsPeers;
channels.deleteParticipantHistory#367544db channel:InputChannel participant:InputPeer = messages.AffectedHistory;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
@ -1734,4 +1676,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
// LAYER 138
// LAYER 133

View File

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

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -158,7 +158,6 @@ def pyrogram_api():
send_venue
send_contact
send_cached_media
send_reaction
edit_message_text
edit_message_caption
edit_message_media
@ -181,17 +180,14 @@ def pyrogram_api():
retract_vote
send_dice
search_messages
search_messages_count
search_global
search_global_count
download_media
get_discussion_message
""",
chats="""
Chats
join_chat
leave_chat
ban_chat_member
kick_chat_member
unban_chat_member
restrict_chat_member
promote_chat_member
@ -227,9 +223,6 @@ def pyrogram_api():
mark_chat_unread
get_chat_event_log
get_chat_online_count
get_send_as_chats
set_send_as_chat
set_chat_protected_content
""",
users="""
Users
@ -260,8 +253,6 @@ def pyrogram_api():
get_chat_admin_invite_links_count
get_chat_admins_with_invite_links
delete_chat_admin_invite_links
approve_chat_join_request
decline_chat_join_request
""",
contacts="""
Contacts
@ -287,7 +278,6 @@ def pyrogram_api():
send_game
set_game_score
get_game_high_scores
set_bot_commands
""",
authorization="""
Authorization
@ -364,7 +354,6 @@ def pyrogram_api():
ChatEvent
ChatEventFilter
ChatMemberUpdated
ChatJoinRequest
Dialog
Restriction
""",
@ -389,7 +378,6 @@ def pyrogram_api():
Poll
PollOption
Dice
Reaction
VoiceChatScheduled
VoiceChatStarted
VoiceChatEnded
@ -426,8 +414,6 @@ def pyrogram_api():
InlineQueryResultArticle
InlineQueryResultPhoto
InlineQueryResultAnimation
InlineQueryResultAudio
InlineQueryResultVideo
ChosenInlineResult
""",
input_message_content="""
@ -513,7 +499,7 @@ def pyrogram_api():
Chat.set_title
Chat.set_description
Chat.set_photo
Chat.ban_member
Chat.kick_member
Chat.unban_member
Chat.restrict_member
Chat.promote_member
@ -524,7 +510,6 @@ def pyrogram_api():
Chat.join
Chat.leave
Chat.mark_unread
Chat.set_protected_content
""",
user="""
User
@ -544,11 +529,6 @@ def pyrogram_api():
inline_query="""
InlineQuery
InlineQuery.answer
""",
chat_join_request="""
ChatJoinRequest
ChatJoinRequest.approve
ChatJoinRequest.decline
"""
)

View File

@ -1,11 +1,12 @@
Bound Methods
=============
Some Pyrogram types define what are called bound methods. Bound methods are functions attached to a type which are
accessed via an instance of that type. They make it even easier to call specific methods by automatically inferring
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
@ -14,7 +15,7 @@ some of the required arguments.
@app.on_message()
def hello(client, message)
message.reply("hi")
message.reply_text("hi")
app.run()
@ -91,17 +92,3 @@ InlineQuery
:hidden:
{inline_query_toctree}
ChatJoinRequest
---------------
.. hlist::
:columns: 2
{chat_join_request_hlist}
.. toctree::
:hidden:
{chat_join_request_toctree}

View File

@ -1,17 +1,18 @@
Available Methods
=================
This page is about Pyrogram methods. All the methods listed here are bound to a :class:`~pyrogram.Client` instance.
Some other utility functions can instead be found in the main package directly.
This page is about Pyrogram methods. All the methods listed here are bound to a :class:`~pyrogram.Client` instance,
except for :meth:`~pyrogram.idle()`, which is a special function that can be found in the main package directly.
.. code-block:: python
:emphasize-lines: 6
from pyrogram import Client
app = Client("my_account")
with app:
app.send_message("me", "hi")
app.send_message("haskell", "hi")
.. contents:: Contents
:backlinks: none

View File

@ -6,6 +6,7 @@ Unless required as argument to a client method, most of the types don't need to
are only returned by other methods. You also don't need to import them, unless you want to type-hint your variables.
.. code-block:: python
:emphasize-lines: 1
from pyrogram.types import User, Message, ...

View File

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

View File

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

View File

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

View File

@ -52,7 +52,6 @@ CHANNEL_TOO_LARGE The channel is too large to be deleted; this error is issued w
CHAT_ABOUT_NOT_MODIFIED The chat about text was not modified because you tried to edit it using the same content
CHAT_ABOUT_TOO_LONG The chat about text is too long
CHAT_ADMIN_REQUIRED The method requires chat admin privileges
CHAT_FORWARDS_RESTRICTED The chat restricts forwarding content
CHAT_ID_EMPTY The provided chat id is empty
CHAT_ID_INVALID The chat id being used is invalid or not known yet. Make sure you see the chat before interacting with it
CHAT_INVALID The chat is invalid
@ -62,7 +61,6 @@ CHAT_NOT_MODIFIED The chat settings (title, permissions, photo, etc..) were not
CHAT_RESTRICTED The chat is restricted and cannot be used
CHAT_SEND_INLINE_FORBIDDEN You cannot use inline bots to send messages in this chat
CHAT_TITLE_EMPTY The chat title is empty
CHAT_TOO_BIG The chat is too big for this action
CODE_EMPTY The provided code is empty
CODE_HASH_INVALID The provided code hash invalid
CODE_INVALID The provided code is invalid (i.e. from email)
@ -250,7 +248,7 @@ RANDOM_ID_INVALID The provided random ID is invalid
RANDOM_LENGTH_INVALID The random length is invalid
RANGES_INVALID Invalid range provided
REACTION_EMPTY The reaction provided is empty
REACTION_INVALID Invalid reaction provided (only valid emoji are allowed)
REACTION_INVALID Invalid reaction provided (only emoji are allowed)
REFLECTOR_NOT_AVAILABLE The call reflector is not available
REPLY_MARKUP_BUY_EMPTY Reply markup for buy button empty
REPLY_MARKUP_GAME_EMPTY The provided reply markup for the game is empty

1 id message
52 CHAT_ABOUT_NOT_MODIFIED The chat about text was not modified because you tried to edit it using the same content
53 CHAT_ABOUT_TOO_LONG The chat about text is too long
54 CHAT_ADMIN_REQUIRED The method requires chat admin privileges
CHAT_FORWARDS_RESTRICTED The chat restricts forwarding content
55 CHAT_ID_EMPTY The provided chat id is empty
56 CHAT_ID_INVALID The chat id being used is invalid or not known yet. Make sure you see the chat before interacting with it
57 CHAT_INVALID The chat is invalid
61 CHAT_RESTRICTED The chat is restricted and cannot be used
62 CHAT_SEND_INLINE_FORBIDDEN You cannot use inline bots to send messages in this chat
63 CHAT_TITLE_EMPTY The chat title is empty
CHAT_TOO_BIG The chat is too big for this action
64 CODE_EMPTY The provided code is empty
65 CODE_HASH_INVALID The provided code hash invalid
66 CODE_INVALID The provided code is invalid (i.e. from email)
248 RANDOM_LENGTH_INVALID The random length is invalid
249 RANGES_INVALID Invalid range provided
250 REACTION_EMPTY The reaction provided is empty
251 REACTION_INVALID Invalid reaction provided (only valid emoji are allowed) Invalid reaction provided (only emoji are allowed)
252 REFLECTOR_NOT_AVAILABLE The call reflector is not available
253 REPLY_MARKUP_BUY_EMPTY Reply markup for buy button empty
254 REPLY_MARKUP_GAME_EMPTY The provided reply markup for the game is empty

View File

@ -2,7 +2,7 @@ id message
ACTIVE_USER_REQUIRED The method is only available to already activated users
AUTH_KEY_INVALID The key is invalid
AUTH_KEY_PERM_EMPTY The method is unavailable for temporary authorization key, not bound to permanent
AUTH_KEY_UNREGISTERED The key is not registered in the system. Delete your session file and login again
AUTH_KEY_UNREGISTERED The key is not registered in the system
SESSION_EXPIRED The authorization has expired
SESSION_PASSWORD_NEEDED The two-step verification is enabled and a password is required
SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions

1 id message
2 ACTIVE_USER_REQUIRED The method is only available to already activated users
3 AUTH_KEY_INVALID The key is invalid
4 AUTH_KEY_PERM_EMPTY The method is unavailable for temporary authorization key, not bound to permanent
5 AUTH_KEY_UNREGISTERED The key is not registered in the system. Delete your session file and login again The key is not registered in the system
6 SESSION_EXPIRED The authorization has expired
7 SESSION_PASSWORD_NEEDED The two-step verification is enabled and a password is required
8 SESSION_REVOKED The authorization has been invalidated, because of the user terminating all sessions

View File

@ -1,3 +1,2 @@
id message
Timeout Telegram is having internal problems. Please try again later.
ApiCallError Telegram is having internal problems. Please try again later.
Timeout Telegram is having internal problems. Please try again later.
1 id message
2 Timeout Telegram is having internal problems. Please try again later.
ApiCallError Telegram is having internal problems. Please try again later.

8
docs/README.md Normal file
View File

@ -0,0 +1,8 @@
# Pyrogram Docs
- Install requirements.
- Install `pandoc` and `latexmk`.
- HTML: `make html`
- PDF: `make latexpdf`
TODO: Explain better

View File

@ -1,6 +1,6 @@
sphinx
sphinx_rtd_theme==1.0.0
sphinx_rtd_theme
sphinx_copybutton
pypandoc
requests
sphinx-autobuild
sphinx-autobuild

7
docs/robots.txt Normal file
View File

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

84
docs/scripts/releases.py Normal file
View File

@ -0,0 +1,84 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2021 Dan <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.
**Contents**
""".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))

81
docs/scripts/sitemap.py Normal file
View File

@ -0,0 +1,81 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-2021 Dan <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 datetime
import os
canonical = "https://docs.pyrogram.org/"
dirs = {
".": ("weekly", 1.0),
"intro": ("weekly", 0.9),
"start": ("weekly", 0.9),
"api": ("weekly", 0.8),
"topics": ("weekly", 0.8),
"releases": ("weekly", 0.8),
"telegram": ("weekly", 0.6)
}
def now():
return datetime.datetime.today().strftime("%Y-%m-%d")
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')
urls = []
def search(path):
try:
for j in os.listdir(path):
search(f"{path}/{j}")
except NotADirectoryError:
if not path.endswith(".rst"):
return
path = path.split("/")[2:]
if path[0].endswith(".rst"):
folder = "."
else:
folder = path[0]
path = f"{canonical}{'/'.join(path)}"[:-len(".rst")]
if path.endswith("index"):
path = path[:-len("index")]
urls.append((path, now(), *dirs[folder]))
search("../source")
urls.sort(key=lambda x: x[3], reverse=True)
for i in urls:
f.write(f" <url>\n")
f.write(f" <loc>{i[0]}</loc>\n")
f.write(f" <lastmod>{i[1]}</lastmod>\n")
f.write(f" <changefreq>{i[2]}</changefreq>\n")
f.write(f" <priority>{i[3]}</priority>\n")
f.write(f" </url>\n")
f.write("</urlset>")

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -8,6 +8,7 @@ found starting from this page.
This page is about the Client class, which exposes high-level methods for an easy access to the API.
.. code-block:: python
:emphasize-lines: 1-3
from pyrogram import Client

View File

@ -1,12 +1,16 @@
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

View File

@ -5,6 +5,7 @@ Handlers are used to instruct Pyrogram about which kind of updates you'd like to
For a much more convenient way of registering callback functions have a look at :doc:`Decorators <decorators>` instead.
.. code-block:: python
:emphasize-lines: 2, 11
from pyrogram import Client
from pyrogram.handlers import MessageHandler

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -29,37 +29,35 @@ from pygments.styles.friendly import FriendlyStyle
FriendlyStyle.background_color = "#f3f2f1"
project = "Pyrogram"
copyright = f"2017-present, Dan"
copyright = f"2017-{datetime.now().year}, Dan"
author = "Dan"
version = ".".join(__version__.split(".")[:-1])
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx.ext.autosummary",
"sphinx_copybutton"
"sphinx_copybutton",
"sphinx_tabs.tabs"
]
master_doc = "index"
source_suffix = ".rst"
autodoc_member_order = "bysource"
templates_path = ["_resources/templates"]
html_copy_source = False
version = __version__
release = version
templates_path = ["_templates"]
napoleon_use_rtype = False
napoleon_use_param = False
pygments_style = "friendly"
copybutton_prompt_text = "$ "
suppress_warnings = ["image.not_readable"]
html_title = "Pyrogram Documentation"
html_theme = "sphinx_rtd_theme"
html_static_path = ["_resources/static"]
html_static_path = ["_static"]
html_show_sourcelink = True
html_show_copyright = False
html_theme_options = {
@ -67,15 +65,17 @@ html_theme_options = {
"collapse_navigation": True,
"sticky_navigation": False,
"logo_only": True,
"display_version": False,
"display_version": True,
"style_external_links": True
}
html_logo = "_resources/static/img/pyrogram.png"
html_favicon = "_resources/static/img/favicon.ico"
napoleon_use_param = False
html_logo = "_images/pyrogram.png"
html_favicon = "_images/favicon.ico"
latex_engine = "xelatex"
latex_logo = "_resources/static/img/pyrogram.png"
latex_logo = "_images/pyrogram.png"
latex_elements = {
"pointsize": "12pt",

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

@ -0,0 +1,407 @@
Pyrogram FAQ
============
.. role:: strike
:class: strike
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
:depth: 1
:local:
-----
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 to 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.
- **Asynchronous**: Allows both synchronous and asynchronous models to fit all usage needs.
- **Documented**: API methods, types and public interfaces are all well documented.
- **Type-hinted**: Types and methods are all type-hinted, enabling excellent editor support.
- **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
Why is Pyrogram defined as both Client Library and Framework?
-------------------------------------------------------------
Simply because it falls in both categories, depending on how you use it.
Pyrogram as a client library makes it easy and intuitive accessing the Telegram API by offering idiomatic Python code
that is generated or hand-written. Low-level details and client-server communication protocols are handled under the
hood. Pyrogram acts as a client library when *you call* its methods and use its types in a batch application that
executes a set of instructions.
Pyrogram as a framework makes it easy to handle live events by allowing you to register event handlers that will be
executed as soon as they arrive from the server side. Pyrogram acts as a framework when it's Pyrogram itself that
*calls your code*, that is, your registered event handlers. Such applications are usually started and left online
indefinitely, until you decide to stop them.
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/WvwBoZo.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 Webhooks?
-------------------
Lots of people ask this question because they are used to the bot API, but things are different in Pyrogram!
There is no webhook in Pyrogram, simply because there is no HTTP involved, by default. However, a similar technique is
being used to make receiving updates efficient.
Pyrogram uses persistent connections via TCP sockets to interact with the server and instead of actively asking for
updates every time (polling), Pyrogram will simply sit down and wait for the server to send updates by itself
the very moment they are available (server push).
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 account; 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_id values in Pyrogram?
-----------------------------------------------
Yes! All file ids you take or might have taken from the Bot API are 100% compatible and re-usable in Pyrogram.
The opposite is also valid, you can take any file id generated by Pyrogram and re-use in the Bot API.
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 terminated 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. More information about this block can be found at
`Wikipedia <https://en.wikipedia.org/wiki/Blocking_Telegram_in_Russia>`_.
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 (currently 5 DCs, each of which can
work independently) spread in different locations worldwide. However, some of the less busy DCs have been lately
dismissed and their IP addresses are now kept as aliases to the nearest one.
.. csv-table:: Production Environment
:header: ID, Location, IPv4, IPv6
:widths: auto
:align: center
DC1, "MIA, Miami FL, USA", ``149.154.175.53``, ``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.130``, ``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``
.. centered:: More info about the Test Environment can be found :doc:`here <topics/test-servers>`.
***** Alias DC
Thanks to `@FrayxRulez <https://t.me/tgbetachat/104921>`_ for telling about alias DCs.
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.
Thanks to `@gabriel <https://t.me/AnotherGroup/217699>`_ for confirming the feature was not implemented yet.
Why is my client reacting slowly in supergroups?
------------------------------------------------
This issue affects only some supergroups or only some members within the same supergroup. Mostly, it affects supergroups
whose creator's account (and thus the supergroup itself) lives inside a **different DC**, far away from yours, but could
also depend on where a member is connecting from.
Because of how Telegram works internally, every single message you receive from and send to other members must pass
through the creator's DC, and in the worst case where you, the creator and another member all belong to three different
DCs, the other member messages have to go through from its DC to the creator's DC and finally to your DC. This process
will inevitably take its time.
To confirm this theory and see it by yourself, you can test in a supergroup where you are sure all parties live
inside the same DC. In this case the responses will be faster.
Another reason that makes responses come slowly is that messages are **dispatched by priority**. Depending on the kind
of member, some users receive messages faster than others and for big and busy supergroups the delay might become
noticeable, especially if you are among the lower end of the priority list:
1. Creator.
2. Administrators.
3. Bots.
4. Mentioned users.
5. Recent online users.
6. Everyone else.
Thanks to `@Manuel15 <https://t.me/PyrogramChat/76990>`_ for the priority list.
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 argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
- The chat id refers to a user or chat your current session hasn't met yet.
About the last point: in order for you to meet a user and thus communicate with them, you should ask yourself how to
contact people using official apps. The answer is the same for Pyrogram too and involves normal usages such as searching
for usernames, meeting them in a common group, having their phone contacts saved, getting a message mentioning them
(either a forward or a mention in the message text) or obtaining the dialogs list.
Code hangs when I stop, restart, add/remove_handler
---------------------------------------------------
You tried to ``.stop()``, ``.restart()``, ``.add_handler()`` or ``.remove_handler()`` *inside* a running handler, but
that can't be done because the way Pyrogram deals with handlers would make it hang.
When calling one of the methods above inside an event handler, Pyrogram needs to wait for all running handlers to finish
in order to safely continue. In other words, since your handler is blocking the execution by waiting for the called
method to finish and since Pyrogram needs to wait for your handler to finish, you are left with a deadlock.
The solution to this problem is to pass ``block=False`` to such methods so that they return immediately and the actual
code called asynchronously.
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 terminal altogether.
Uploading with URLs gives error WEBPAGE_CURL_FAILED
---------------------------------------------------
When uploading media files using an URL, the server automatically tries to download the media and uploads it to the
Telegram cloud. This error usually happens in case the provided URL is not publicly accessible by Telegram itself or the
media exceeds 20 MB in size. In such cases, your only option is to download the media yourself and upload from your
local machine.
sqlite3.OperationalError: database is locked
--------------------------------------------
This error occurs when more than one process is using the same session file, that is, when you run two or more clients
at the same time using the same session name.
It could also occur when a background script is still running and you forgot about it. In this case, you either restart
your system or find and kill the process that is locking the database. On Unix based systems, you can do the following:
#. ``cd`` into your session file directory.
#. ``fuser my_account.session`` to find the process id.
#. ``kill 1234`` to gracefully stop the process.
#. If the last command doesn't help, use ``kill -9 1234`` instead.
If you want to run multiple clients on the same account, you must authorize your account (either user or bot)
from the beginning every time, and use different session names for each parallel client you are going to use.
sqlite3.OperationalError: unable to open database file
------------------------------------------------------
Stackoverflow to the rescue: https://stackoverflow.com/questions/4636970
sqlite3.InterfaceError: Error binding parameter 0
-------------------------------------------------
This error occurs when you pass a chat id value of the wrong type when trying to call a method. Most likely, you
accidentally passed the whole user or chat object instead of the id or username.
.. code-block:: python
# Wrong. You passed the whole Chat instance
app.send_message(chat, "text")
# Correct
app.send_message(chat.id, "text")
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``.
How can avoid Flood Waits?
--------------------------
Long story short: make less requests, and remember that the API is designed to be used by official apps, by real people;
anything above normal usage could be limited.
This question is being asked quite a lot of times, but the bottom line is that nobody knows the exact limits and it's
unlikely that such information will be ever disclosed, because otherwise people could easily circumvent them and defeat
their whole purpose.
Do also note that Telegram wants to be a safe and reliable place and that limits exist to protect itself from abuses.
Having said that, here's some insights about limits:
- They are tuned by Telegram based on real people usage and can change anytime.
- Some limits are be applied to single sessions, some others apply to the whole account.
- Limits vary based on methods and the arguments passed to methods. For example: log-ins are expensive and thus have
stricter limits; replying to a user command could cause a flood wait in case the user starts flooding, but
such limit will only be applied to that particular chat (i.e.: other users are not affected).
- You can catch Flood Wait exceptions in your code and wait the required seconds before continuing, this way:
.. code-block:: python
import time
from pyrogram.errors import FloodWait
try:
... # Your code
except FloodWait as e:
time.sleep(e.x) # Wait "x" seconds before continuing
More info about error handling can be found `here <start/errors>`_.
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 thanks to `@koteeq <https://t.me/koteeq>`_, 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>
<br><br>
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

View File

@ -1,11 +0,0 @@
Client started, but nothing happens
===================================
A possible cause might be network issues, either yours or Telegram's. To check this, add the following code at
the top of your script and run it again. You should see some error mentioning a socket timeout or an unreachable
network:
.. code-block:: python
import logging
logging.basicConfig(level=logging.INFO)

View File

@ -1,12 +0,0 @@
Code hangs when calling stop, restart, add/remove_handler
=========================================================
You tried to ``.stop()``, ``.restart()``, ``.add_handler()`` or ``.remove_handler()`` inside a running handler, but
that can't be done because the way Pyrogram deals with handlers would make it hang.
When calling one of the methods above inside an event handler, Pyrogram needs to wait for all running handlers to finish
in order to continue. Since your handler is blocking the execution by waiting for the called method to finish
and since Pyrogram needs to wait for your handler to finish, you are left with a deadlock.
The solution to this problem is to pass ``block=False`` to such methods so that they return immediately and the actual
code called asynchronously.

View File

@ -1,23 +0,0 @@
How to avoid Flood Waits?
=========================
Slow things down and make less requests. Moreover, exact limits are unknown and can change anytime based on normal
usages.
When a flood wait happens the server will tell you how much time to wait before continuing.
The following shows how to catch the exception in your code and wait the required seconds.
.. code-block:: python
import time
from pyrogram.errors import FloodWait
...
try:
... # Your code
except FloodWait as e:
await asyncio.sleep(e.x) # Wait "x" seconds before continuing
...
More info about error handling can be found :doc:`here <../start/errors>`.

View File

@ -1,9 +0,0 @@
How to use webhooks?
====================
There is no webhook in Pyrogram, simply because there is no HTTP involved. However, a similar technique is
being used to make receiving updates efficient.
Pyrogram uses persistent connections via TCP sockets to interact with the server and instead of actively asking for
updates every time (polling), Pyrogram will sit down and wait for the server to send updates by itself the very moment
they are available (server push).

View File

@ -1,47 +0,0 @@
Frequently Asked Questions
==========================
This FAQ page provides answers to common questions about Pyrogram and, to some extent, Telegram in general.
**Contents**
- :doc:`why-is-the-api-key-needed-for-bots`
- :doc:`how-to-use-webhooks`
- :doc:`using-the-same-file-id-across-different-accounts`
- :doc:`using-multiple-clients-at-once-on-the-same-account`
- :doc:`client-started-but-nothing-happens`
- :doc:`what-are-the-ip-addresses-of-telegram-data-centers`
- :doc:`migrating-the-account-to-another-data-center`
- :doc:`why-is-the-client-reacting-slowly-in-supergroups-channels`
- :doc:`peer-id-invalid-error`
- :doc:`code-hangs-when-calling-stop-restart-add-remove-handler`
- :doc:`unicodeencodeerror-codec-cant-encode`
- :doc:`uploading-with-urls-gives-error-webpage-curl-failed`
- :doc:`why-is-the-event-handler-triggered-twice-or-more`
- :doc:`sqlite3-operationalerror-database-is-locked`
- :doc:`sqlite3-interfaceerror-error-binding-parameter`
- :doc:`socket-send-raised-exception-oserror-timeouterror`
- :doc:`how-to-avoid-flood-waits`
- :doc:`the-account-has-been-limited-deactivated`
.. toctree::
:hidden:
why-is-the-api-key-needed-for-bots
how-to-use-webhooks
using-the-same-file-id-across-different-accounts
using-multiple-clients-at-once-on-the-same-account
client-started-but-nothing-happens
what-are-the-ip-addresses-of-telegram-data-centers
migrating-the-account-to-another-data-center
why-is-the-client-reacting-slowly-in-supergroups-channels
peer-id-invalid-error
code-hangs-when-calling-stop-restart-add-remove-handler
unicodeencodeerror-codec-cant-encode
uploading-with-urls-gives-error-webpage-curl-failed
why-is-the-event-handler-triggered-twice-or-more
sqlite3-operationalerror-database-is-locked
sqlite3-interfaceerror-error-binding-parameter
socket-send-raised-exception-oserror-timeouterror
how-to-avoid-flood-waits
the-account-has-been-limited-deactivated

View File

@ -1,10 +0,0 @@
Migrating the account to another data center
============================================
This question is asked by people who find their account always being connected to one DC (data center), but are
connecting from a place far away, thus resulting in slower interactions when using the API because of the greater
physical distance between the user and the 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. It's also up to the server to decide whether to automatically migrate a user in case of prolonged usages
from a distant location.

View File

@ -1,14 +0,0 @@
PEER_ID_INVALID error
=====================
This error could mean several things:
- The chat id you tried to use is simply wrong, check it again.
- The chat id refers to a group or channel you are not a member of.
- The chat id argument you passed is in form of a string; you have to convert it into an integer with ``int(chat_id)``.
- The chat id refers to a user or chat your current session hasn't met yet.
About the last point: in order for you to meet a user and thus communicate with them, you should ask yourself how to
contact people using official apps. The answer is the same for Pyrogram too and involves normal usages such as searching
for usernames, meeting them in a common group, having their phone contacts saved, getting a message mentioning them
or obtaining the dialogs list.

View File

@ -1,10 +0,0 @@
socket.send() raised exception, OSError(), TimeoutError()
=========================================================
If you get this error chances are you are blocking the event loop for too long.
In general, it means you are executing thread-blocking code that prevents the event loop from
running properly. For example:
- You are using ``time.sleep()`` instead of ``asyncio.sleep()``.
- You are running processing loops that take too much time to complete.
- You are reading/writing files to disk that take too much time to complete.

View File

@ -1,13 +0,0 @@
sqlite3.InterfaceError: Error binding parameter
===============================================
This error occurs when you pass a chat id value of the wrong type when trying to call a method. Most likely, you
accidentally passed the whole user or chat object instead of the id or username.
.. code-block:: python
# Wrong. You passed the whole Chat instance
app.send_message(chat, "text")
# Correct
app.send_message(chat.id, "text")

View File

@ -1,17 +0,0 @@
sqlite3.OperationalError: database is locked
============================================
This error occurs when more than one process is using the same session file, that is, when you run two or more clients
at the same time using the same session name or in case another program has accessed the file.
For example, it could occur when a background script is still running and you forgot about it. In this case, you either
restart your system or find and kill the process that is locking the database. On Unix based systems, you can try the
following:
#. ``cd`` into your session file directory.
#. ``fuser my_account.session`` to find the process id.
#. ``kill 1234`` to gracefully stop the process.
#. If the last command doesn't help, use ``kill -9 1234`` instead.
If you want to run multiple clients on the same account, you must authorize your account (either user or bot)
from the beginning every time, and use different session names for each parallel client you are going to use.

View File

@ -1,16 +0,0 @@
The account has been limited/deactivated
========================================
Pyrogram is a framework that interfaces with Telegram; it is at your commands, meaning it only does what you tell it to
do, the rest is up to you and Telegram (see `Telegram's ToS`_).
If you found your account being limited/deactivated, it could be due spam/flood/abuse of the API or the usage of certain
virtual/VoIP numbers.
If you think your account was limited/deactivated by mistake, you can write to recover@telegram.org, contact
`@SpamBot`_ or use `this form`_.
.. _@SpamBot: https://t.me/spambot
.. _this form: https://telegram.org/support
.. _Telegram's ToS: https://telegram.org/tos

View File

@ -1,7 +0,0 @@
UnicodeEncodeError: '...' 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
another terminal altogether.

View File

@ -1,7 +0,0 @@
Uploading with URLs gives error WEBPAGE_CURL_FAILED
===================================================
When uploading media files using an URL, the server automatically tries to download the media and uploads it to the
Telegram cloud. This error usually happens in case the provided URL is not publicly accessible by Telegram itself or the
media file is too large. In such cases, your only option is to download the media yourself and upload it from your
local machine.

View File

@ -1,7 +0,0 @@
Using multiple clients at once on the same account
==================================================
Both user and bot accounts are able to run multiple sessions in parallel. However, you must not use the same session
in more than one client at the same time. The correct way to run multiple clients on the same account is by authorizing
your account (either user or bot) from the beginning each time, and use one separate session for each parallel client.

View File

@ -1,6 +0,0 @@
Using the same file_id across different accounts
================================================
Telegram file_id strings are bound to the account which generated them. 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.

View File

@ -1,30 +0,0 @@
What are the IP addresses of Telegram Data Centers?
===================================================
Telegram is currently composed by a decentralized, multi-DC infrastructure (currently 5 DCs, each of which can
work independently) spread across different locations worldwide. However, some of the less busy DCs have been lately
dismissed and their IP addresses are now kept as aliases to the nearest one.
.. csv-table:: Production Environment
:header: ID, Location, IPv4, IPv6
:widths: auto
:align: center
DC1, "MIA, Miami FL, USA", ``149.154.175.53``, ``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.130``, ``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``
.. centered:: More info about the Test Environment can be found :doc:`here <../topics/test-servers>`.
***** Alias DC

View File

@ -1,12 +0,0 @@
Why is the API key needed for bots?
===================================
Requests against the official bot API endpoints are made via JSON/HTTP and are handled by an intermediate server
application that implements the MTProto protocol and uses its own API key to communicate with the MTProto servers.
.. figure:: //_static/img/mtproto-vs-bot-api.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.

View File

@ -1,18 +0,0 @@
Why is the client reacting slowly in supergroups/channels?
==========================================================
Because of how Telegram works internally, every message you receive and send must pass through the creator's DC, and in
the worst case where you, the creator and another member all belong to three different DCs, the other member messages
have to go through from their DC to the creator's DC and finally to your DC. This is applied to each message and member
of a supergroup/channel and the process will inevitably take its time.
Another reason that makes responses come slowly is that messages are dispatched by priority. Depending on the kind
of member, some users receive messages faster than others and for big and busy supergroups the delay might become
noticeable, especially if you are among the lower end of the priority list:
1. Creator.
2. Administrators.
3. Bots.
4. Mentioned users.
5. Recent online users.
6. Everyone else.

View File

@ -1,28 +0,0 @@
Why is the event handler called twice or more?
==============================================
The event handler is being called twice or more because one or more message edit events have arrived.
By default, Pyrogram listens to both new and edit message events inside ``on_message`` handlers. To prevent edit events
from calling the handler, use the "not edited" filter ``~filters.edited``.
For example:
.. code-block:: python
...
@app.on_message(... & ~filters.edited)
async def handler(client, message):
...
Or, avoid handling any edited message altogether this way:
.. code-block:: python
...
@app.on_message(filters.edited)
async def edited(client, message):
pass
... # other handlers

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

@ -0,0 +1,86 @@
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`_.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
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.
Not to be confused with *bot*, that is, a normal Telegram bot created by `@BotFather <https://t.me/botfather>`_.
Session
Also known as *login session*, is a strictly personal piece of data 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

@ -5,8 +5,7 @@ Welcome to Pyrogram
<div align="center">
<a href="/">
<div class="pyrogram-logo-index"><img src="_static/pyrogram.png" alt="Pyrogram"></div>
<div class="pyrogram-text pyrogram-text-index">Pyrogram</div>
<div><img src="_static/pyrogram.png" alt="Pyrogram Logo" width="420"></div>
</a>
</div>
@ -15,15 +14,15 @@ Welcome to Pyrogram
<br>
<a href="https://github.com/pyrogram/pyrogram">
Development
Source Code
</a>
<a href="https://docs.pyrogram.org/releases">
<a href="https://github.com/pyrogram/pyrogram/releases">
Releases
</a>
<a href="https://t.me/pyrogram">
News
<a href="https://t.me/Pyrogram">
Community
</a>
</p>
@ -36,34 +35,16 @@ Welcome to Pyrogram
@app.on_message(filters.private)
async def hello(client, message):
await message.reply("Hello from Pyrogram!")
await message.reply_text(f"Hello {message.from_user.mention}")
app.run()
**Pyrogram** is a modern, elegant and asynchronous :doc:`MTProto API <topics/mtproto-vs-botapi>` framework.
It enables you to easily interact with the main Telegram API through a user account (custom client) or a bot identity
(bot API alternative) using Python.
**Pyrogram** is a modern, elegant and easy-to-use Telegram_ 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>`.
Support
-------
If you'd like to support Pyrogram, you can consider:
- `Become a GitHub sponsor <https://github.com/sponsors/delivrance>`_.
- `Become a LiberaPay patron <https://liberapay.com/delivrance>`_.
- `Become an OpenCollective backer <https://opencollective.com/pyrogram>`_.
Key Features
------------
- **Ready**: Install Pyrogram with pip and start building your applications right away.
- **Easy**: Makes the Telegram API simple and intuitive, while still allowing advanced usages.
- **Elegant**: Low-level details are abstracted and re-presented in a more convenient way.
- **Fast**: Boosted up by :doc:`TgCrypto <topics/tgcrypto>`, a high-performance crypto library written in pure C.
- **Type-hinted**: Types and methods are all type-hinted, enabling excellent editor support.
- **Async**: Fully asynchronous (also usable synchronously if wanted, for convenience).
- **Powerful**: Full access to Telegram's API to execute any official client action and more.
.. _Telegram: https://telegram.org
How the Documentation is Organized
----------------------------------
@ -72,11 +53,18 @@ Contents are organized into sections composed of self-contained topics which can
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.
.. admonition :: Cloud Credits
:class: tip
If you need a cloud server to host your applications, we recommend using **Hetzner Cloud**. Sign up with
`this link <https://hetzner.cloud/?ref=9CyT92gZEINU>`_ to get €20 in cloud credits and help support Pyrogram as
well.
First Steps
^^^^^^^^^^^
.. hlist::
:columns: 1
:columns: 2
- :doc:`Quick Start <intro/quickstart>`: Overview to get you started quickly.
- :doc:`Calling Methods <start/invoking>`: How to call Pyrogram's methods.
@ -87,7 +75,7 @@ API Reference
^^^^^^^^^^^^^
.. hlist::
:columns: 1
:columns: 2
- :doc:`Pyrogram Client <api/client>`: Reference details about the Client class.
- :doc:`Available Methods <api/methods/index>`: List of available high-level methods.
@ -98,12 +86,16 @@ Meta
^^^^
.. hlist::
:columns: 1
:columns: 2
- :doc:`Pyrogram FAQ <faq/index>`: Answers to common Pyrogram questions.
- :doc:`Pyrogram FAQ <faq>`: Answers to common Pyrogram questions.
- :doc:`Pyrogram Glossary <glossary>`: List of words with brief explanations.
- :doc:`Support Pyrogram <support>`: 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.
Last updated on |today|
.. toctree::
:hidden:
:caption: Introduction
@ -144,13 +136,14 @@ Meta
topics/more-on-updates
topics/config-file
topics/smart-plugins
topics/client-settings
topics/session-settings
topics/tgcrypto
topics/storage-engines
topics/text-formatting
topics/serializing
topics/proxy
topics/scheduling
topics/bots-interaction
topics/mtproto-vs-botapi
topics/debugging
topics/test-servers
@ -161,8 +154,10 @@ Meta
:hidden:
:caption: Meta
faq/index
faq
glossary
support
license
releases/index
.. toctree::

View File

@ -1,9 +1,16 @@
Install Guide
=============
Being a modern Python framework, Pyrogram requires an up to date version of Python to be installed in your system.
Being a modern Python library, **Pyrogram** requires Python 3.6+ to be installed in your system.
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/.
.. important::
Pyrogram supports **Python 3** only, starting from version 3.6. **PyPy** is supported too.
.. contents:: Contents
:backlinks: none
:depth: 1
@ -29,7 +36,12 @@ Install Pyrogram
Bleeding Edge
-------------
You can install the development version from the git ``master`` branch using this command:
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'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 ``master`` branch using this command (note "master.zip" in
the link):
.. code-block:: text
@ -45,6 +57,6 @@ If no error shows up you are good to go.
>>> import pyrogram
>>> pyrogram.__version__
'x.y.z'
'|version|'
.. _`Github repo`: http://github.com/pyrogram/pyrogram

View File

@ -1,54 +1,49 @@
Quick Start
===========
The next few steps serve as a quick start to see Pyrogram in action as fast as possible.
The next few steps serve as a quick start for all new :term:`Pyrogrammers <Pyrogrammer>` that want to see Pyrogram in
action as fast as possible. Let's go!
Get Pyrogram Real Fast
----------------------
.. admonition :: Cloud Credits
:class: tip
If you need a cloud server to host your applications, try Hetzner Cloud. You can sign up with
`this link <https://hetzner.cloud/?ref=9CyT92gZEINU>`_ to get €20 in cloud credits.
1. Install Pyrogram with ``pip3 install -U pyrogram``.
2. Get your own Telegram API key from https://my.telegram.org/apps.
3. Open the text editor of your choice and paste the following:
3. Open your best text editor and paste the following:
.. code-block:: python
import asyncio
from pyrogram import Client
api_id = 12345
api_hash = "0123456789abcdef0123456789abcdef"
async def main():
async with Client("my_account", api_id, api_hash) as app:
await app.send_message("me", "Greetings from **Pyrogram**!")
asyncio.run(main())
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 ``hello.py``.
5. Save the file as ``pyro.py``.
6. Run the script with ``python3 hello.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. In the next few pages of the introduction, we'll take a much more in-depth look of what
we have just done above.
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.
If you are feeling eager to continue you can take a shortcut to :doc:`Calling Methods <../start/invoking>` and come back
later to learn some more details.
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: https://t.me/Pyrogram

View File

@ -2,7 +2,7 @@ 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 framework.
project with the library. Let's see how it's done.
.. contents:: Contents
:backlinks: none
@ -17,13 +17,18 @@ 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 with your details and register a new Telegram application.
#. Done. The API key consists of two parts: **api_id** and **api_hash**. Keep it secret.
#. 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 defines a token for a Telegram *application* you are going to build.
This means that you are able to authorize multiple users or bots with a single API key.
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
-------------
@ -31,9 +36,9 @@ 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: create a new ``config.ini`` file next to your main script, copy-paste the following and
replace the *api_id* and *api_hash* values with your own. This method allows you to keep your credentials out of
your code without having to deal with how to load them.
- First option (recommended): create a new ``config.ini`` file next to your main script, 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
@ -42,7 +47,8 @@ There are two ways to do so, and you can choose what fits better for you:
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:
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

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

@ -0,0 +1,16 @@
About the License
=================
.. image:: https://www.gnu.org/graphics/lgplv3-with-text-154x68.png
:align: left
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 code (either open source, under the same or a different
license, or even proprietary) for any purpose whatsoever without being required to release the source code of your
applications. Derivative works, including modifications to the library itself can only be redistributed 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

@ -26,20 +26,23 @@ the :meth:`~pyrogram.Client.run` method:
app = Client("my_account")
app.run()
This starts an interactive shell asking you to input your **phone number**, including your `Country Code`_ (the plus
``+`` and minus ``-`` symbols can be omitted) and the **phone code** you will receive in your devices that are already
authorized or via SMS:
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: +1-123-456-7890
Is "+1-123-456-7890" correct? (y/n): y
Enter phone code: 12345
Logged in successfully
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 is personal and 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.
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`` file is personal and must be kept secret.
.. note::

View File

@ -1,8 +1,8 @@
Error Handling
==============
Errors can be correctly handled with ``try...except`` blocks in order to control the behaviour of your application.
Pyrogram errors all live inside the ``errors`` package:
Errors are inevitable when working with the API, and they can 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
@ -25,10 +25,10 @@ This error is raised every time a method call against Telegram's API was unsucce
from pyrogram.errors import RPCError
.. note::
.. warning::
Avoid catching this error everywhere, 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.
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
----------------
@ -84,6 +84,9 @@ whole category of errors and be sure to also handle these unknown errors.
In case a whole class of errors is unknown (that is, an error code that is unknown), Pyrogram will raise a special
``520 UnknownError`` exception.
In both cases, Pyrogram will log them in the ``unknown_errors.txt`` file. Users are invited to report
these unknown errors in the `discussion group <https://t.me/pyrogram>`_.
Errors with Values
------------------

View File

@ -19,7 +19,7 @@ like send_audio(), send_document(), send_location(), etc...
with app:
app.send_message(
"me", # Edit this
"haskell", # Edit this
"This is a ReplyKeyboardMarkup example",
reply_markup=ReplyKeyboardMarkup(
[
@ -33,7 +33,7 @@ like send_audio(), send_document(), send_location(), etc...
)
app.send_message(
"me", # Edit this
"haskell", # Edit this
"This is a InlineKeyboardMarkup example",
reply_markup=InlineKeyboardMarkup(
[

View File

@ -15,7 +15,7 @@ It uses the ``@on_message`` decorator to register a ``MessageHandler`` and appli
@app.on_message(filters.text & filters.private)
def echo(client, message):
message.reply(message.text)
message.reply_text(message.text)
app.run() # Automatically start() and idle()

View File

@ -13,3 +13,9 @@ This example demonstrates a basic API usage
with app:
# Send a message, Markdown is enabled by default
app.send_message("me", "Hi there! I'm using **Pyrogram**")
# Send a location
app.send_location("me", 51.500729, -0.124583)
# Send a sticker
app.send_sticker("me", "CAADBAADzg4AAvLQYAEz_x2EOgdRwBYE")

View File

@ -26,6 +26,7 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
),
url="https://docs.pyrogram.org/intro/install",
description="How to install Pyrogram",
thumb_url="https://i.imgur.com/JyxrStE.png",
reply_markup=InlineKeyboardMarkup(
[
[InlineKeyboardButton(
@ -42,6 +43,7 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
),
url="https://docs.pyrogram.org/start/invoking",
description="How to use Pyrogram",
thumb_url="https://i.imgur.com/JyxrStE.png",
reply_markup=InlineKeyboardMarkup(
[
[InlineKeyboardButton(

View File

@ -11,8 +11,8 @@ This example shows how to query an inline bot (as user).
app = Client("my_account")
with app:
# Get bot results for "hello" from the inline bot @vid
bot_results = app.get_inline_bot_results("vid", "hello")
# 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

@ -8,7 +8,7 @@ to make it only work for specific messages in a specific chat.
from pyrogram import Client, emoji, filters
TARGET = -100123456789 # Target chat. Can also be a list of multiple chat ids/usernames
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.org/)'s group chat {}!" # Welcome message

View File

@ -2,7 +2,7 @@ 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 framework.
account; we are now aiming towards the core of the library. It's time to start playing with the API!
.. contents:: Contents
:backlinks: none
@ -16,6 +16,67 @@ Basic Usage
Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
with app:
app.send_message("me", "Hi!")
Basic step-by-step
^^^^^^^^^^^^^^^^^^
#. Let's begin by importing the Client class:
.. 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")
#. The ``with`` context manager is a shortcut for starting, executing and stopping the Client:
.. code-block:: python
with app:
#. Now, you can call any method you like:
.. code-block:: python
app.send_message("me", "Hi!")
Context Manager
---------------
The ``with`` statement starts a context manager used as a shortcut to automatically call :meth:`~pyrogram.Client.start`
and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work properly. The context manager does
also gracefully stop the client, even in case of unhandled exceptions in your code.
This is how Pyrogram looks without the context manager:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
app.start()
app.send_message("me", "Hi!")
app.stop()
Asynchronous Calls
------------------
In case you want Pyrogram to run asynchronously (e.g.: if you are using third party libraries that require you to call
them with ``await``), use the asynchronous context manager:
.. code-block:: python
from pyrogram import Client
@ -28,24 +89,20 @@ Making API method calls with Pyrogram is very simple. Here's a basic example we
app.run(main())
Step-by-step
^^^^^^^^^^^^
Asynchronous step-by-step
^^^^^^^^^^^^^^^^^^^^^^^^^
#. Let's begin by importing the Client class.
#. Import the Client class and create an instance:
.. 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")
#. Async methods can't be executed at the top level, because they must be inside an async context.
Here we define an async function and put our code inside. Also notice the ``await`` keyword in front of the method
call; this is required for all asynchronous methods.
#. Async methods can't normally be executed at the top level, because they must be inside an async-defined function;
here we define one and put our code inside; the context manager is also being used differently in asyncio and
method calls require the await keyword:
.. code-block:: python
@ -53,72 +110,10 @@ Step-by-step
async with app:
await app.send_message("me", "Hi!")
#. Finally, we tell Python to schedule our ``main()`` async function by using Pyrogram's :meth:`~pyrogram.Client.run`
method.
#. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's methods.
Using :meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose
``asyncio.get_event_loop().run_until_complete(main())``:
.. code-block:: python
app.run(main())
Context Manager
---------------
The ``async with`` statement starts a context manager, which is used as a shortcut for starting, executing and stopping
the Client, asynchronously. It does so by automatically calling :meth:`~pyrogram.Client.start` and
:meth:`~pyrogram.Client.stop` in a more convenient way which also gracefully stops the client, even in case of
unhandled exceptions in your code.
Below there's the same example as above, but without the use of the context manager:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
async def main():
await app.start()
await app.send_message("me", "Hi!")
await app.stop()
app.run(main())
Using asyncio.run()
-------------------
Alternatively to the :meth:`~pyrogram.Client.run` method, you can use Python's ``asyncio.run()`` to execute the main
function, with one little caveat: the Client instance (and possibly other asyncio resources you are going to use) must
be instantiated inside the main function.
.. code-block:: python
import asyncio
from pyrogram import Client
async def main():
app = Client("my_account")
async with app:
await app.send_message("me", "Hi!")
asyncio.run(main())
Synchronous Calls
------------------
Pyrogram is an asynchronous framework, but it also provides a convenience way for calling methods without the need
of async/await keywords and the extra boilerplate. In case you want Pyrogram to run synchronously, simply use the
synchronous context manager:
.. code-block:: python
from pyrogram import Client
app = Client("my_account")
with app:
app.send_message("me", "Hi!")
As you can see, the non-async example becomes less cluttered. Use Pyrogram in this non-asynchronous way only when you
want to write something without the boilerplate or in case you want to combine Pyrogram with other libraries that are
not async.

View File

@ -1,8 +1,8 @@
Handling Updates
================
Calling :doc:`API methods <invoking>` sequentially is one way to use Pyrogram, but how to react when, for example, a
new message arrives? This page deals with updates and how to handle such events in Pyrogram.
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.
.. contents:: Contents
:backlinks: none
@ -14,9 +14,10 @@ new message arrives? This page deals with updates and how to handle such events
Defining 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>`.
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.
@ -39,51 +40,50 @@ The most elegant way to register a message handler is by using the :meth:`~pyrog
app = Client("my_account")
@app.on_message()
async def my_handler(client, message):
await message.forward("me")
def my_handler(client, message):
message.forward("me")
app.run()
The defined function ``my_handler``, which accepts the two arguments *(client, message)*, will be the function that gets
executed every time a new message arrives.
In the last line we see again the :meth:`~pyrogram.Client.run` method, this time used without any argument.
Its purpose here is simply to automatically :meth:`~pyrogram.Client.start`, keep the Client online so that it can listen
for updates and :meth:`~pyrogram.Client.stop` it once you hit ``CTRL+C``.
Synchronous handlers
Asynchronous handlers
^^^^^^^^^^^^^^^^^^^^^
You can also have synchronous handlers; you only need to define the callback function without using ``async def`` and
call API methods by not placing ``await`` in front of them:
You can also have asynchronous handlers; you only need to define the callback function using ``async def`` and call API
methods by placing ``await`` in front of them:
.. code-block:: python
@app.on_message()
def my_handler(client, message):
message.forward("me")
async def my_handler(client, message):
await message.forward("me")
.. note::
You can mix ``def`` and ``async def`` handlers as much as you like, Pyrogram will still work concurrently and
efficiently regardless of what you choose. However, it is recommended to use Pyrogram in its native, asynchronous
form at all times, unless you want to write something without the boilerplate or in case you want to combine
Pyrogram with other libraries that are not async.
You can mix ``def`` and ``async def`` handlers as much as you need, Pyrogram will still work concurrently and
efficiently regardless of what you choose.
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. It is useful in case you want to programmatically add handlers.
function and registers it in your Client. It is useful in case you want to programmatically add handlers (or in case,
for some reason, you don't like to use decorators).
.. code-block:: python
from pyrogram import Client
from pyrogram.handlers import MessageHandler
async def my_function(client, message):
await message.forward("me")
def my_function(client, message):
message.forward("me")
app = Client("my_account")
@ -92,12 +92,12 @@ function and registers it in your Client. It is useful in case you want to progr
app.run()
The same about synchronous handlers applies for :meth:`~pyrogram.Client.add_handler`:
The same about asynchronous handlers applies for :meth:`~pyrogram.Client.add_handler`:
.. code-block:: python
def my_function(client, message):
message.forward("me")
async def my_function(client, message):
await message.forward("me")
.. note::

View File

@ -1,62 +1,66 @@
Support Pyrogram
================
.. raw:: html
As a developer, you probably understand that "open source" doesn't mean "free work". If you wish to tip me for Pyrogram
-- or any of my `other works`_ -- you can do so by the ways shown below. Your appreciation means a lot and helps
staying motivated!
<script async defer src="https://buttons.github.io/buttons.js"></script>
<div style="float: right; margin-bottom: 10px">
<a class="github-button"
href="https://github.com/pyrogram/pyrogram/fork"
data-icon="octicon-repo-forked" data-size="large" data-show-count="true"
aria-label="Fork pyrogram/pyrogram on GitHub">Fork</a>
<a class="github-button"
href="https://github.com/pyrogram/pyrogram"
data-icon="octicon-star" data-size="large"
data-show-count="true" aria-label="Star pyrogram/pyrogram on GitHub">Star</a>
</div>
<br style="clear: both"/>
Pyrogram is a free and open source project.
If you enjoy Pyrogram and would like to show your appreciation, consider donating or becoming
a sponsor of the project. You can support Pyrogram via the ways shown below:
--- `Dan`_
-----
GitHub Sponsor
--------------
Star
----
`Become a GitHub sponsor <https://github.com/sponsors/delivrance>`_.
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`_.
.. raw:: html
<a class="github-button"
href="https://github.com/sponsors/delivrance"
data-icon="octicon-heart"
data-size="large"
aria-label="Sponsor @delivrance on GitHub">
Sponsor</a>
<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>
-----
LiberaPay Patron
----------------
Sponsor
-------
`Become a LiberaPay patron <https://liberapay.com/delivrance>`_.
You can become a GitHub sponsor:
.. raw:: html
<script src="https://liberapay.com/delivrance/widgets/button.js"></script>
<iframe
src="https://github.com/sponsors/delivrance/button"
title="Sponsor delivrance"
height="40" width="120"
style="border: 0px; padding-top: 5px; margin-top: -5px">
</iframe>
-----
OpenCollective Backer
---------------------
Donate
------
`Become an OpenCollective backer <https://opencollective.com/pyrogram>`_
You can donate via PayPal using the button below:
.. raw:: html
<script src="https://opencollective.com/pyrogram/banner.js"></script>
<form action="https://www.paypal.com/donate" method="post" target="_top">
<input type="hidden" name="hosted_button_id" value="WMKAVFE47XEML" />
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" title="PayPal - The safer, easier way to pay online!" alt="Donate with PayPal button" />
<img alt="" border="0" src="https://www.paypal.com/en_IT/i/scr/pixel.gif" width="1" height="1" />
</form>
-----
Cloud Credits
-------------
If you need a cloud server to host your applications, try **Hetzner Cloud**. You can sign up with
`this link <https://hetzner.cloud/?ref=9CyT92gZEINU>`_ to get €20 in cloud credits and help support Pyrogram and
my `other projects`_.
.. _Star on GitHub: https://github.com/pyrogram/pyrogram
.. _other projects: https://github.com/delivrance
.. _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 :doc:`methods <../api/methods/index>` and
:doc:`types <../api/types/index>` -- exists to provide an easier interface to the more complex Telegram API.
Pyrogram's API, which consists of well documented convenience :doc:`methods <../api/methods/index>` and facade
:doc:`types <../api/types/index>`, 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.
@ -20,18 +21,25 @@ 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:`~pyrogram.raw.functions` and :mod:`~pyrogram.raw.types`.
As already hinted, raw functions and types can be less convenient. This section will therefore explain some pitfalls to
take into consideration when working with the raw API.
As already hinted, raw functions and types can be really confusing, mainly because people don't realize soon enough they
accept *only* the right types and that all required parameters must be filled in. This section will therefore explain
some pitfalls to take into consideration when working with the raw API.
.. tip::
.. hint::
Every available high-level method in Pyrogram is built on top of these raw functions.
Every available high-level methods in Pyrogram is built on top of these raw functions.
Nothing stops you from using the raw functions only, but they are rather complex and
:doc:`plenty of them <../api/methods/index>` 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 :doc:`methods <../api/methods/index>` 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.
functions to be invoked from the raw Telegram API have a different way of usage and are more complex.
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.raw.functions``, ``pyrogram.raw.types``. They all exist
@ -53,12 +61,12 @@ Here's some examples:
with Client("my_account") as app:
app.send(
functions.account.UpdateProfile(
first_name="First Name", last_name="Last Name",
about="New bio text"
first_name="Dan", last_name="Tès",
about="Bio written from Pyrogram"
)
)
- Set online/offline status:
- Disable links to your account when someone forwards your messages:
.. code-block:: python
@ -66,13 +74,14 @@ Here's some examples:
from pyrogram.raw import functions, types
with Client("my_account") as app:
# Set online status
app.send(functions.account.UpdateStatus(offline=False))
app.send(
functions.account.SetPrivacy(
key=types.PrivacyKeyForwards(),
rules=[types.InputPrivacyValueDisallowAll()]
)
)
# Set offline status
app.send(functions.account.UpdateStatus(offline=True))
- Get chat info:
- Invite users to your channel/supergroup:
.. code-block:: python
@ -80,18 +89,21 @@ Here's some examples:
from pyrogram.raw import functions, types
with Client("my_account") as app:
r = app.send(
functions.channels.GetFullChannel(
channel=app.resolve_peer("username")
app.send(
functions.channels.InviteToChannel(
channel=app.resolve_peer(123456789), # ID or Username
users=[ # The users you want to invite
app.resolve_peer(23456789), # By ID
app.resolve_peer("username"), # By username
app.resolve_peer("+393281234567"), # By phone number
]
)
)
print(r)
Chat IDs
--------
^^^^^^^^
The way Telegram works makes it not possible to directly send a message to a user or a chat by using their IDs only.
The way Telegram works makes it impossible to directly send a message to a user or a chat by using their IDs only.
Instead, a pair of ``id`` and ``access_hash`` wrapped in a so called ``InputPeer`` is always needed. Pyrogram allows
sending messages with IDs only thanks to cached access hashes.
@ -100,17 +112,18 @@ Whenever an InputPeer is needed you must pass one of these:
- :class:`~pyrogram.raw.types.InputPeerUser` - Users
- :class:`~pyrogram.raw.types.InputPeerChat` - Basic Chats
- :class:`~pyrogram.raw.types.InputPeerChannel` - Channels & Supergroups
- :class:`~pyrogram.raw.types.InputPeerChannel` - Either Channels or Supergroups
But you don't necessarily have to manually instantiate each object because Pyrogram already provides
But you don't necessarily have to manually instantiate each object because, luckily for you, Pyrogram already provides
: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
all positive within their respective raw types.
Things are different when working with Pyrogram's API because having them in the same space could lead to
collisions, and that's why Pyrogram uses a slightly different representation for each kind of ID.
Things are different when working with Pyrogram's API because having them in the same space can theoretically lead to
collisions, and that's why Pyrogram (as well as the official Bot API) uses a slightly different representation for each
kind of ID.
For example, given the ID *123456789*, here's how Pyrogram can tell entities apart:

View File

@ -0,0 +1,50 @@
Bots Interaction
================
Users can interact with other bots via plain text messages as well as inline queries.
.. contents:: Contents
:backlinks: none
:depth: 1
:local:
-----
Inline Bots
-----------
- If a bot accepts inline queries, you can call it by using
:meth:`~pyrogram.Client.get_inline_bot_results` to get the list of its inline results for a query:
.. code-block:: python
# Get bot results for "Fuzz Universe" from the inline bot @vid
bot_results = app.get_inline_bot_results("vid", "Fuzz Universe")
.. figure:: https://i.imgur.com/IAqLs54.png
:width: 90%
:align: center
:figwidth: 60%
``get_inline_bot_results()`` is the equivalent action of writing ``@vid Fuzz Universe`` and getting the
results list.
- After you retrieved the bot results, you can use
:meth:`~pyrogram.Client.send_inline_bot_result` to send a chosen result to any chat:
.. code-block:: python
# Send the first result to your own chat
app.send_inline_bot_result(
"me",
bot_results.query_id,
bot_results.results[0].id
)
.. figure:: https://i.imgur.com/wwxr7B7.png
:width: 90%
:align: center
:figwidth: 60%
``send_inline_bot_result()`` is the equivalent action of choosing a result from the list and sending it
to a chat.

View File

@ -15,7 +15,7 @@ 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 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.
@ -23,7 +23,7 @@ fill in the necessary parts.
The configuration file is optional, but recommended. If, for any reason, you prefer not to use it, there's always an
alternative way to configure Pyrogram via Client's parameters. Doing so, you can have full control on how to store
and load your settings.
and load your settings (e.g.: from environment variables).
Settings specified via Client's parameter have higher priority and will override any setting stored in the
configuration file.

View File

@ -87,7 +87,7 @@ Finally, the filter usage remains the same:
Filters with Arguments
----------------------
A more flexible filter would be one that accepts "pyrogram" or any other string as argument at usage time.
A much cooler filter would be one that accepts "pyrogram" or any other string as argument at usage time.
A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method and the
first argument of the callback function, which is a reference to the filter object itself holding the extra data passed
via named arguments.

View File

@ -2,7 +2,7 @@ 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 since Pyrogram provides some commodities to help you in this.
to actually worry about -- that's normal -- and luckily for you, Pyrogram provides some commodities to help you in this.
.. contents:: Contents
:backlinks: none
@ -27,8 +27,8 @@ Consider the following code:
.. code-block:: python
me = app.get_users("me")
print(me) # User
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.types.User` instance, in this case. The output on your terminal will be something similar to this:
@ -36,9 +36,9 @@ This will show a JSON representation of the object returned by :meth:`~pyrogram.
.. code-block:: json
{
"_": "User",
"id": 123456789,
"is_self": true,
"_": "pyrogram.User",
"id": 23122162,
"is_self": false,
"is_contact": false,
"is_mutual_contact": false,
"is_deleted": false,
@ -46,13 +46,19 @@ This will show a JSON representation of the object returned by :meth:`~pyrogram.
"is_verified": false,
"is_restricted": false,
"is_support": false,
"first_name": "Pyrogram",
"is_scam": false,
"first_name": "Dan",
"status": {
"_": "pyrogram.UserStatus",
"user_id": 23122162,
"recently": true
},
"username": "haskell",
"language_code": "en",
"photo": {
"_": "ChatPhoto",
"small_file_id": "AbCdE...EdCbA",
"small_photo_unique_id": "VwXyZ...ZyXwV",
"big_file_id": "AbCdE...EdCbA",
"big_photo_unique_id": "VwXyZ...ZyXwV"
"_": "pyrogram.ChatPhoto",
"small_file_id": "AQADBAAD8tBgAQAEJjCxGgAEo5IBAAIC",
"big_file_id": "AQADBAAD8tBgAQAEJjCxGgAEpZIBAAEBAg"
}
}
@ -63,23 +69,37 @@ Accessing Attributes
--------------------
Even though you see a JSON output, it doesn't mean we are dealing with dictionaries; in fact, all Pyrogram types are
fully-fledged Python objects and the correct way to access any attribute of them is by using the dot notation ``.``:
full-fledged Python objects and the correct way to access any attribute of them is by using the dot notation ``.``:
.. code-block:: python
photo = me.photo
print(photo) # ChatPhoto
dan_photo = dan.photo
print(dan_photo) # ChatPhoto
.. code-block:: json
{
"_": "ChatPhoto",
"small_file_id": "AbCdE...EdCbA",
"small_photo_unique_id": "VwXyZ...ZyXwV",
"big_file_id": "AbCdE...EdCbA",
"big_photo_unique_id": "VwXyZ...ZyXwV"
"_": "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
-------------------------
@ -91,8 +111,8 @@ error. The correct way to get the object type is by using the built-in function
.. code-block:: python
status = me.status
print(type(status))
dan_status = dan.status
print(type(dan_status))
.. code-block:: text
@ -105,8 +125,8 @@ And to check if an object is an instance of a given class, you use the built-in
from pyrogram.types import UserStatus
status = me.status
print(isinstance(status, UserStatus))
dan_status = dan.status
print(isinstance(dan_status, UserStatus))
.. code-block:: text

View File

@ -24,6 +24,7 @@ group. Dispatching groups hold one or more handlers and are processed sequential
For example, take these two handlers:
.. code-block:: python
:emphasize-lines: 1, 6
@app.on_message(filters.text | filters.sticker)
def text_or_sticker(client, message):

View File

@ -1,10 +1,10 @@
MTProto vs. Bot API
===================
Pyrogram is a framework written from the ground up that acts as a fully-fledged Telegram client based on the MTProto
API. This means that Pyrogram is able to execute any official client and bot API action and more. 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.
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.
.. contents:: Contents
:backlinks: none
@ -19,11 +19,10 @@ 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 in order to distinguish it
from the Bot API. The main Telegram 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. Clients that make use of Telegram's main API, such as
Pyrogram, implement all these details.
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
@ -32,12 +31,12 @@ Pyrogram, implement all these details.
What is the Bot API?
--------------------
The `Bot API`_ is an HTTP(S) interface for building normal bots using a sub-set of the main Telegram 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.
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:: //_static/img/mtproto-vs-bot-api.png
.. figure:: https://i.imgur.com/WvwBoZo.png
:align: center
.. _Bot API: https://core.telegram.org/bots/api
@ -45,8 +44,8 @@ servers using MTProto.
Advantages of the MTProto API
-----------------------------
Here is a non-exhaustive list of all the advantages in using MTProto-based libraries -- such as Pyrogram -- instead of
the official HTTP Bot API. Using Pyrogram you can:
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
@ -70,7 +69,7 @@ the official HTTP Bot API. Using Pyrogram you can:
.. hlist::
:columns: 1
- :guilabel:`+` **Run multiple sessions at once (for both user and bot identities)**
- :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.

View File

@ -14,8 +14,8 @@ non-asynchronous contexts. For more detailed information, you can visit and lear
-----
Using apscheduler
-----------------
Using ``apscheduler``
---------------------
- Install with ``pip3 install apscheduler``
- Documentation: https://apscheduler.readthedocs.io

View File

@ -24,7 +24,8 @@ If you want a nicely formatted, human readable JSON representation of any object
...
with app:
r = app.get_chat("me")
r = app.get_chat("haskell")
print(str(r))
.. tip::
@ -47,7 +48,7 @@ as the process requires the package to be in scope.
...
with app:
r = app.get_chat("me")
r = app.get_chat("haskell")
print(repr(r))
print(eval(repr(r)) == r) # True

View File

@ -1,12 +1,24 @@
Client Settings
===============
Session Settings
================
You can control the way your client appears in the Active Sessions menu of an official client by changing some client
settings. By default you will see something like the following:
As you may probably know, Telegram allows users (and bots) having more than one session (authorizations) registered
in the system at the same time.
- Device Model: ``CPython x.y.z``
- Application: ``Pyrogram x.y.z``
- System Version: ``Linux x.y.z``
Briefly explaining, sessions are simply new logins in your account. They can be reviewed in the settings of an official
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/YaqtMLO.png
:width: 600
:align: center
**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.13.0**
- ``device_model``: **CPython 3.7.2**
- ``system_version``: **Linux 4.15.0-23-generic**
.. contents:: Contents
:backlinks: none

View File

@ -1,9 +1,9 @@
Smart Plugins
=============
Pyrogram embeds a smart, lightweight yet powerful plugin system that is meant to further simplify the organization
of large projects and to provide a way for creating pluggable (modular) components that can be easily shared across
different Pyrogram applications with minimal boilerplate code.
Pyrogram embeds a **smart**, lightweight yet powerful plugin system that is meant to further simplify the organization
of large projects and to provide a way for creating pluggable (modular) components that can be **easily shared** across
different Pyrogram applications with **minimal boilerplate code**.
.. tip::
@ -74,8 +74,8 @@ after importing your modules, like this:
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:`~pyrogram.Client.add_handler` and manually instantiate each
:class:`~pyrogram.handlers.MessageHandler` object because you can't use decorators for your functions.
So, what if you could? Smart Plugins solve this issue by taking care of handlers registration automatically.
:class:`~pyrogram.handlers.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
-------------------
@ -91,6 +91,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
This is the same example application as shown above, written using the Smart Plugin system.
.. code-block:: text
:emphasize-lines: 2, 3
myproject/
plugins/
@ -101,6 +102,7 @@ Setting up your Pyrogram project to accommodate Smart Plugins is pretty straight
- ``plugins/handlers.py``
.. code-block:: python
:emphasize-lines: 4, 9
from pyrogram import Client, filters
@ -162,7 +164,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, by design. Learn more at :doc:`More on Updates <more-on-updates>`.
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``
@ -298,30 +300,32 @@ In the previous section we've explained how to specify which plugins to load and
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 a special ``handlers`` attribute pointing to a list of tuples of
updates) will be modified in such a way that a special ``handler`` attribute pointing to a tuple of
*(handler: Handler, group: int)* is attached to the function object itself.
- ``plugins/handlers.py``
.. code-block:: python
:emphasize-lines: 5, 6
@Client.on_message(filters.text & filters.private)
def echo(client, message):
message.reply(message.text)
print(echo)
print(echo.handlers)
print(echo.handler)
- Printing ``echo`` will show something like ``<function echo at 0x10e3b6598>``.
- Printing ``echo.handlers`` will reveal the handlers, that is, a list of tuples containing the actual handlers and
the groups they were registered on ``[(<MessageHandler object at 0x10e3abc50>, 0)]``.
- Printing ``echo.handler`` will reveal the handler, that is, a tuple containing the actual handler and the group it
was registered on ``(<MessageHandler object at 0x10e3abc50>, 0)``.
Unloading
^^^^^^^^^
In order to unload a plugin, all you need to do is obtain a reference to it by importing the relevant module and call
:meth:`~pyrogram.Client.remove_handler` Client's method with your function's *handler* instance:
:meth:`~pyrogram.Client.remove_handler` Client's method with your function's *handler* special attribute preceded by the
star ``*`` operator as argument. Example:
- ``main.py``
@ -329,19 +333,16 @@ In order to unload a plugin, all you need to do is obtain a reference to it by i
from plugins.handlers import echo
handlers = echo.handlers
...
for h in handlers:
app.remove_handler(*h)
app.remove_handler(*echo.handler)
The star ``*`` operator is used to unpack the tuple into positional arguments so that *remove_handler* will receive
exactly what is needed. The same could have been achieved with:
.. code-block:: python
handlers = echo.handlers
handler, group = handlers[0]
handler, group = echo.handler
app.remove_handler(handler, group)
Loading
@ -358,7 +359,4 @@ using :meth:`~pyrogram.Client.add_handler` instead. Example:
...
handlers = echo.handlers
for h in handlers:
app.add_handler(*h)
app.add_handler(*echo.handler)

View File

@ -18,18 +18,28 @@ Persisting Sessions
In order to make a client reconnect successfully between restarts, that is, without having to start a new
authorization process from scratch each time, Pyrogram needs to store the generated session data somewhere.
Other useful data being stored is peers' cache. In short, peers are all those entities you can chat with, such as users
or bots, basic groups, but also channels and supergroups. Because of how Telegram works, a unique pair of **id** and
**access_hash** is needed to contact a peer. This, plus other useful info such as the peer type, is what is stored
inside a session storage.
So, if you ever wondered how is Pyrogram able to contact peers just by asking for their ids, it's because of this very
reason: the peer *id* is looked up in the internal database and the available *access_hash* is retrieved, which is then
used to correctly invoke API methods.
Different Storage Engines
-------------------------
Pyrogram offers two different types of storage engines: a **File Storage** and a **Memory Storage**.
These engines are well integrated in the framework and require a minimal effort to set up. Here's how they work:
Let's now talk about how Pyrogram actually stores all the relevant data. Pyrogram offers two different types of storage
engines: a **File Storage** and a **Memory Storage**. These engines are well integrated in the library and require a
minimal effort to set up. Here's how they work:
File Storage
^^^^^^^^^^^^
This is the most common storage engine. It is implemented by using **SQLite**, which will store the session details.
The database will be saved to disk as a single portable file and is designed to efficiently store and retrieve
data whenever they are needed.
This is the most common storage engine. It is implemented by using **SQLite**, which will store the session and peers
details. The database will be saved to disk as a single portable file and is designed to efficiently store and retrieve
peers whenever they are needed.
To use this type of engine, simply pass any name of your choice to the ``session_name`` parameter of the
:obj:`~pyrogram.Client` constructor, as usual:
@ -58,8 +68,8 @@ session name "**:memory:**" to the ``session_name`` parameter of the :obj:`~pyro
with Client(":memory:") as app:
print(app.get_me())
This storage engine is still backed by SQLite, but the database exists purely in memory. This means that, once you stop
a client, the entire database is discarded and the session details used for logging in again will be lost forever.
This storage engine is still backed by SQLite, but the database exists purely in memory. This means that, once you stop a
client, the entire database is discarded and the session details used for logging in again will be lost forever.
Session Strings
---------------
@ -74,8 +84,8 @@ In case you want to use an in-memory storage, but also want to keep access to th
with Client(":memory:") as app:
print(app.export_session_string())
...and save the resulting string. You can use this string as session name the next time you want to login
using the same session; the storage used will still be in-memory:
...and save the resulting (quite long) string somewhere. You can use this string as session name the next time you want
to login using the same session; the storage used will still be completely in-memory:
.. code-block:: python
@ -86,5 +96,11 @@ using the same session; the storage used will still be in-memory:
with Client(session_string) as app:
print(app.get_me())
Session strings are useful when you want to run authorized Pyrogram clients on platforms where their ephemeral
filesystems makes it harder for a file-based storage engine to properly work as intended.
Session strings are useful when you want to run authorized Pyrogram clients on platforms like
`Heroku <https://www.heroku.com/>`_, where their ephemeral filesystems makes it much harder for a file-based storage
engine to properly work as intended.
But, why is the session string so long? Can't it be shorter? No, it can't. The session string already packs the bare
minimum data Pyrogram needs to successfully reconnect to an authorized session, and the 2048-bits auth key is the major
contributor to the overall length. Needless to say that this string, as well as any other session storage, represent
strictly personal data. Keep them safe.

View File

@ -15,7 +15,8 @@ Telegram's test servers without hassle. All you need to do is start a new sessio
.. note::
If this is the first time you login into test servers, you will be asked to register your account first.
Accounts registered on test servers reside in a different, parallel instance of a Telegram server.
Don't worry about your contacts and chats, they will be kept untouched inside the production environment;
accounts authorized on test servers reside in a different, parallel instance of a Telegram database.
.. contents:: Contents
:backlinks: none
@ -27,15 +28,19 @@ Telegram's test servers without hassle. All you need to do is start a new sessio
Test Mode in Official Apps
--------------------------
You can also login yourself into test servers using official desktop apps, such as Telegram Web and Telegram Desktop:
You can also login yourself into test servers using official desktop apps, such as Webogram and TDesktop:
- **Telegram Web**: Login here: https://web.telegram.org/?test=1
- **Telegram Desktop**: Hold ``Alt+Shift`` and right click on "Add account", then choose "Test server".
- **Webogram**: Login here: https://web.telegram.org/?test=1
- **TDesktop**: Hold ``Alt+Shift`` and right click on "Add account", then choose "Test server".
Test Numbers
------------
Beside normal numbers, the test environment allows you to login with reserved test numbers.
Valid phone numbers follow the pattern ``99966XYYYY``, where ``X`` is the DC number (1 to 3) and ``YYYY`` are random
numbers. Users with such numbers always get ``XXXXX`` or ``XXXXXX`` as the confirmation code (the DC number, repeated
five or six times).
numbers. Users with such numbers always get ``XXXXX`` as the confirmation code (the DC number, repeated five times).
.. important::
Do not store any important or private information in such test users' accounts; anyone can make use of the
simplified authorization mechanism and login at any time.

View File

@ -14,7 +14,7 @@ Text Formatting
:class: strike-italic
Pyrogram uses a custom Markdown dialect for text formatting which adds some unique features that make writing styled
texts easier in both Markdown and HTML. You can send sophisticated text messages and media captions using a
texts easier in both Markdown and HTML. You can send sophisticated text messages and media captions using a great
variety of decorations that can also be nested in order to combine multiple styles together.
.. contents:: Contents
@ -34,9 +34,8 @@ list of the basic styles currently supported by Pyrogram.
- *italic*
- :strike:`strike`
- :underline:`underline`
- spoiler
- `text URL <https://pyrogram.org>`_
- `user text mention <tg://user?id=123456789>`_
- `user text mention <https://t.me/haskell>`_
- ``inline fixed-width code``
- .. code-block:: text
@ -64,11 +63,9 @@ To strictly use this mode, pass "markdown" to the *parse_mode* parameter when us
~~strike~~
||spoiler||
[text URL](https://docs.pyrogram.org/)
[text URL](https://pyrogram.org/)
[text user mention](tg://user?id=123456789)
[text user mention](tg://user?id=23122162)
`inline fixed-width code`
@ -83,13 +80,13 @@ To strictly use this mode, pass "markdown" to the *parse_mode* parameter when us
.. code-block:: python
app.send_message(
"me",
"haskell",
(
"**bold**, "
"__italic__, "
"--underline--, "
"~~strike~~, "
"||spoiler||, "
"[mention](tg://user?id=23122162), "
"[URL](https://pyrogram.org), "
"`code`, "
"```"
@ -116,11 +113,9 @@ The following tags are currently supported:
<s>strike</s>, <del>strike</del>, <strike>strike</strike>
<spoiler>spoiler</spoiler>
<a href="http://docs.pyrogram.org/">text URL</a>
<a href="https://pyrogram.org/">text URL</a>
<a href="tg://user?id=123456789">inline mention</a>
<a href="tg://user?id=23122162">inline mention</a>
<code>inline fixed-width code</code>
@ -135,13 +130,13 @@ The following tags are currently supported:
.. code-block:: python
app.send_message(
"me",
"haskell",
(
"<b>bold</b>, "
"<i>italic</i>, "
"<u>underline</u>, "
"<s>strike</s>, "
"<spoiler>spoiler</spoiler>, "
"<a href=\"tg://user?id=23122162\">mention</a>, "
"<a href=\"https://pyrogram.org/\">URL</a>, "
"<code>code</code>\n\n"
"<pre>"
@ -179,7 +174,7 @@ This means you can combine together both syntaxes in the same text:
.. code-block:: python
app.send_message("me", "**bold**, <i>italic</i>")
app.send_message("haskell", "**bold**, <i>italic</i>")
Result:
@ -190,8 +185,8 @@ If you don't like this behaviour you can always choose to only enable either Mar
.. code-block::
app.send_message("me", "**bold**, <i>italic</i>", parse_mode="markdown")
app.send_message("me", "**bold**, <i>italic</i>", parse_mode="html")
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode="markdown")
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode="html")
Result:
@ -204,7 +199,7 @@ as-is.
.. code-block:: python
app.send_message("me", "**bold**, <i>italic</i>", parse_mode=None)
app.send_message("haskell", "**bold**, <i>italic</i>", parse_mode=None)
Result:

View File

@ -1,11 +1,11 @@
Fast Crypto
===========
Pyrogram's speed can be boosted up by TgCrypto_, a high-performance, easy-to-install cryptography library specifically
written in C for Pyrogram as a Python extension.
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 [1]_ as a Python extension.
TgCrypto is a replacement for a slower Python-only alternative and implements the cryptographic algorithms Telegram
requires, namely: AES-256-IGE, AES-256-CTR and AES-256-CBC.
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).
Installation
------------
@ -14,10 +14,10 @@ Installation
$ pip3 install -U tgcrypto
.. note:: When TgCrypto is not detected in your system, Pyrogram will automatically fall back to a slower Python-only
implementation and will show you a warning.
.. note:: Being a C extension for Python, TgCrypto is an optional but *highly recommended* dependency; when TgCrypto is
not detected in your system, Pyrogram will automatically fall back to PyAES and will show you a warning.
The reason about being an optional package is that TgCrypto requires extra system tools in order to be compiled.
The reason about being an optional package is that TgCrypto requires some extra system tools in order to be compiled.
The errors you receive when trying to install TgCrypto are system dependent, but also descriptive enough to understand
what you should do next:
@ -26,4 +26,7 @@ what you should do next:
- **Linux**: Install a proper C compiler (``gcc``, ``clang``) and the Python header files (``python3-dev``).
- **Termux**: Install ``clang`` package.
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
.. _TgCrypto: https://github.com/pyrogram/tgcrypto
.. [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

@ -19,15 +19,16 @@ Single Filters
Let's start right away with a simple example:
- This example will show you how to **only** handle messages containing a :class:`~pyrogram.types.Sticker` object and
- 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.sticker)
@app.on_message(filters.audio)
def my_handler(client, message):
print(message)
@ -35,6 +36,7 @@ Let's start right away with a simple example:
callback function itself:
.. code-block:: python
:emphasize-lines: 9
from pyrogram import filters
from pyrogram.handlers import MessageHandler
@ -44,12 +46,12 @@ Let's start right away with a simple example:
print(message)
app.add_handler(MessageHandler(my_handler, filters.sticker))
app.add_handler(MessageHandler(my_handler, filters.audio))
Combining Filters
-----------------
Filters can be used in a more advanced way by inverting and combining more filters together using bitwise
Filters can also be used in a more advanced way by inverting and combining more filters together using bitwise
operators ``~``, ``&`` and ``|``:
- Use ``~`` to invert a filter (behaves like the ``not`` operator).

View File

@ -1,8 +1,8 @@
Voice Calls
===========
Both private voice calls and group voice calls are currently supported by third-party, external libraries that integrate
with Pyrogram.
Both private voice calls and group voice calls are currently supported by third-party libraries that integrate with
Pyrogram.
Libraries
---------

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -16,9 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
__version__ = "1.4.0"
__version__ = "1.2.9"
__license__ = "GNU Lesser General Public License v3 or later (LGPLv3+)"
__copyright__ = "Copyright (C) 2017-present Dan <https://github.com/delivrance>"
__copyright__ = "Copyright (C) 2017-2021 Dan <https://github.com/delivrance>"
from concurrent.futures.thread import ThreadPoolExecutor
@ -35,14 +35,14 @@ class ContinuePropagation(StopAsyncIteration):
pass
from asyncio import get_event_loop
import asyncio
from . import raw, types, filters, handlers, emoji
from .client import Client
from .sync import idle
# Save the main thread loop for future references
main_event_loop = get_event_loop()
main_event_loop = asyncio.get_event_loop()
CRYPTO_EXECUTOR_SIZE_THRESHOLD = 512

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -32,11 +32,9 @@ from pathlib import Path
from typing import Union, List, Optional
import pyrogram
from pyrogram import __version__, __license__
from pyrogram import raw
from pyrogram import utils
from pyrogram.crypto import aes
from pyrogram.errors import CDNFileHashMismatch
from pyrogram.errors import (
SessionPasswordNeeded,
VolumeLocNotFound, ChannelPrivate,
@ -107,11 +105,6 @@ class Client(Methods, Scaffold):
Only applicable for new sessions and will be ignored in case previously created sessions are loaded.
Defaults to False.
mode (``int``, *optional*):
The connection mode to use.
Defaults to Obfuscated TCPAbridged (3),
The list of modes are available at `connection/connection.py`
bot_token (``str``, *optional*):
Pass your Bot API token to create a bot session, e.g.: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
Only applicable for new sessions.
@ -193,7 +186,6 @@ class Client(Methods, Scaffold):
ipv6: bool = False,
proxy: dict = None,
test_mode: bool = False,
mode: int = 3,
bot_token: str = None,
phone_number: str = None,
phone_code: str = None,
@ -222,7 +214,6 @@ class Client(Methods, Scaffold):
# TODO: Make code consistent, use underscore for private/protected fields
self._proxy = proxy
self.test_mode = test_mode
self.mode = mode
self.bot_token = bot_token
self.phone_number = phone_number
self.phone_code = phone_code
@ -289,10 +280,6 @@ class Client(Methods, Scaffold):
if self.bot_token:
return await self.sign_in_bot(self.bot_token)
print(f"Welcome to Pyrogram (version {__version__})")
print(f"Pyrogram is free software and comes with ABSOLUTELY NO WARRANTY. Licensed\n"
f"under the terms of the {__license__}.\n")
while True:
try:
if not self.phone_number:
@ -440,6 +427,7 @@ class Client(Methods, Scaffold):
Example:
.. code-block:: python
:emphasize-lines: 10,14,18,22
from pyrogram import Client
@ -447,23 +435,23 @@ class Client(Methods, Scaffold):
with app:
# Default combined mode: Markdown + HTML
app.send_message("me", "1. **markdown** and <i>html</i>")
app.send_message("haskell", "1. **markdown** and <i>html</i>")
# Force Markdown-only, HTML is disabled
app.set_parse_mode("markdown")
app.send_message("me", "2. **markdown** and <i>html</i>")
app.send_message("haskell", "2. **markdown** and <i>html</i>")
# Force HTML-only, Markdown is disabled
app.set_parse_mode("html")
app.send_message("me", "3. **markdown** and <i>html</i>")
app.send_message("haskell", "3. **markdown** and <i>html</i>")
# Disable the parser completely
app.set_parse_mode(None)
app.send_message("me", "4. **markdown** and <i>html</i>")
app.send_message("haskell", "4. **markdown** and <i>html</i>")
# Bring back the default combined mode
app.set_parse_mode()
app.send_message("me", "5. **markdown** and <i>html</i>")
app.send_message("haskell", "5. **markdown** and <i>html</i>")
"""
self.parse_mode = parse_mode
@ -928,6 +916,9 @@ class Client(Methods, Scaffold):
while True:
chunk = r.bytes
if not chunk:
break
f.write(chunk)
offset += limit
@ -947,9 +938,6 @@ class Client(Methods, Scaffold):
else:
await self.loop.run_in_executor(self.executor, func)
if len(chunk) < limit:
break
r = await session.send(
raw.functions.upload.GetFile(
location=location,
@ -1021,7 +1009,7 @@ class Client(Methods, Scaffold):
# https://core.telegram.org/cdn#verifying-files
for i, h in enumerate(hashes):
cdn_chunk = decrypted_chunk[h.limit * i: h.limit * (i + 1)]
CDNFileHashMismatch.check(h.hash == sha256(cdn_chunk).digest())
assert h.hash == sha256(cdn_chunk).digest(), f"Invalid CDN hash part {i}"
f.write(decrypted_chunk)

View File

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

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -34,9 +34,7 @@ class Connection:
1: TCPAbridged,
2: TCPIntermediate,
3: TCPAbridgedO,
4: TCPIntermediateO,
5: TCPPaddedIntermediate,
6: TCPPaddedIntermediateO
4: TCPIntermediateO
}
def __init__(self, dc_id: int, test_mode: bool, ipv6: bool, proxy: dict, media: bool = False, mode: int = 3):
@ -48,7 +46,7 @@ class Connection:
self.address = DataCenter(dc_id, test_mode, ipv6, media)
self.mode = self.MODES.get(mode, TCPAbridged)
self.protocol = None # type: Optional[TCP]
self.protocol = None # type: TCP
async def connect(self):
for i in range(Connection.MAX_RETRIES):
@ -71,7 +69,7 @@ class Connection:
))
break
else:
log.warning("Connection failed! Retrying...")
log.warning("Connection failed! Trying again...")
raise TimeoutError
def close(self):

View File

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

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -21,6 +21,4 @@ from .tcp_abridged import TCPAbridged
from .tcp_abridged_o import TCPAbridgedO
from .tcp_full import TCPFull
from .tcp_intermediate import TCPIntermediate
from .tcp_padded_intermediate import TCPPaddedIntermediate
from .tcp_intermediate_o import TCPIntermediateO
from .tcp_padded_intermediate_o import TCPPaddedIntermediateO

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -24,12 +24,14 @@ import time
try:
import socks
except ImportError:
raise ImportError(
except ImportError as e:
e.msg = (
"PySocks is missing and Pyrogram can't run without. "
"Please install it using \"pip3 install pysocks\"."
)
raise e
log = logging.getLogger(__name__)

View File

@ -1,5 +1,5 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
# Copyright (C) 2017-2021 Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
@ -17,6 +17,7 @@
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import logging
from typing import Optional
from .tcp import TCP

View File

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

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