Update docs

This commit is contained in:
Dan 2020-08-22 16:09:38 +02:00
parent 5f087e5f82
commit 303712f599
14 changed files with 110 additions and 49 deletions

View File

@ -15,7 +15,7 @@ some of the required arguments.
@app.on_message() @app.on_message()
def hello(client, message) def hello(client, message)
message.reply("hi") message.reply_text("hi")
app.run() app.run()

View File

@ -1,12 +1,12 @@
Available Types Available Types
=============== ===============
This page is about Pyrogram types. All types listed here are accessible through the main package directly. This page is about Pyrogram types. All types listed here are accessible through ``types`` package.
.. code-block:: python .. code-block:: python
:emphasize-lines: 1 :emphasize-lines: 1
from pyrogram import User, Message, ... from pyrogram.types import User, Message, ...
.. note:: .. note::

View File

@ -5,7 +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. For a much more convenient way of registering callback functions have a look at :doc:`Decorators <decorators>` instead.
.. code-block:: python .. code-block:: python
:emphasize-lines: 1, 10 :emphasize-lines: 2, 11
from pyrogram import Client from pyrogram import Client
from pyrogram.handlers import MessageHandler from pyrogram.handlers import MessageHandler

View File

@ -40,12 +40,12 @@ Pyrogram is always evolving, although new releases on PyPI are published only wh
doesn't mean you can't try new features right now! 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; In case you'd like to try out the latest Pyrogram features, the `GitHub repo`_ is always kept updated with new changes;
you can install the development version straight from the ``develop`` branch using this command (note "develop.zip" in you can install the development version straight from the ``master`` branch using this command (note "master.zip" in
the link): the link):
.. code-block:: text .. code-block:: text
$ pip3 install -U https://github.com/pyrogram/pyrogram/archive/develop.zip $ pip3 install -U https://github.com/pyrogram/pyrogram/archive/master.zip
Verifying Verifying
--------- ---------

View File

@ -1,8 +1,8 @@
Quick Start Quick Start
=========== ===========
The next few steps serve as a quick start for all new Pyrogrammers that want to see Pyrogram in action as fast as The next few steps serve as a quick start for all new :term:`Pyrogrammers <Pyrogrammer>` that want to see Pyrogram in
possible. Let's go! action as fast as possible. Let's go!
Get Pyrogram Real Fast Get Pyrogram Real Fast
---------------------- ----------------------

View File

@ -1,7 +1,7 @@
Error Handling Error Handling
============== ==============
Errors are inevitable when working with the API, and they must be correctly handled with ``try..except`` blocks in order 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: to control the behaviour of your application. Pyrogram errors all live inside the ``errors`` package:
.. code-block:: python .. code-block:: python

View File

@ -11,7 +11,8 @@ like send_audio(), send_document(), send_location(), etc...
.. code-block:: python .. code-block:: python
from pyrogram import Client, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton from pyrogram import Client
from pyrogram.types import ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
# Create a client using your bot token # Create a client using your bot token
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11") app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")

View File

@ -3,19 +3,19 @@ echobot
This simple echo bot replies to every private text message. This simple echo bot replies to every private text message.
It uses the @on_message decorator to register a MessageHandler and applies two filters on it: It uses the ``@on_message`` decorator to register a ``MessageHandler`` and applies two filters on it:
Filters.text and Filters.private to make sure it will reply to private text messages only. ``filters.text`` and ``filters.private`` to make sure it will reply to private text messages only.
.. code-block:: python .. code-block:: python
from pyrogram import Client, Filters from pyrogram import Client, filters
app = Client("my_account") app = Client("my_account")
@app.on_message(Filters.text & Filters.private) @app.on_message(filters.text & filters.private)
def echo(client, message): def echo(client, message):
message.reply(message.text) message.reply_text(message.text)
app.run() # Automatically start() and idle() app.run() # Automatically start() and idle()

View File

@ -8,9 +8,9 @@ It uses the @on_inline_query decorator to register an InlineQueryHandler.
.. code-block:: python .. code-block:: python
from pyrogram import ( from pyrogram import Client
Client, InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardMarkup, InlineKeyboardButton from pyrogram.types import (InlineQueryResultArticle, InputTextMessageContent,
) InlineKeyboardMarkup, InlineKeyboardButton)
app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11") app = Client("my_bot", bot_token="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11")

View File

