mirror of
https://github.com/TeamPGM/pyrogram.git
synced 2024-11-18 13:34:54 +00:00
Merge branch 'develop' into asyncio
# Conflicts: # pyrogram/client/client.py # pyrogram/client/methods/users/delete_user_profile_photos.py
This commit is contained in:
commit
f45e3377a9
@ -506,6 +506,7 @@ def start():
|
|||||||
f.write("\n 0xb0700028: \"pyrogram.client.types.Dialog\",")
|
f.write("\n 0xb0700028: \"pyrogram.client.types.Dialog\",")
|
||||||
f.write("\n 0xb0700029: \"pyrogram.client.types.Dialogs\",")
|
f.write("\n 0xb0700029: \"pyrogram.client.types.Dialogs\",")
|
||||||
f.write("\n 0xb0700030: \"pyrogram.client.types.ChatMembers\",")
|
f.write("\n 0xb0700030: \"pyrogram.client.types.ChatMembers\",")
|
||||||
|
f.write("\n 0xb0700031: \"pyrogram.client.types.UserStatus\"")
|
||||||
|
|
||||||
f.write("\n}\n")
|
f.write("\n}\n")
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ Welcome to Pyrogram
|
|||||||
<a href="https://t.me/PyrogramChat">
|
<a href="https://t.me/PyrogramChat">
|
||||||
Community
|
Community
|
||||||
</a>
|
</a>
|
||||||
<br><br>
|
<br>
|
||||||
<a href="https://github.com/pyrogram/pyrogram/blob/master/compiler/api/source/main_api.tl">
|
<a href="https://github.com/pyrogram/pyrogram/blob/master/compiler/api/source/main_api.tl">
|
||||||
<img src="https://img.shields.io/badge/SCHEME-LAYER%2082-eda738.svg?longCache=true&style=for-the-badge&colorA=262b30"
|
<img src="https://img.shields.io/badge/schema-layer%2082-eda738.svg?longCache=true&colorA=262b30"
|
||||||
alt="Scheme Layer">
|
alt="Scheme Layer">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/pyrogram/tgcrypto">
|
<a href="https://github.com/pyrogram/tgcrypto">
|
||||||
<img src="https://img.shields.io/badge/TGCRYPTO-V1.1.1-eda738.svg?longCache=true&style=for-the-badge&colorA=262b30"
|
<img src="https://img.shields.io/badge/tgcrypto-v1.1.1-eda738.svg?longCache=true&colorA=262b30"
|
||||||
alt="TgCrypto">
|
alt="TgCrypto">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@ -49,14 +49,14 @@ Welcome to Pyrogram
|
|||||||
app.run()
|
app.run()
|
||||||
|
|
||||||
Welcome to Pyrogram's Documentation! Here you can find resources for learning how to use the library.
|
Welcome to Pyrogram's Documentation! Here you can find resources for learning how to use the library.
|
||||||
Contents are organized by topic and can be accessed from the sidebar, or by following them one by one using the Next
|
Contents are organized into self-contained topics and can be accessed from the sidebar, or by following them in order
|
||||||
button at the end of each page. But first, here's a brief overview of what is this all about.
|
using the Next button at the end of each page. But first, here's a brief overview of what is this all about.
|
||||||
|
|
||||||
About
|
About
|
||||||
-----
|
-----
|
||||||
|
|
||||||
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for building
|
**Pyrogram** is a brand new Telegram_ Client Library written from the ground up in Python and C. It can be used for
|
||||||
custom Telegram applications that interact with the MTProto API as both User and Bot.
|
building custom Telegram applications that interact with the MTProto API as both User and Bot.
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
@ -64,7 +64,7 @@ Features
|
|||||||
- **Easy to use**: You can easily install Pyrogram using pip and start building your app right away.
|
- **Easy to use**: You can easily install Pyrogram using pip and start building your app right away.
|
||||||
- **High-level**: The low-level details of MTProto are abstracted and automatically handled.
|
- **High-level**: The low-level details of MTProto are abstracted and automatically handled.
|
||||||
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
- **Fast**: Crypto parts are boosted up by TgCrypto_, a high-performance library written in pure C.
|
||||||
- **Updated** to the latest Telegram API version, currently Layer 81 on top of MTProto 2.0.
|
- **Updated** to the latest Telegram API version, currently Layer 82 on top of MTProto 2.0.
|
||||||
- **Documented**: The Pyrogram API is well documented and resembles the Telegram Bot API.
|
- **Documented**: The Pyrogram API is well documented and resembles the Telegram Bot API.
|
||||||
- **Full API**, allowing to execute any advanced action an official client is able to do, and more.
|
- **Full API**, allowing to execute any advanced action an official client is able to do, and more.
|
||||||
|
|
||||||
@ -84,6 +84,7 @@ To get started, press the Next button.
|
|||||||
|
|
||||||
resources/UpdateHandling
|
resources/UpdateHandling
|
||||||
resources/UsingFilters
|
resources/UsingFilters
|
||||||
|
resources/Plugins
|
||||||
resources/AutoAuthorization
|
resources/AutoAuthorization
|
||||||
resources/CustomizeSessions
|
resources/CustomizeSessions
|
||||||
resources/TgCrypto
|
resources/TgCrypto
|
||||||
|
@ -30,6 +30,7 @@ Decorators
|
|||||||
on_message
|
on_message
|
||||||
on_callback_query
|
on_callback_query
|
||||||
on_deleted_messages
|
on_deleted_messages
|
||||||
|
on_user_status
|
||||||
on_disconnect
|
on_disconnect
|
||||||
on_raw_update
|
on_raw_update
|
||||||
|
|
||||||
@ -96,7 +97,8 @@ Users
|
|||||||
get_me
|
get_me
|
||||||
get_users
|
get_users
|
||||||
get_user_profile_photos
|
get_user_profile_photos
|
||||||
delete_profile_photos
|
set_user_profile_photo
|
||||||
|
delete_user_profile_photos
|
||||||
|
|
||||||
Contacts
|
Contacts
|
||||||
--------
|
--------
|
||||||
|
@ -9,6 +9,7 @@ Handlers
|
|||||||
MessageHandler
|
MessageHandler
|
||||||
DeletedMessagesHandler
|
DeletedMessagesHandler
|
||||||
CallbackQueryHandler
|
CallbackQueryHandler
|
||||||
|
UserStatusHandler
|
||||||
DisconnectHandler
|
DisconnectHandler
|
||||||
RawUpdateHandler
|
RawUpdateHandler
|
||||||
|
|
||||||
@ -21,6 +22,9 @@ Handlers
|
|||||||
.. autoclass:: CallbackQueryHandler
|
.. autoclass:: CallbackQueryHandler
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: UserStatusHandler
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: DisconnectHandler
|
.. autoclass:: DisconnectHandler
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ Users & Chats
|
|||||||
:nosignatures:
|
:nosignatures:
|
||||||
|
|
||||||
User
|
User
|
||||||
|
UserStatus
|
||||||
Chat
|
Chat
|
||||||
ChatPhoto
|
ChatPhoto
|
||||||
ChatMember
|
ChatMember
|
||||||
@ -73,6 +74,9 @@ Input Media
|
|||||||
.. autoclass:: User
|
.. autoclass:: User
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: UserStatus
|
||||||
|
:members:
|
||||||
|
|
||||||
.. autoclass:: Chat
|
.. autoclass:: Chat
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
116
docs/source/resources/Plugins.rst
Normal file
116
docs/source/resources/Plugins.rst
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
Plugins
|
||||||
|
=======
|
||||||
|
|
||||||
|
Pyrogram embeds an **automatic** and lightweight plugin system that is meant to greatly simplify the organization of
|
||||||
|
large projects and to provide a way for creating pluggable components that can be **easily shared** across different
|
||||||
|
Pyrogram applications with **minimal boilerplate code**.
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
Prior to the plugin system, pluggable handlers were already possible. For instance, if you wanted to modularize your
|
||||||
|
applications, you had to do something like this...
|
||||||
|
|
||||||
|
.. note:: This is an example application that replies in private chats with two messages: one containing the same
|
||||||
|
text message you sent and the other containing the reversed text message (e.g.: "pyrogram" -> "pyrogram" and
|
||||||
|
"margoryp"):
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
myproject/
|
||||||
|
config.ini
|
||||||
|
handlers.py
|
||||||
|
main.py
|
||||||
|
|
||||||
|
- ``handlers.py``
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def echo(client, message):
|
||||||
|
message.reply(message.text)
|
||||||
|
|
||||||
|
|
||||||
|
def echo_reversed(client, message):
|
||||||
|
message.reply(message.text[::-1])
|
||||||
|
|
||||||
|
- ``main.py``
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client, MessageHandler, Filters
|
||||||
|
|
||||||
|
from handlers import echo, echo_reversed
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
app.add_handler(
|
||||||
|
MessageHandler(
|
||||||
|
echo,
|
||||||
|
Filters.text & Filters.private))
|
||||||
|
|
||||||
|
app.add_handler(
|
||||||
|
MessageHandler(
|
||||||
|
echo_reversed,
|
||||||
|
Filters.text & Filters.private),
|
||||||
|
group=1)
|
||||||
|
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
...which is already nice and doesn't add *too much* boilerplate code, but things can get boring still; you have to
|
||||||
|
manually ``import``, manually :meth:`add_handler <pyrogram.Client.add_handler>` and manually instantiate each
|
||||||
|
:obj:`MessageHandler <pyrogram.MessageHandler>` object because **you can't use those cool decorators** for your
|
||||||
|
functions. So... What if you could?
|
||||||
|
|
||||||
|
Creating Plugins
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Setting up your Pyrogram project to accommodate plugins is as easy as creating a folder and putting your files full of
|
||||||
|
handlers inside.
|
||||||
|
|
||||||
|
.. note:: This is the same example application `as shown above <#introduction>`_, written using the plugin system.
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
:emphasize-lines: 2, 3
|
||||||
|
|
||||||
|
myproject/
|
||||||
|
plugins/
|
||||||
|
handlers.py
|
||||||
|
config.ini
|
||||||
|
main.py
|
||||||
|
|
||||||
|
- ``plugins/handlers.py``
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:emphasize-lines: 4, 9
|
||||||
|
|
||||||
|
from pyrogram import Client, Filters
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(Filters.text & Filters.private)
|
||||||
|
def echo(client, message):
|
||||||
|
message.reply(message.text)
|
||||||
|
|
||||||
|
|
||||||
|
@Client.on_message(Filters.text & Filters.private, group=1)
|
||||||
|
def echo_reversed(client, message):
|
||||||
|
message.reply(message.text[::-1])
|
||||||
|
|
||||||
|
- ``main.py``
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
Client("my_account").run()
|
||||||
|
|
||||||
|
The first important thing to note is the ``plugins`` folder, whose name is default and can be changed easily by setting
|
||||||
|
the ``plugins_dir`` parameter when creating a :obj:`Client <pyrogram.Client>`; you can put any python file in the
|
||||||
|
plugins folder and each file can contain any decorated function (handlers). Your Pyrogram Client instance (in the
|
||||||
|
``main.py`` file) will **automatically** scan the folder upon creation to search for valid handlers and register them
|
||||||
|
for you.
|
||||||
|
|
||||||
|
Then you'll notice you can now use decorators. That's right, you can apply the usual decorators to your callback
|
||||||
|
functions in a static way, i.e. **without having the Client instance around**: simply use ``@Client`` (Client class)
|
||||||
|
instead of the usual ``@app`` (Client instance) namespace and things will work just the same.
|
||||||
|
|
||||||
|
The ``main.py`` script is now at its bare minimum and cleanest state.
|
@ -2,15 +2,15 @@ Update Handling
|
|||||||
===============
|
===============
|
||||||
|
|
||||||
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
Updates are events that happen in your Telegram account (incoming messages, new channel posts, new members join, ...)
|
||||||
and can be handled by registering one or more callback functions in your app by using an `Handler <../pyrogram/Handlers.html>`_.
|
and can be handled by registering one or more callback functions in your app by using `Handlers <../pyrogram/Handlers.html>`_.
|
||||||
|
|
||||||
To put it simply, whenever an update is received from Telegram it will be dispatched and your previously defined callback
|
To put it simply, whenever an update is received from Telegram it will be dispatched and your previously defined callback
|
||||||
function(s) will be called back with the update itself as argument.
|
function(s) matching it will be called back with the update itself as argument.
|
||||||
|
|
||||||
Registering an Handler
|
Registering an Handler
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
To explain how `Handlers <../pyrogram/Handlers.html>`_ work let's have a look at the most used one, the
|
To explain how handlers work let's have a look at the most used one, the
|
||||||
:obj:`MessageHandler <pyrogram.MessageHandler>`, which will be in charge for handling :obj:`Message <pyrogram.Message>`
|
:obj:`MessageHandler <pyrogram.MessageHandler>`, which will be in charge for handling :obj:`Message <pyrogram.Message>`
|
||||||
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
updates coming from all around your chats. Every other handler shares the same setup logic; you should not have troubles
|
||||||
settings them up once you learn from this section.
|
settings them up once you learn from this section.
|
||||||
|
@ -4,11 +4,12 @@ Installation
|
|||||||
Being a Python library, Pyrogram requires Python to be installed in your system.
|
Being a Python library, Pyrogram requires Python to be installed in your system.
|
||||||
We recommend using the latest version of Python 3 and pip.
|
We recommend using the latest version of Python 3 and pip.
|
||||||
|
|
||||||
Get Python 3 from https://www.python.org/downloads/ or with your package manager and pip
|
Get Python 3 from https://www.python.org/downloads/ (or with your package manager) and pip
|
||||||
by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
by following the instructions at https://pip.pypa.io/en/latest/installing/.
|
||||||
|
|
||||||
.. note::
|
.. important::
|
||||||
Pyrogram supports Python 3 only, starting from version 3.4 and PyPy.
|
|
||||||
|
Pyrogram supports **Python 3** only, starting from version 3.4. **PyPy** is supported too.
|
||||||
|
|
||||||
Install Pyrogram
|
Install Pyrogram
|
||||||
----------------
|
----------------
|
||||||
@ -29,7 +30,7 @@ Bleeding Edge
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
If you want the latest development version of Pyrogram, you can install it straight from the develop_
|
If you want the latest development version of Pyrogram, you can install it straight from the develop_
|
||||||
branch using this command:
|
branch using this command (you might need to install **git** first):
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ fits better for you:
|
|||||||
)
|
)
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The examples below assume you have created a ``config.ini`` file, thus they won't show the *api_id*
|
The examples below assume you have created a ``config.ini`` file, thus they won't show the *api_id*
|
||||||
and *api_hash* parameters usage.
|
and *api_hash* parameters usage.
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ the :class:`Client <pyrogram.Client>` class by passing to it a ``session_name``
|
|||||||
This starts an interactive shell asking you to input your **phone number** (including your `Country Code`_)
|
This starts an interactive shell asking you to input your **phone number** (including your `Country Code`_)
|
||||||
and the **phone code** you will receive:
|
and the **phone code** you will receive:
|
||||||
|
|
||||||
.. code::
|
.. code-block:: text
|
||||||
|
|
||||||
Enter phone number: +39**********
|
Enter phone number: +39**********
|
||||||
Is "+39**********" correct? (y/n): y
|
Is "+39**********" correct? (y/n): y
|
||||||
@ -84,7 +85,9 @@ After successfully authorizing yourself, a new file called ``my_account.session`
|
|||||||
Pyrogram executing API calls with your identity. This file will be loaded again when you restart your app,
|
Pyrogram executing API calls with your identity. This file will be loaded again when you restart your app,
|
||||||
and as long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
and as long as you keep the session alive, Pyrogram won't ask you again to enter your phone number.
|
||||||
|
|
||||||
.. important:: Your ``*.session`` files are personal and must be kept secret.
|
.. important::
|
||||||
|
|
||||||
|
Your ``*.session`` files are personal and must be kept secret.
|
||||||
|
|
||||||
Bot Authorization
|
Bot Authorization
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -10,25 +10,38 @@ High-level API
|
|||||||
The easiest and recommended way to interact with Telegram is via the high-level Pyrogram methods_ and types_, which are
|
The easiest and recommended way to interact with Telegram is via the high-level Pyrogram methods_ and types_, which are
|
||||||
named after the `Telegram Bot API`_.
|
named after the `Telegram Bot API`_.
|
||||||
|
|
||||||
Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_):
|
Here's a simple example:
|
||||||
|
|
||||||
- Get information about the authorized user:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
from pyrogram import Client
|
||||||
|
|
||||||
|
app = Client("my_account")
|
||||||
|
|
||||||
|
app.start()
|
||||||
|
|
||||||
print(app.get_me())
|
print(app.get_me())
|
||||||
|
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||||
|
app.send_location("me", 51.500729, -0.124583)
|
||||||
|
|
||||||
- Send a message to yourself (Saved Messages):
|
app.stop()
|
||||||
|
|
||||||
|
You can also use Pyrogram in a context manager with the ``with`` statement. The Client will automatically
|
||||||
|
:meth:`start <pyrogram.Client.start>` and :meth:`stop <pyrogram.Client.stop>` gracefully, even in case of unhandled
|
||||||
|
exceptions in your code:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
app.send_message("me", "Hi there! I'm using Pyrogram")
|
from pyrogram import Client
|
||||||
|
|
||||||
- Upload a new photo (with caption):
|
app = Client("my_account")
|
||||||
|
|
||||||
.. code-block:: python
|
with app:
|
||||||
|
print(app.get_me())
|
||||||
|
app.send_message("me", "Hi there! I'm using **Pyrogram**")
|
||||||
|
app.send_location("me", 51.500729, -0.124583)
|
||||||
|
|
||||||
app.send_photo("me", "/home/dan/perla.jpg", "Cute!")
|
More examples on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/examples>`_.
|
||||||
|
|
||||||
Raw Functions
|
Raw Functions
|
||||||
-------------
|
-------------
|
||||||
@ -38,7 +51,9 @@ you have to use the raw :mod:`functions <pyrogram.api.functions>` and :mod:`type
|
|||||||
``pyrogram.api`` package and call any Telegram API method you wish using the :meth:`send() <pyrogram.Client.send>`
|
``pyrogram.api`` package and call any Telegram API method you wish using the :meth:`send() <pyrogram.Client.send>`
|
||||||
method provided by the Client class.
|
method provided by the Client class.
|
||||||
|
|
||||||
.. hint:: Every high-level method mentioned in the section above is built on top of these raw functions.
|
.. hint::
|
||||||
|
|
||||||
|
Every high-level method mentioned in the section above is built on top of these raw functions.
|
||||||
|
|
||||||
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
|
Nothing stops you from using the raw functions only, but they are rather complex and `plenty of them`_ are already
|
||||||
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API.
|
re-implemented by providing a much simpler and cleaner interface which is very similar to the Bot API.
|
||||||
@ -54,9 +69,7 @@ Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exa
|
|||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
from pyrogram.api import functions
|
from pyrogram.api import functions
|
||||||
|
|
||||||
app = Client("my_account")
|
with Client("my_account") as app:
|
||||||
app.start()
|
|
||||||
|
|
||||||
app.send(
|
app.send(
|
||||||
functions.account.UpdateProfile(
|
functions.account.UpdateProfile(
|
||||||
first_name="Dan", last_name="Tès",
|
first_name="Dan", last_name="Tès",
|
||||||
@ -64,8 +77,6 @@ Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exa
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
app.stop()
|
|
||||||
|
|
||||||
- Share your Last Seen time only with your contacts:
|
- Share your Last Seen time only with your contacts:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@ -73,9 +84,7 @@ Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exa
|
|||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
|
|
||||||
app = Client("my_account")
|
with Client("my_account") as app:
|
||||||
app.start()
|
|
||||||
|
|
||||||
app.send(
|
app.send(
|
||||||
functions.account.SetPrivacy(
|
functions.account.SetPrivacy(
|
||||||
key=types.InputPrivacyKeyStatusTimestamp(),
|
key=types.InputPrivacyKeyStatusTimestamp(),
|
||||||
@ -83,8 +92,6 @@ Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exa
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
app.stop()
|
|
||||||
|
|
||||||
- Invite users to your channel/supergroup:
|
- Invite users to your channel/supergroup:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@ -92,9 +99,7 @@ Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exa
|
|||||||
from pyrogram import Client
|
from pyrogram import Client
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
|
|
||||||
app = Client("my_account")
|
with Client("my_account") as app:
|
||||||
app.start()
|
|
||||||
|
|
||||||
app.send(
|
app.send(
|
||||||
functions.channels.InviteToChannel(
|
functions.channels.InviteToChannel(
|
||||||
channel=app.resolve_peer(123456789), # ID or Username
|
channel=app.resolve_peer(123456789), # ID or Username
|
||||||
@ -106,8 +111,6 @@ Examples (more on `GitHub <https://github.com/pyrogram/pyrogram/tree/develop/exa
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
app.stop()
|
|
||||||
|
|
||||||
.. _methods: ../pyrogram/Client.html#messages
|
.. _methods: ../pyrogram/Client.html#messages
|
||||||
.. _plenty of them: ../pyrogram/Client.html#messages
|
.. _plenty of them: ../pyrogram/Client.html#messages
|
||||||
.. _types: ../pyrogram/Types.html
|
.. _types: ../pyrogram/Types.html
|
||||||
|
@ -37,12 +37,12 @@ from .api.errors import Error
|
|||||||
from .client.types import (
|
from .client.types import (
|
||||||
Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
|
Audio, Chat, ChatMember, ChatMembers, ChatPhoto, Contact, Document, InputMediaPhoto,
|
||||||
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
|
InputMediaVideo, InputMediaDocument, InputMediaAudio, InputMediaAnimation, InputPhoneContact,
|
||||||
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, Update, User,
|
Location, Message, MessageEntity, Dialog, Dialogs, Photo, PhotoSize, Sticker, Update, User, UserStatus,
|
||||||
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
|
UserProfilePhotos, Venue, Animation, Video, VideoNote, Voice, CallbackQuery, Messages, ForceReply,
|
||||||
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
||||||
)
|
)
|
||||||
from .client import (
|
from .client import (
|
||||||
Client, ChatAction, ParseMode, Emoji,
|
Client, ChatAction, ParseMode, Emoji,
|
||||||
MessageHandler, DeletedMessagesHandler, CallbackQueryHandler,
|
MessageHandler, DeletedMessagesHandler, CallbackQueryHandler,
|
||||||
RawUpdateHandler, DisconnectHandler, Filters
|
RawUpdateHandler, DisconnectHandler, UserStatusHandler, Filters
|
||||||
)
|
)
|
||||||
|
@ -22,5 +22,5 @@ from .filters import Filters
|
|||||||
from .handlers import (
|
from .handlers import (
|
||||||
MessageHandler, DeletedMessagesHandler,
|
MessageHandler, DeletedMessagesHandler,
|
||||||
CallbackQueryHandler, RawUpdateHandler,
|
CallbackQueryHandler, RawUpdateHandler,
|
||||||
DisconnectHandler
|
DisconnectHandler, UserStatusHandler
|
||||||
)
|
)
|
||||||
|
@ -33,6 +33,7 @@ import time
|
|||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from hashlib import sha256, md5
|
from hashlib import sha256, md5
|
||||||
|
from importlib import import_module
|
||||||
from signal import signal, SIGINT, SIGTERM, SIGABRT
|
from signal import signal, SIGINT, SIGTERM, SIGABRT
|
||||||
|
|
||||||
from pyrogram.api import functions, types
|
from pyrogram.api import functions, types
|
||||||
@ -43,6 +44,8 @@ from pyrogram.api.errors import (
|
|||||||
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
PhoneCodeExpired, PhoneCodeEmpty, SessionPasswordNeeded,
|
||||||
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
|
PasswordHashInvalid, FloodWait, PeerIdInvalid, FirstnameInvalid, PhoneNumberBanned,
|
||||||
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate)
|
VolumeLocNotFound, UserMigrate, FileIdInvalid, ChannelPrivate)
|
||||||
|
from pyrogram.client.handlers import DisconnectHandler
|
||||||
|
from pyrogram.client.handlers.handler import Handler
|
||||||
from pyrogram.crypto import AES
|
from pyrogram.crypto import AES
|
||||||
from pyrogram.session import Auth, Session
|
from pyrogram.session import Auth, Session
|
||||||
from .dispatcher import Dispatcher
|
from .dispatcher import Dispatcher
|
||||||
@ -140,6 +143,11 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
config_file (``str``, *optional*):
|
config_file (``str``, *optional*):
|
||||||
Path of the configuration file. Defaults to ./config.ini
|
Path of the configuration file. Defaults to ./config.ini
|
||||||
|
|
||||||
|
plugins_dir (``str``, *optional*):
|
||||||
|
Define a custom directory for your plugins. The plugins directory is the location in your
|
||||||
|
filesystem where Pyrogram will automatically load your update handlers.
|
||||||
|
Defaults to "./plugins". Set to None to completely disable plugins.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -159,9 +167,10 @@ class Client(Methods, BaseClient):
|
|||||||
force_sms: bool = False,
|
force_sms: bool = False,
|
||||||
first_name: str = None,
|
first_name: str = None,
|
||||||
last_name: str = None,
|
last_name: str = None,
|
||||||
workers: int = 4,
|
workers: int = BaseClient.WORKERS,
|
||||||
workdir: str = ".",
|
workdir: str = BaseClient.WORKDIR,
|
||||||
config_file: str = "./config.ini"):
|
config_file: str = BaseClient.CONFIG_FILE,
|
||||||
|
plugins_dir: str or None = BaseClient.PLUGINS_DIR):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self.session_name = session_name
|
self.session_name = session_name
|
||||||
@ -184,6 +193,7 @@ class Client(Methods, BaseClient):
|
|||||||
self.workers = workers
|
self.workers = workers
|
||||||
self.workdir = workdir
|
self.workdir = workdir
|
||||||
self.config_file = config_file
|
self.config_file = config_file
|
||||||
|
self.plugins_dir = plugins_dir
|
||||||
|
|
||||||
self.dispatcher = Dispatcher(self, workers)
|
self.dispatcher = Dispatcher(self, workers)
|
||||||
|
|
||||||
@ -219,6 +229,7 @@ class Client(Methods, BaseClient):
|
|||||||
|
|
||||||
self.load_config()
|
self.load_config()
|
||||||
await self.load_session()
|
await self.load_session()
|
||||||
|
self.load_plugins()
|
||||||
|
|
||||||
self.session = Session(
|
self.session = Session(
|
||||||
self,
|
self,
|
||||||
@ -966,6 +977,44 @@ class Client(Methods, BaseClient):
|
|||||||
if peer:
|
if peer:
|
||||||
self.peers_by_phone[k] = peer
|
self.peers_by_phone[k] = peer
|
||||||
|
|
||||||
|
def load_plugins(self):
|
||||||
|
if self.plugins_dir is not None:
|
||||||
|
try:
|
||||||
|
dirs = os.listdir(self.plugins_dir)
|
||||||
|
except FileNotFoundError:
|
||||||
|
if self.plugins_dir == Client.PLUGINS_DIR:
|
||||||
|
log.info("No plugin loaded: default directory is missing")
|
||||||
|
else:
|
||||||
|
log.warning('No plugin loaded: "{}" directory is missing'.format(self.plugins_dir))
|
||||||
|
else:
|
||||||
|
plugins_dir = self.plugins_dir.lstrip("./").replace("/", ".")
|
||||||
|
plugins_count = 0
|
||||||
|
|
||||||
|
for i in dirs:
|
||||||
|
module = import_module("{}.{}".format(plugins_dir, i.split(".")[0]))
|
||||||
|
|
||||||
|
for j in dir(module):
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
handler, group = getattr(module, j)
|
||||||
|
|
||||||
|
if isinstance(handler, Handler) and isinstance(group, int):
|
||||||
|
self.add_handler(handler, group)
|
||||||
|
|
||||||
|
log.info('{}("{}") from "{}/{}" loaded in group {}'.format(
|
||||||
|
type(handler).__name__, j, self.plugins_dir, i, group)
|
||||||
|
)
|
||||||
|
|
||||||
|
plugins_count += 1
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
log.warning('Successfully loaded {} plugin{} from "{}"'.format(
|
||||||
|
plugins_count,
|
||||||
|
"s" if plugins_count > 1 else "",
|
||||||
|
self.plugins_dir
|
||||||
|
))
|
||||||
|
|
||||||
def save_session(self):
|
def save_session(self):
|
||||||
auth_key = base64.b64encode(self.auth_key).decode()
|
auth_key = base64.b64encode(self.auth_key).decode()
|
||||||
auth_key = [auth_key[i: i + 43] for i in range(0, len(auth_key), 43)]
|
auth_key = [auth_key[i: i + 43] for i in range(0, len(auth_key), 43)]
|
||||||
|
@ -23,7 +23,7 @@ from collections import OrderedDict
|
|||||||
import pyrogram
|
import pyrogram
|
||||||
from pyrogram.api import types
|
from pyrogram.api import types
|
||||||
from ..ext import utils
|
from ..ext import utils
|
||||||
from ..handlers import RawUpdateHandler, CallbackQueryHandler, MessageHandler, DeletedMessagesHandler
|
from ..handlers import RawUpdateHandler, CallbackQueryHandler, MessageHandler, DeletedMessagesHandler, UserStatusHandler
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -108,6 +108,8 @@ class Dispatcher:
|
|||||||
|
|
||||||
callback_query = update.callback_query
|
callback_query = update.callback_query
|
||||||
|
|
||||||
|
user_status = update.user_status
|
||||||
|
|
||||||
if message and isinstance(handler, MessageHandler):
|
if message and isinstance(handler, MessageHandler):
|
||||||
if not handler.check(message):
|
if not handler.check(message):
|
||||||
continue
|
continue
|
||||||
@ -123,6 +125,11 @@ class Dispatcher:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
args = (self.client, callback_query)
|
args = (self.client, callback_query)
|
||||||
|
elif user_status and isinstance(handler, UserStatusHandler):
|
||||||
|
if not handler.check(user_status):
|
||||||
|
continue
|
||||||
|
|
||||||
|
args = (self.client, user_status)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -207,6 +214,14 @@ class Dispatcher:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
elif isinstance(update, types.UpdateUserStatus):
|
||||||
|
self.dispatch(
|
||||||
|
pyrogram.Update(
|
||||||
|
user_status=utils.parse_user_status(
|
||||||
|
update.status, update.user_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -48,6 +48,10 @@ class BaseClient:
|
|||||||
UPDATES_WORKERS = 1
|
UPDATES_WORKERS = 1
|
||||||
DOWNLOAD_WORKERS = 4
|
DOWNLOAD_WORKERS = 4
|
||||||
OFFLINE_SLEEP = 300
|
OFFLINE_SLEEP = 300
|
||||||
|
WORKERS = 4
|
||||||
|
WORKDIR = "."
|
||||||
|
CONFIG_FILE = "./config.ini"
|
||||||
|
PLUGINS_DIR = "./plugins"
|
||||||
|
|
||||||
MEDIA_TYPE_ID = {
|
MEDIA_TYPE_ID = {
|
||||||
0: "thumbnail",
|
0: "thumbnail",
|
||||||
|
@ -141,6 +141,30 @@ def parse_chat_photo(photo):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_user_status(user_status, user_id: int = None, is_bot: bool = False) -> pyrogram_types.UserStatus or None:
|
||||||
|
if is_bot:
|
||||||
|
return None
|
||||||
|
|
||||||
|
status = pyrogram_types.UserStatus(user_id)
|
||||||
|
|
||||||
|
if isinstance(user_status, types.UserStatusOnline):
|
||||||
|
status.online = True
|
||||||
|
status.date = user_status.expires
|
||||||
|
elif isinstance(user_status, types.UserStatusOffline):
|
||||||
|
status.offline = True
|
||||||
|
status.date = user_status.was_online
|
||||||
|
elif isinstance(user_status, types.UserStatusRecently):
|
||||||
|
status.recently = True
|
||||||
|
elif isinstance(user_status, types.UserStatusLastWeek):
|
||||||
|
status.within_week = True
|
||||||
|
elif isinstance(user_status, types.UserStatusLastMonth):
|
||||||
|
status.within_month = True
|
||||||
|
else:
|
||||||
|
status.long_time_ago = True
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
|
||||||
def parse_user(user: types.User) -> pyrogram_types.User or None:
|
def parse_user(user: types.User) -> pyrogram_types.User or None:
|
||||||
return pyrogram_types.User(
|
return pyrogram_types.User(
|
||||||
id=user.id,
|
id=user.id,
|
||||||
@ -154,7 +178,8 @@ def parse_user(user: types.User) -> pyrogram_types.User or None:
|
|||||||
username=user.username,
|
username=user.username,
|
||||||
language_code=user.lang_code,
|
language_code=user.lang_code,
|
||||||
phone_number=user.phone,
|
phone_number=user.phone,
|
||||||
photo=parse_chat_photo(user.photo)
|
photo=parse_chat_photo(user.photo),
|
||||||
|
status=parse_user_status(user.status, is_bot=user.bot),
|
||||||
) if user else None
|
) if user else None
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ class Filters:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def command(command: str or list,
|
def command(command: str or list,
|
||||||
prefix: str = "/",
|
prefix: str or list = "/",
|
||||||
separator: str = " ",
|
separator: str = " ",
|
||||||
case_sensitive: bool = False):
|
case_sensitive: bool = False):
|
||||||
"""Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
|
"""Filter commands, i.e.: text messages starting with "/" or any other custom prefix.
|
||||||
@ -180,9 +180,9 @@ class Filters:
|
|||||||
a command arrives, the command itself and its arguments will be stored in the *command*
|
a command arrives, the command itself and its arguments will be stored in the *command*
|
||||||
field of the :class:`Message <pyrogram.Message>`.
|
field of the :class:`Message <pyrogram.Message>`.
|
||||||
|
|
||||||
prefix (``str``, *optional*):
|
prefix (``str`` | ``list``, *optional*):
|
||||||
The command prefix. Defaults to "/" (slash).
|
A prefix or a list of prefixes as string the filter should look for.
|
||||||
Examples: /start, .help, !settings.
|
Defaults to "/" (slash). Examples: ".", "!", ["/", "!", "."].
|
||||||
|
|
||||||
separator (``str``, *optional*):
|
separator (``str``, *optional*):
|
||||||
The command arguments separator. Defaults to " " (white space).
|
The command arguments separator. Defaults to " " (white space).
|
||||||
@ -194,11 +194,14 @@ class Filters:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def f(_, m):
|
def f(_, m):
|
||||||
if m.text and m.text.startswith(_.p):
|
if m.text:
|
||||||
|
for i in _.p:
|
||||||
|
if m.text.startswith(i):
|
||||||
t = m.text.split(_.s)
|
t = m.text.split(_.s)
|
||||||
c, a = t[0][len(_.p):], t[1:]
|
c, a = t[0][len(i):], t[1:]
|
||||||
c = c if _.cs else c.lower()
|
c = c if _.cs else c.lower()
|
||||||
m.command = ([c] + a) if c in _.c else None
|
m.command = ([c] + a) if c in _.c else None
|
||||||
|
break
|
||||||
|
|
||||||
return bool(m.command)
|
return bool(m.command)
|
||||||
|
|
||||||
@ -211,7 +214,7 @@ class Filters:
|
|||||||
else {c if case_sensitive
|
else {c if case_sensitive
|
||||||
else c.lower()
|
else c.lower()
|
||||||
for c in command},
|
for c in command},
|
||||||
p=prefix,
|
p=set(prefix),
|
||||||
s=separator,
|
s=separator,
|
||||||
cs=case_sensitive
|
cs=case_sensitive
|
||||||
)
|
)
|
||||||
|
@ -21,3 +21,4 @@ from .deleted_messages_handler import DeletedMessagesHandler
|
|||||||
from .disconnect_handler import DisconnectHandler
|
from .disconnect_handler import DisconnectHandler
|
||||||
from .message_handler import MessageHandler
|
from .message_handler import MessageHandler
|
||||||
from .raw_update_handler import RawUpdateHandler
|
from .raw_update_handler import RawUpdateHandler
|
||||||
|
from .user_status_handler import UserStatusHandler
|
||||||
|
54
pyrogram/client/handlers/user_status_handler.py
Normal file
54
pyrogram/client/handlers/user_status_handler.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from .handler import Handler
|
||||||
|
|
||||||
|
|
||||||
|
class UserStatusHandler(Handler):
|
||||||
|
"""The UserStatus handler class. Used to handle user status updates (user going online or offline).
|
||||||
|
It is intended to be used with :meth:`add_handler() <pyrogram.Client.add_handler>`
|
||||||
|
|
||||||
|
For a nicer way to register this handler, have a look at the
|
||||||
|
:meth:`on_user_status() <pyrogram.Client.on_user_status>` decorator.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
callback (``callable``):
|
||||||
|
Pass a function that will be called when a new UserStatus update arrives. It takes *(client, user_status)*
|
||||||
|
as positional arguments (look at the section below for a detailed description).
|
||||||
|
|
||||||
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
Pass one or more filters to allow only a subset of messages to be passed
|
||||||
|
in your callback function.
|
||||||
|
|
||||||
|
Other parameters:
|
||||||
|
client (:obj:`Client <pyrogram.Client>`):
|
||||||
|
The Client itself, useful when you want to call other API methods inside the user status handler.
|
||||||
|
|
||||||
|
user_status (:obj:`UserStatus <pyrogram.UserStatus>`):
|
||||||
|
The received UserStatus update.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, callback: callable, filters=None):
|
||||||
|
super().__init__(callback, filters)
|
||||||
|
|
||||||
|
def check(self, user_status):
|
||||||
|
return (
|
||||||
|
self.filters(user_status)
|
||||||
|
if callable(self.filters)
|
||||||
|
else True
|
||||||
|
)
|
@ -21,7 +21,15 @@ from .on_deleted_messages import OnDeletedMessages
|
|||||||
from .on_disconnect import OnDisconnect
|
from .on_disconnect import OnDisconnect
|
||||||
from .on_message import OnMessage
|
from .on_message import OnMessage
|
||||||
from .on_raw_update import OnRawUpdate
|
from .on_raw_update import OnRawUpdate
|
||||||
|
from .on_user_status import OnUserStatus
|
||||||
|
|
||||||
|
|
||||||
class Decorators(OnMessage, OnDeletedMessages, OnCallbackQuery, OnRawUpdate, OnDisconnect):
|
class Decorators(
|
||||||
|
OnMessage,
|
||||||
|
OnDeletedMessages,
|
||||||
|
OnCallbackQuery,
|
||||||
|
OnRawUpdate,
|
||||||
|
OnDisconnect,
|
||||||
|
OnUserStatus
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
from pyrogram.client.filters.filter import Filter
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +37,14 @@ class OnCallbackQuery(BaseClient):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
self.add_handler(pyrogram.CallbackQueryHandler(func, filters), group)
|
handler = pyrogram.CallbackQueryHandler(func, filters)
|
||||||
return func
|
|
||||||
|
if isinstance(self, Filter):
|
||||||
|
return pyrogram.CallbackQueryHandler(func, self), group if filters is None else filters
|
||||||
|
|
||||||
|
if self is not None:
|
||||||
|
self.add_handler(handler, group)
|
||||||
|
|
||||||
|
return handler, group
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
from pyrogram.client.filters.filter import Filter
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
@ -36,7 +37,14 @@ class OnDeletedMessages(BaseClient):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
self.add_handler(pyrogram.DeletedMessagesHandler(func, filters), group)
|
handler = pyrogram.DeletedMessagesHandler(func, filters)
|
||||||
return func
|
|
||||||
|
if isinstance(self, Filter):
|
||||||
|
return pyrogram.DeletedMessagesHandler(func, self), group if filters is None else filters
|
||||||
|
|
||||||
|
if self is not None:
|
||||||
|
self.add_handler(handler, group)
|
||||||
|
|
||||||
|
return handler, group
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -28,7 +28,11 @@ class OnDisconnect(BaseClient):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
self.add_handler(pyrogram.DisconnectHandler(func))
|
handler = pyrogram.DisconnectHandler(func)
|
||||||
return func
|
|
||||||
|
if self is not None:
|
||||||
|
self.add_handler(handler)
|
||||||
|
|
||||||
|
return handler
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import pyrogram
|
import pyrogram
|
||||||
|
from pyrogram.client.filters.filter import Filter
|
||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class OnMessage(BaseClient):
|
class OnMessage(BaseClient):
|
||||||
def on_message(self, filters=None, group: int = 0):
|
def on_message(self=None, filters=None, group: int = 0):
|
||||||
"""Use this decorator to automatically register a function for handling
|
"""Use this decorator to automatically register a function for handling
|
||||||
messages. This does the same thing as :meth:`add_handler` using the
|
messages. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`MessageHandler`.
|
:class:`MessageHandler`.
|
||||||
@ -36,7 +37,14 @@ class OnMessage(BaseClient):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
self.add_handler(pyrogram.MessageHandler(func, filters), group)
|
handler = pyrogram.MessageHandler(func, filters)
|
||||||
return func
|
|
||||||
|
if isinstance(self, Filter):
|
||||||
|
return pyrogram.MessageHandler(func, self), group if filters is None else filters
|
||||||
|
|
||||||
|
if self is not None:
|
||||||
|
self.add_handler(handler, group)
|
||||||
|
|
||||||
|
return handler, group
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
@ -21,7 +21,7 @@ from ...ext import BaseClient
|
|||||||
|
|
||||||
|
|
||||||
class OnRawUpdate(BaseClient):
|
class OnRawUpdate(BaseClient):
|
||||||
def on_raw_update(self, group: int = 0):
|
def on_raw_update(self=None, group: int = 0):
|
||||||
"""Use this decorator to automatically register a function for handling
|
"""Use this decorator to automatically register a function for handling
|
||||||
raw updates. This does the same thing as :meth:`add_handler` using the
|
raw updates. This does the same thing as :meth:`add_handler` using the
|
||||||
:class:`RawUpdateHandler`.
|
:class:`RawUpdateHandler`.
|
||||||
@ -32,7 +32,14 @@ class OnRawUpdate(BaseClient):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
self.add_handler(pyrogram.RawUpdateHandler(func), group)
|
handler = pyrogram.RawUpdateHandler(func)
|
||||||
return func
|
|
||||||
|
if isinstance(self, int):
|
||||||
|
return handler, group if self is None else group
|
||||||
|
|
||||||
|
if self is not None:
|
||||||
|
self.add_handler(handler, group)
|
||||||
|
|
||||||
|
return handler, group
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
41
pyrogram/client/methods/decorators/on_user_status.py
Normal file
41
pyrogram/client/methods/decorators/on_user_status.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import pyrogram
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class OnUserStatus(BaseClient):
|
||||||
|
def on_user_status(self, filters=None, group: int = 0):
|
||||||
|
"""Use this decorator to automatically register a function for handling
|
||||||
|
user status updates. This does the same thing as :meth:`add_handler` using the
|
||||||
|
:class:`UserStatusHandler`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filters (:obj:`Filters <pyrogram.Filters>`):
|
||||||
|
Pass one or more filters to allow only a subset of UserStatus updated to be passed in your function.
|
||||||
|
|
||||||
|
group (``int``, *optional*):
|
||||||
|
The group identifier, defaults to 0.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
self.add_handler(pyrogram.UserStatusHandler(func, filters), group)
|
||||||
|
return func
|
||||||
|
|
||||||
|
return decorator
|
@ -16,15 +16,17 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from .delete_profile_photos import DeleteProfilePhotos
|
from .delete_user_profile_photos import DeleteUserProfilePhotos
|
||||||
from .get_me import GetMe
|
from .get_me import GetMe
|
||||||
from .get_user_profile_photos import GetUserProfilePhotos
|
from .get_user_profile_photos import GetUserProfilePhotos
|
||||||
from .get_users import GetUsers
|
from .get_users import GetUsers
|
||||||
|
from .set_user_profile_photo import SetUserProfilePhoto
|
||||||
|
|
||||||
|
|
||||||
class Users(
|
class Users(
|
||||||
GetUserProfilePhotos,
|
GetUserProfilePhotos,
|
||||||
DeleteProfilePhotos,
|
SetUserProfilePhoto,
|
||||||
|
DeleteUserProfilePhotos,
|
||||||
GetUsers,
|
GetUsers,
|
||||||
GetMe
|
GetMe
|
||||||
):
|
):
|
||||||
|
@ -23,8 +23,8 @@ from pyrogram.api import functions, types
|
|||||||
from ...ext import BaseClient
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
class DeleteProfilePhotos(BaseClient):
|
class DeleteUserProfilePhotos(BaseClient):
|
||||||
async def delete_profile_photos(self, id: str or list):
|
async def delete_user_profile_photos(self, id: str or list):
|
||||||
"""Use this method to delete your own profile photos
|
"""Use this method to delete your own profile photos
|
||||||
|
|
||||||
Args:
|
Args:
|
48
pyrogram/client/methods/users/set_user_profile_photo.py
Normal file
48
pyrogram/client/methods/users/set_user_profile_photo.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from pyrogram.api import functions
|
||||||
|
from ...ext import BaseClient
|
||||||
|
|
||||||
|
|
||||||
|
class SetUserProfilePhoto(BaseClient):
|
||||||
|
def set_user_profile_photo(self, photo: str):
|
||||||
|
"""Use this method to set a new profile photo.
|
||||||
|
|
||||||
|
This method only works for Users.
|
||||||
|
Bots profile photos must be set using BotFather.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
photo (``str``):
|
||||||
|
Profile photo to set.
|
||||||
|
Pass a file path as string to upload a new photo that exists on your local machine.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True on success.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
:class:`Error <pyrogram.Error>`
|
||||||
|
"""
|
||||||
|
|
||||||
|
return bool(
|
||||||
|
self.send(
|
||||||
|
functions.photos.UploadProfilePhoto(
|
||||||
|
self.save_file(photo)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
@ -36,5 +36,5 @@ from .messages_and_media import (
|
|||||||
from .update import Update
|
from .update import Update
|
||||||
from .user_and_chats import (
|
from .user_and_chats import (
|
||||||
Chat, ChatMember, ChatMembers, ChatPhoto,
|
Chat, ChatMember, ChatMembers, ChatPhoto,
|
||||||
Dialog, Dialogs, User
|
Dialog, Dialogs, User, UserStatus
|
||||||
)
|
)
|
||||||
|
@ -58,6 +58,9 @@ class Update(Object):
|
|||||||
|
|
||||||
pre_checkout_query (:obj:`PreCheckoutQuery <pyrogram.PreCheckoutQuery>`, *optional*):
|
pre_checkout_query (:obj:`PreCheckoutQuery <pyrogram.PreCheckoutQuery>`, *optional*):
|
||||||
New incoming pre-checkout query. Contains full information about checkout.
|
New incoming pre-checkout query. Contains full information about checkout.
|
||||||
|
|
||||||
|
user_status (:obj:`UserStatus <pyrogram.UserStatus>`, *optional*):
|
||||||
|
User status (last seen date) update.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ID = 0xb0700000
|
ID = 0xb0700000
|
||||||
@ -74,7 +77,8 @@ class Update(Object):
|
|||||||
chosen_inline_result=None,
|
chosen_inline_result=None,
|
||||||
callback_query=None,
|
callback_query=None,
|
||||||
shipping_query=None,
|
shipping_query=None,
|
||||||
pre_checkout_query=None
|
pre_checkout_query=None,
|
||||||
|
user_status=None
|
||||||
):
|
):
|
||||||
self.message = message
|
self.message = message
|
||||||
self.edited_message = edited_message
|
self.edited_message = edited_message
|
||||||
@ -87,3 +91,4 @@ class Update(Object):
|
|||||||
self.callback_query = callback_query
|
self.callback_query = callback_query
|
||||||
self.shipping_query = shipping_query
|
self.shipping_query = shipping_query
|
||||||
self.pre_checkout_query = pre_checkout_query
|
self.pre_checkout_query = pre_checkout_query
|
||||||
|
self.user_status = user_status
|
||||||
|
@ -22,4 +22,5 @@ from .chat_members import ChatMembers
|
|||||||
from .chat_photo import ChatPhoto
|
from .chat_photo import ChatPhoto
|
||||||
from .dialog import Dialog
|
from .dialog import Dialog
|
||||||
from .dialogs import Dialogs
|
from .dialogs import Dialogs
|
||||||
|
from .user_status import UserStatus
|
||||||
from .user import User
|
from .user import User
|
||||||
|
@ -41,6 +41,9 @@ class User(Object):
|
|||||||
is_bot (``bool``):
|
is_bot (``bool``):
|
||||||
True, if this user is a bot.
|
True, if this user is a bot.
|
||||||
|
|
||||||
|
status (:obj:`UserStatus <pyrogram.UserStatus>`):
|
||||||
|
User's Last Seen status. Empty for bots.
|
||||||
|
|
||||||
first_name (``str``):
|
first_name (``str``):
|
||||||
User's or bot's first name.
|
User's or bot's first name.
|
||||||
|
|
||||||
@ -70,6 +73,7 @@ class User(Object):
|
|||||||
is_mutual_contact: bool,
|
is_mutual_contact: bool,
|
||||||
is_deleted: bool,
|
is_deleted: bool,
|
||||||
is_bot: bool,
|
is_bot: bool,
|
||||||
|
status,
|
||||||
first_name: str,
|
first_name: str,
|
||||||
last_name: str = None,
|
last_name: str = None,
|
||||||
username: str = None,
|
username: str = None,
|
||||||
@ -83,6 +87,7 @@ class User(Object):
|
|||||||
self.is_mutual_contact = is_mutual_contact
|
self.is_mutual_contact = is_mutual_contact
|
||||||
self.is_deleted = is_deleted
|
self.is_deleted = is_deleted
|
||||||
self.is_bot = is_bot
|
self.is_bot = is_bot
|
||||||
|
self.status = status
|
||||||
self.first_name = first_name
|
self.first_name = first_name
|
||||||
self.last_name = last_name
|
self.last_name = last_name
|
||||||
self.username = username
|
self.username = username
|
||||||
|
84
pyrogram/client/types/user_and_chats/user_status.py
Normal file
84
pyrogram/client/types/user_and_chats/user_status.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# Pyrogram - Telegram MTProto API Client Library for Python
|
||||||
|
# Copyright (C) 2017-2018 Dan Tès <https://github.com/delivrance>
|
||||||
|
#
|
||||||
|
# This file is part of Pyrogram.
|
||||||
|
#
|
||||||
|
# Pyrogram is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Pyrogram is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Lesser General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from pyrogram.api.core import Object
|
||||||
|
|
||||||
|
|
||||||
|
class UserStatus(Object):
|
||||||
|
"""This object represents a User status (Last Seen privacy)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You won't see exact last seen timestamps for people with whom you don't share your own. Instead, you get
|
||||||
|
"recently", "within_week", "within_month" or "long_time_ago" fields set.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user_id (``int``):
|
||||||
|
User's id. Only available for UserStatus updates.
|
||||||
|
|
||||||
|
online (``bool``):
|
||||||
|
True if the user is online in this moment, None otherwise.
|
||||||
|
If True, the "date" field will be also set containing the online expiration date (i.e.: the date when a
|
||||||
|
user will automatically go offline in case of no action by his client).
|
||||||
|
|
||||||
|
offline (``bool``):
|
||||||
|
True if the user is offline and has the Last Seen privacy setting visible for everybody, None otherwise.
|
||||||
|
If True, the "date" field will be also set containing the last seen date (i.e.: the date when a user
|
||||||
|
was online the last time).
|
||||||
|
|
||||||
|
date (``int``):
|
||||||
|
Exact date in unix time. Available only in case "online" or "offline" equals to True.
|
||||||
|
|
||||||
|
recently (``bool``):
|
||||||
|
True for users with hidden Last Seen privacy that have been online between 1 second and 2-3 days ago,
|
||||||
|
None otherwise.
|
||||||
|
|
||||||
|
within_week (``bool``):
|
||||||
|
True for users with hidden Last Seen privacy that have been online between 2-3 and seven days ago,
|
||||||
|
None otherwise.
|
||||||
|
|
||||||
|
within_month (``bool``):
|
||||||
|
True for users with hidden Last Seen privacy that have been online between 6-7 days and a month ago,
|
||||||
|
None otherwise.
|
||||||
|
|
||||||
|
long_time_ago (``bool``):
|
||||||
|
True for users with hidden Last Seen privacy that have been online more than a month ago (this is also
|
||||||
|
always shown to blocked users), None otherwise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
ID = 0xb0700031
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
user_id: int = None,
|
||||||
|
online: bool = None,
|
||||||
|
offline: bool = None,
|
||||||
|
date: int = None,
|
||||||
|
recently: bool = None,
|
||||||
|
within_week: bool = None,
|
||||||
|
within_month: bool = None,
|
||||||
|
long_time_ago: bool = None
|
||||||
|
):
|
||||||
|
self.user_id = user_id
|
||||||
|
self.online = online
|
||||||
|
self.offline = offline
|
||||||
|
self.date = date
|
||||||
|
self.recently = recently
|
||||||
|
self.within_week = within_week
|
||||||
|
self.within_month = within_month
|
||||||
|
self.long_time_ago = long_time_ago
|
Loading…
Reference in New Issue
Block a user