@ -1,14 +1,12 @@
welcomebot welcomebot
========== ==========
This is the Welcome Bot in @PyrogramChat. This example uses the ``emoji`` module to easily add emoji in your text messages and ``filters``
It uses the Emoji module to easily add emojis in your text messages and Filters
to make it only work for specific messages in a specific chat. to make it only work for specific messages in a specific chat.
.. code-block:: python .. code-block:: python
from pyrogram import Client, Emoji, Filters from pyrogram import Client, emoji, filters
TARGET = "PyrogramChat" # 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 MENTION = "[{}](tg://user?id={})" # User mention markup
@ -18,16 +16,16 @@ to make it only work for specific messages in a specific chat.
# Filter in only new_chat_members updates generated in TARGET chat # Filter in only new_chat_members updates generated in TARGET chat
@app.on_message(Filters.chat(TARGET) & Filters.new_chat_members) @app.on_message(filters.chat(TARGET) & filters.new_chat_members)
def welcome(client, message): def welcome(client, message):
# Build the new members list (with mentions) by using their first_name # Build the new members list (with mentions) by using their first_name
new_members = [MENTION.format(i.first_name, i.id) for i in message.new_chat_members] new_members = [u.mention for u in message.new_chat_members]
# Build the welcome message by using an emoji and the list we built above # Build the welcome message by using an emoji and the list we built above
text = MESSAGE.format(Emoji.SPARKLES, ", ".join(new_members)) text = MESSAGE.format(emoji.SPARKLES, ", ".join(new_members))
# Send the welcome message, without the web page preview # Send the welcome message, without the web page preview
message.reply(text, disable_web_page_preview=True) message.reply_text(text, disable_web_page_preview=True)
app.run() # Automatically start() and idle() app.run() # Automatically start() and idle()

View File

@ -14,8 +14,7 @@ account; we are now aiming towards the core of the library. It's time to start p
Basic Usage Basic Usage
----------- -----------
Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step and Making API method calls with Pyrogram is very simple. Here's a basic example we are going to examine step by step:
then expand to explain what happens underneath:
.. code-block:: python .. code-block:: python
@ -56,9 +55,9 @@ Basic step-by-step
Context Manager Context Manager
--------------- ---------------
The ``with`` statement starts a context manager, which is used as a shortcut to automatically call The ``with`` statement starts a context manager used as a shortcut to automatically call :meth:`~pyrogram.Client.start`
:meth:`~pyrogram.Client.start` and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work and :meth:`~pyrogram.Client.stop`, which are methods required for Pyrogram to work properly. The context manager does
properly. The context manager does also gracefully stop the client, even in case of unhandled exceptions in your code. also gracefully stop the client, even in case of unhandled exceptions in your code.
This is how Pyrogram looks without the context manager: This is how Pyrogram looks without the context manager:
@ -111,8 +110,8 @@ Asynchronous step-by-step
async with app: async with app:
await app.send_message("me", "Hi!") await app.send_message("me", "Hi!")
#. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's code. Using #. Finally, we tell Python to schedule our ``main()`` async function, which in turn will execute Pyrogram's methods.
:meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose Using :meth:`~pyrogram.Client.run` this way is a friendly alternative for the much more verbose
``asyncio.get_event_loop().run_until_complete(main())``: ``asyncio.get_event_loop().run_until_complete(main())``:
.. code-block:: python .. code-block:: python

View File

@ -26,8 +26,8 @@ Registering a Handler
--------------------- ---------------------
To explain how handlers work let's examine the one which will be in charge for handling :class:`~pyrogram.types.Message` To explain how handlers work let's examine the one which will be in charge for handling :class:`~pyrogram.types.Message`
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have updates coming from all around your chats. Every other kind of handler shares the same setup logic and you should not
troubles settings them up once you learn from this section. have troubles settings them up once you learn from this section.
Using Decorators Using Decorators
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
@ -98,3 +98,9 @@ The same about asynchronous handlers applies for :meth:`~pyrogram.Client.add_han
async def my_function(client, message): async def my_function(client, message):
await message.forward("me") await message.forward("me")
.. note::
From now on, you'll see examples using synchronous code (i.e.: without ``async`` and ``await``, unless when actually
relevant). This is done to keep snippets concise and more readable. Once you get the idea behind a feature, you can
easily turn examples asynchronous later on.

View File

@ -2,7 +2,8 @@ Creating Filters
================ ================
Pyrogram already provides lots of built-in :class:`~pyrogram.filters` to work with, but in case you can't find a Pyrogram already provides lots of built-in :class:`~pyrogram.filters` to work with, but in case you can't find a
specific one for your needs or want to build a custom filter by yourself you can use :meth:`~pyrogram.filters.create`. specific one for your needs or want to build a custom filter by yourself you can use
:meth:`filters.create() <pyrogram.filters.create>`.
.. contents:: Contents .. contents:: Contents
:backlinks: none :backlinks: none
@ -37,29 +38,45 @@ Basic Filters
For this basic filter we will be using only the first parameter of :meth:`~pyrogram.filters.create`. For this basic filter we will be using only the first parameter of :meth:`~pyrogram.filters.create`.
The code below creates a simple filter for hardcoded, static callback data. This filter will only allow callback queries The heart of a filter is its callback function, which accepts three arguments *(self, client, update)* and returns
containing "pyrogram" as data, that is, the function *func* you pass returns True in case the callback query data either ``True``, in case you want the update to pass the filter or ``False`` otherwise.
equals to ``"pyrogram"``.
In this example we are matching the query data to "pyrogram", which means that the filter will only allow callback
queries containing "pyrogram" as data:
.. code-block:: python .. code-block:: python
from pyrogram import filters from pyrogram import filters
static_data_filter = filters.create(lambda _, query: query.data == "pyrogram") static_data_filter = filters.create(lambda _, __, query: query.data == "pyrogram")
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example, the same The first two arguments of the callback function are unused here and because of this we named them using underscores.
could be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
The ``lambda`` operator in python is used to create small anonymous functions and is perfect for this example. The same
can be achieved with a normal function, but we don't really need it as it makes sense only inside the filter's scope:
.. code-block:: python .. code-block:: python
from pyrogram import filters from pyrogram import filters
def func(_, query): def func(_, __, query):
return query.data == "pyrogram" return query.data == "pyrogram"
static_data_filter = filters.create(func) static_data_filter = filters.create(func)
The filter usage remains the same: Asynchronous filters are also possible. Sadly, Python itself doesn't have an ``async lambda``, so we are left with
using a named function:
.. code-block:: python
from pyrogram import filters
async def func(_, __, query):
return query.data == "pyrogram"
static_data_filter = filters.create(func)
Finally, the filter usage remains the same:
.. code-block:: python .. code-block:: python
@ -70,8 +87,10 @@ The filter usage remains the same:
Filters with Arguments Filters with Arguments
---------------------- ----------------------
A much cooler filter would be one that accepts "pyrogram" or any other data as argument at usage time. A much cooler filter would be one that accepts "pyrogram" or any other string as argument at usage time.
A dynamic filter like this will make use of named arguments for the :meth:`~pyrogram.filters.create` method. 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.
This is how a dynamic custom filter looks like: This is how a dynamic custom filter looks like:
@ -81,14 +100,52 @@ This is how a dynamic custom filter looks like:
def dynamic_data_filter(data): def dynamic_data_filter(data):
return filters.create( return filters.create(
lambda flt, query: flt.data == query.data, lambda flt, _, query: flt.data == query.data,
data=data # "data" kwarg is accessed with "flt.data" above data=data # "data" kwarg is accessed with "flt.data" above
) )
And its usage: And its asynchronous variant:
.. code-block:: python
from pyrogram import filters
def dynamic_data_filter(data):
async def func(flt, _, query):
return flt.data == query.data
# "data" kwarg is accessed with "flt.data" above
return filters.create(func, data=data)
And finally its usage:
.. code-block:: python .. code-block:: python
@app.on_callback_query(dynamic_data_filter("pyrogram")) @app.on_callback_query(dynamic_data_filter("pyrogram"))
def pyrogram_data(_, query): def pyrogram_data(_, query):
query.answer("it works!") query.answer("it works!")
Method Calls Inside Filters
---------------------------
The missing piece we haven't covered yet is the second argument of a filter callback function, namely, the ``client``
argument. This is a reference to the :obj:`~pyrogram.Client` instance that is running the filter and it is useful in
case you would like to make some API calls before deciding whether the filter should allow the update or not:
.. code-block:: python
def func(_, client, query):
# r = client.some_api_method()
# check response "r" and decide to return True or False
...
Asynchronous filters making API calls work fine as well. Just remember that you need to put ``async`` in front of
function definitions and ``await`` in front of method calls:
.. code-block:: python
async def func(_, client, query):
# r = await client.some_api_method()
# check response "r" and decide to return True or False
...

View File

@ -58,7 +58,7 @@ class Client(Methods, Scaffold):
session_name (``str``): session_name (``str``):
Pass a string of your choice to give a name to the client session, e.g.: "*my_account*". This name will be Pass a string of your choice to give a name to the client session, e.g.: "*my_account*". This name will be
used to save a file on disk that stores details needed to reconnect without asking again for credentials. used to save a file on disk that stores details needed to reconnect without asking again for credentials.
Alternatively, if you don't want a file to be saved on disk, pass the special name "**:memory:**" to start Alternatively, if you don't want a file to be saved on disk, pass the special name ``":memory:"`` to start
an in-memory session that will be discarded as soon as you stop the Client. In order to reconnect again an in-memory session that will be discarded as soon as you stop the Client. In order to reconnect again
using a memory storage without having to login again, you can use using a memory storage without having to login again, you can use
:meth:`~pyrogram.Client.export_session_string` before stopping the client to get a session string you can :meth:`~pyrogram.Client.export_session_string` before stopping the client to get a session string you can