mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-29 12:53:44 +03:00
Revisit documentation, cross-references and unnecessary indents
This commit is contained in:
parent
1b7e7320a4
commit
c85ba4accc
|
@ -11,11 +11,11 @@ Accessing the Full API
|
||||||
reason not to, like a method not existing or you wanting more control.
|
reason not to, like a method not existing or you wanting more control.
|
||||||
|
|
||||||
|
|
||||||
The `telethon.telegram_client.TelegramClient` doesn't offer a method for every
|
The :ref:`TelegramClient <telethon-client>` doesn't offer a method for
|
||||||
single request the Telegram API supports. However, it's very simple to *call*
|
every single request the Telegram API supports. However, it's very simple to
|
||||||
or *invoke* any request. Whenever you need something, don't forget to `check
|
*call* or *invoke* any request. Whenever you need something, don't forget to
|
||||||
the documentation`__ and look for the `method you need`__. There you can go
|
`check the documentation`__ and look for the `method you need`__. There you
|
||||||
through a sorted list of everything you can do.
|
can go through a sorted list of everything you can do.
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -30,7 +30,8 @@ You should also refer to the documentation to see what the objects
|
||||||
(constructors) Telegram returns look like. Every constructor inherits
|
(constructors) Telegram returns look like. Every constructor inherits
|
||||||
from a common type, and that's the reason for this distinction.
|
from a common type, and that's the reason for this distinction.
|
||||||
|
|
||||||
Say `telethon.telegram_client.TelegramClient.send_message` didn't exist,
|
Say `client.send_message
|
||||||
|
<telethon.client.messages.MessageMethods.send_message>` didn't exist,
|
||||||
we could use the `search`__ to look for "message". There we would find
|
we could use the `search`__ to look for "message". There we would find
|
||||||
:tl:`SendMessageRequest`, which we can work with.
|
:tl:`SendMessageRequest`, which we can work with.
|
||||||
|
|
||||||
|
@ -63,7 +64,8 @@ construct one, for instance:
|
||||||
|
|
||||||
peer = InputPeerUser(user_id, user_hash)
|
peer = InputPeerUser(user_id, user_hash)
|
||||||
|
|
||||||
Or we call `telethon.telegram_client.TelegramClient.get_input_entity()`:
|
Or we call `client.get_input_entity
|
||||||
|
<telethon.client.users.UserMethods.get_input_entity>`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -71,10 +73,11 @@ Or we call `telethon.telegram_client.TelegramClient.get_input_entity()`:
|
||||||
|
|
||||||
When you're going to invoke an API method, most require you to pass an
|
When you're going to invoke an API method, most require you to pass an
|
||||||
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
|
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
|
||||||
``.get_input_entity()`` is more straightforward (and often
|
`client.get_input_entity <telethon.client.users.UserMethods.get_input_entity>`
|
||||||
immediate, if you've seen the user before, know their ID, etc.).
|
is more straightforward (and often immediate, if you've seen the user before,
|
||||||
If you also need to have information about the whole user, use
|
know their ID, etc.). If you also **need** to have information about the whole
|
||||||
`telethon.telegram_client.TelegramClient.get_entity()` instead:
|
user, use `client.get_entity <telethon.client.users.UserMethods.get_entity>`
|
||||||
|
instead:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -94,12 +97,15 @@ every time its used, simply call `telethon.utils.get_input_peer`:
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Since ``v0.16.2`` this is further simplified. The ``Request`` itself
|
Since ``v0.16.2`` this is further simplified. The ``Request`` itself
|
||||||
will call ``client.get_input_entity()`` for you when required, but
|
will call `client.get_input_entity <
|
||||||
it's good to remember what's happening.
|
telethon.client.users.UserMethods.get_input_entity>` for you when required,
|
||||||
|
but it's good to remember what's happening.
|
||||||
|
|
||||||
|
|
||||||
After this small parenthesis about ``.get_entity`` versus
|
After this small parenthesis about `client.get_entity
|
||||||
``.get_input_entity``, we have everything we need. To ``.invoke()`` our
|
<telethon.client.users.UserMethods.get_entity>` versus
|
||||||
|
`client.get_input_entity <telethon.client.users.UserMethods.get_input_entity>`,
|
||||||
|
we have everything we need. To invoke our
|
||||||
request we do:
|
request we do:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
Session Files
|
Session Files
|
||||||
==============
|
==============
|
||||||
|
|
||||||
The first parameter you pass to the constructor of the ``TelegramClient`` is
|
The first parameter you pass to the constructor of the
|
||||||
|
:ref:`TelegramClient <telethon-client>` is
|
||||||
the ``session``, and defaults to be the session name (or full path). That is,
|
the ``session``, and defaults to be the session name (or full path). That is,
|
||||||
if you create a ``TelegramClient('anon')`` instance and connect, an
|
if you create a ``TelegramClient('anon')`` instance and connect, an
|
||||||
``anon.session`` file will be created in the working directory.
|
``anon.session`` file will be created in the working directory.
|
||||||
|
@ -42,7 +43,8 @@ If you don't want to use the default SQLite session storage, you can also use
|
||||||
one of the other implementations or implement your own storage.
|
one of the other implementations or implement your own storage.
|
||||||
|
|
||||||
To use a custom session storage, simply pass the custom session instance to
|
To use a custom session storage, simply pass the custom session instance to
|
||||||
``TelegramClient`` instead of the session name.
|
:ref:`TelegramClient <telethon-client>` instead of
|
||||||
|
the session name.
|
||||||
|
|
||||||
Telethon contains two implementations of the abstract ``Session`` class:
|
Telethon contains two implementations of the abstract ``Session`` class:
|
||||||
|
|
||||||
|
|
|
@ -46,17 +46,35 @@ your disk. This is by default a database file using Python's ``sqlite3``.
|
||||||
creates the file in your working directory, but absolute paths work too.
|
creates the file in your working directory, but absolute paths work too.
|
||||||
|
|
||||||
|
|
||||||
|
.. important::
|
||||||
|
|
||||||
|
The process shown here shows how to sign in *manually*. You **should**
|
||||||
|
use `client.start() <telethon.client.auth.AuthMethods.start>` instead
|
||||||
|
unless you have a better reason not to (e.g. you need more control):
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
client.start()
|
||||||
|
|
||||||
|
This is explained after going through the manual process.
|
||||||
|
|
||||||
|
|
||||||
Before using the client, you must be connected to Telegram.
|
Before using the client, you must be connected to Telegram.
|
||||||
Doing so is very easy:
|
Doing so is very easy:
|
||||||
|
|
||||||
``client.connect() # Must return True, otherwise, try again``
|
.. code-block:: python
|
||||||
|
|
||||||
|
client.connect() # Must return True, otherwise, try again
|
||||||
|
|
||||||
You may or may not be authorized yet. You must be authorized
|
You may or may not be authorized yet. You must be authorized
|
||||||
before you're able to send any request:
|
before you're able to send any request:
|
||||||
|
|
||||||
``client.is_user_authorized() # Returns True if you can send requests``
|
.. code-block:: python
|
||||||
|
|
||||||
If you're not authorized, you need to ``.sign_in()``:
|
client.is_user_authorized() # Returns True if you can send requests
|
||||||
|
|
||||||
|
If you're not authorized, you need to `.sign_in
|
||||||
|
<telethon.client.auth.AuthMethods.sign_in>`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -91,7 +109,8 @@ As a full example:
|
||||||
me = client.sign_in(phone_number, input('Enter code: '))
|
me = client.sign_in(phone_number, input('Enter code: '))
|
||||||
|
|
||||||
|
|
||||||
All of this, however, can be done through a call to ``.start()``:
|
All of this, however, can be done through a call to `.start()
|
||||||
|
<telethon.client.auth.AuthMethods.start>`:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -99,7 +118,8 @@ All of this, however, can be done through a call to ``.start()``:
|
||||||
client.start()
|
client.start()
|
||||||
|
|
||||||
|
|
||||||
The code shown is just what ``.start()`` will be doing behind the scenes
|
The code shown is just what `.start()
|
||||||
|
<telethon.client.auth.AuthMethods.start>` will be doing behind the scenes
|
||||||
(with a few extra checks), so that you know how to sign in case you want
|
(with a few extra checks), so that you know how to sign in case you want
|
||||||
to avoid using ``input()`` (the default) for whatever reason. If no phone
|
to avoid using ``input()`` (the default) for whatever reason. If no phone
|
||||||
or bot token is provided, you will be asked one through ``input()``. The
|
or bot token is provided, you will be asked one through ``input()``. The
|
||||||
|
@ -108,13 +128,15 @@ method also accepts a ``phone=`` and ``bot_token`` parameters.
|
||||||
You can use either, as both will work. Determining which
|
You can use either, as both will work. Determining which
|
||||||
is just a matter of taste, and how much control you need.
|
is just a matter of taste, and how much control you need.
|
||||||
|
|
||||||
Remember that you can get yourself at any time with ``client.get_me()``.
|
Remember that you can get yourself at any time with `client.get_me()
|
||||||
|
<telethon.client.users.UserMethods.get_me>`.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
Please note that if you fail to login around 5 times (or change the first
|
Please note that if you fail to login around 5 times (or change the first
|
||||||
parameter of the ``TelegramClient``, which is the session name) you will
|
parameter of the :ref:`TelegramClient <telethon-client>`, which is the session
|
||||||
receive a ``FloodWaitError`` of around 22 hours, so be careful not to mess
|
name) you will receive a ``FloodWaitError`` of around 22 hours, so be
|
||||||
this up! This shouldn't happen if you're doing things as explained, though.
|
careful not to mess this up! This shouldn't happen if you're doing things
|
||||||
|
as explained, though.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
If you want to use a **proxy**, you have to `install PySocks`__
|
If you want to use a **proxy**, you have to `install PySocks`__
|
||||||
|
@ -137,9 +159,10 @@ Two Factor Authorization (2FA)
|
||||||
******************************
|
******************************
|
||||||
|
|
||||||
If you have Two Factor Authorization (from now on, 2FA) enabled on your
|
If you have Two Factor Authorization (from now on, 2FA) enabled on your
|
||||||
account, calling :meth:`telethon.TelegramClient.sign_in` will raise a
|
account, calling `.sign_in()
|
||||||
``SessionPasswordNeededError``. When this happens, just
|
<telethon.client.auth.AuthMethods.sign_in>` will raise a
|
||||||
:meth:`telethon.TelegramClient.sign_in` again with a ``password=``:
|
``SessionPasswordNeededError``. When this happens, just use the method
|
||||||
|
again with a ``password=``:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -153,15 +176,19 @@ account, calling :meth:`telethon.TelegramClient.sign_in` will raise a
|
||||||
client.sign_in(password=getpass.getpass())
|
client.sign_in(password=getpass.getpass())
|
||||||
|
|
||||||
|
|
||||||
The mentioned ``.start()`` method will handle this for you as well, but
|
The mentioned `.start()
|
||||||
you must set the ``password=`` parameter beforehand (it won't be asked).
|
<telethon.client.auth.AuthMethods.start>` method will handle this for you as
|
||||||
|
well, but you must set the ``password=`` parameter beforehand (it won't be
|
||||||
|
asked).
|
||||||
|
|
||||||
|
If you don't have 2FA enabled, but you would like to do so through the
|
||||||
|
library, use `client.edit_2fa()
|
||||||
|
<telethon.client.auth.AuthMethods.edit_2fa>`.
|
||||||
|
|
||||||
If you don't have 2FA enabled, but you would like to do so through the library,
|
|
||||||
use ``client.edit_2fa()``.
|
|
||||||
Be sure to know what you're doing when using this function and
|
Be sure to know what you're doing when using this function and
|
||||||
you won't run into any problems.
|
you won't run into any problems. Take note that if you want to
|
||||||
Take note that if you want to set only the email/hint and leave
|
set only the email/hint and leave the current password unchanged,
|
||||||
the current password unchanged, you need to "redo" the 2fa.
|
you need to "redo" the 2fa.
|
||||||
|
|
||||||
See the examples below:
|
See the examples below:
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ in response to certain methods, such as :tl:`GetUsersRequest`.
|
||||||
|
|
||||||
To "encounter" an ID, you would have to "find it" like you would in the
|
To "encounter" an ID, you would have to "find it" like you would in the
|
||||||
normal app. If the peer is in your dialogs, you would need to
|
normal app. If the peer is in your dialogs, you would need to
|
||||||
`client.get_dialogs() <telethon.telegram_client.TelegramClient.get_dialogs>`.
|
`client.get_dialogs() <telethon.client.dialogs.DialogMethods.get_dialogs>`.
|
||||||
If the peer is someone in a group, you would similarly
|
If the peer is someone in a group, you would similarly
|
||||||
`client.get_participants(group) <telethon.telegram_client.TelegramClient.get_participants>`.
|
`client.get_participants(group) <telethon.client.chats.ChatMethods.get_participants>`.
|
||||||
|
|
||||||
Once you have encountered an ID, the library will (by default) have saved
|
Once you have encountered an ID, the library will (by default) have saved
|
||||||
their ``access_hash`` for you, which is needed to invoke most methods.
|
their ``access_hash`` for you, which is needed to invoke most methods.
|
||||||
|
@ -69,9 +69,11 @@ you're able to just do this:
|
||||||
my_channel = client.get_entity(PeerChannel(some_id))
|
my_channel = client.get_entity(PeerChannel(some_id))
|
||||||
|
|
||||||
|
|
||||||
All methods in the :ref:`telegram-client` call ``.get_input_entity()`` prior
|
All methods in the :ref:`telegram-client` call `.get_input_entity()
|
||||||
|
<telethon.client.users.UserMethods.get_input_entity>` prior
|
||||||
to sending the requst to save you from the hassle of doing so manually.
|
to sending the requst to save you from the hassle of doing so manually.
|
||||||
That way, convenience calls such as ``client.send_message('lonami', 'hi!')``
|
That way, convenience calls such as `client.send_message('lonami', 'hi!')
|
||||||
|
<telethon.client.messages.MessageMethods.send_message>`
|
||||||
become possible.
|
become possible.
|
||||||
|
|
||||||
Every entity the library encounters (in any response to any call) will by
|
Every entity the library encounters (in any response to any call) will by
|
||||||
|
@ -88,8 +90,10 @@ Entities vs. Input Entities
|
||||||
|
|
||||||
Don't worry if you don't understand this section, just remember some
|
Don't worry if you don't understand this section, just remember some
|
||||||
of the details listed here are important. When you're calling a method,
|
of the details listed here are important. When you're calling a method,
|
||||||
don't call ``.get_entity()`` beforehand, just use the username or phone,
|
don't call `client.get_entity() <telethon.client.users.UserMethods.get_entity>`
|
||||||
or the entity retrieved by other means like ``.get_dialogs()``.
|
beforehand, just use the username or phone, or the entity retrieved by
|
||||||
|
other means like `client.get_dialogs()
|
||||||
|
<telethon.client.dialogs.DialogMethods.get_dialogs>`.
|
||||||
|
|
||||||
|
|
||||||
On top of the normal types, the API also make use of what they call their
|
On top of the normal types, the API also make use of what they call their
|
||||||
|
@ -108,21 +112,27 @@ before you can "use them".
|
||||||
|
|
||||||
As we just mentioned, API calls don't need to know the whole information
|
As we just mentioned, API calls don't need to know the whole information
|
||||||
about the entities, only their ID and hash. For this reason, another method,
|
about the entities, only their ID and hash. For this reason, another method,
|
||||||
``.get_input_entity()`` is available. This will always use the cache while
|
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
|
||||||
possible, making zero API calls most of the time. When a request is made,
|
is available. This will always use the cache while possible, making zero API
|
||||||
if you provided the full entity, e.g. an :tl:`User`, the library will convert
|
calls most of the time. When a request is made, if you provided the full
|
||||||
it to the required :tl:`InputPeer` automatically for you.
|
entity, e.g. an :tl:`User`, the library will convert it to the required
|
||||||
|
:tl:`InputPeer` automatically for you.
|
||||||
|
|
||||||
**You should always favour** ``.get_input_entity()`` **over** ``.get_entity()``
|
**You should always favour**
|
||||||
|
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
|
||||||
|
**over**
|
||||||
|
`client.get_entity() <telethon.client.users.UserMethods.get_entity>`
|
||||||
for this reason! Calling the latter will always make an API call to get
|
for this reason! Calling the latter will always make an API call to get
|
||||||
the most recent information about said entity, but invoking requests don't
|
the most recent information about said entity, but invoking requests don't
|
||||||
need this information, just the ``InputPeer``. Only use ``.get_entity()``
|
need this information, just the :tl:`InputPeer`. Only use
|
||||||
|
`client.get_entity() <telethon.client.users.UserMethods.get_entity>`
|
||||||
if you need to get actual information, like the username, name, title, etc.
|
if you need to get actual information, like the username, name, title, etc.
|
||||||
of the entity.
|
of the entity.
|
||||||
|
|
||||||
To further simplify the workflow, since the version ``0.16.2`` of the
|
To further simplify the workflow, since the version ``0.16.2`` of the
|
||||||
library, the raw requests you make to the API are also able to call
|
library, the raw requests you make to the API are also able to call
|
||||||
``.get_input_entity`` wherever needed, so you can even do things like:
|
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
|
||||||
|
wherever needed, so you can even do things like:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ Getting Started
|
||||||
Simple Installation
|
Simple Installation
|
||||||
*******************
|
*******************
|
||||||
|
|
||||||
``pip3 install telethon``
|
.. code-block:: sh
|
||||||
|
|
||||||
|
pip3 install telethon
|
||||||
|
|
||||||
**More details**: :ref:`installation`
|
**More details**: :ref:`installation`
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,18 @@ Automatic Installation
|
||||||
|
|
||||||
To install Telethon, simply do:
|
To install Telethon, simply do:
|
||||||
|
|
||||||
``pip3 install telethon``
|
.. code-block:: sh
|
||||||
|
|
||||||
|
pip3 install telethon
|
||||||
|
|
||||||
Needless to say, you must have Python 3 and PyPi installed in your system.
|
Needless to say, you must have Python 3 and PyPi installed in your system.
|
||||||
See https://python.org and https://pypi.python.org/pypi/pip for more.
|
See https://python.org and https://pypi.python.org/pypi/pip for more.
|
||||||
|
|
||||||
If you already have the library installed, upgrade with:
|
If you already have the library installed, upgrade with:
|
||||||
|
|
||||||
``pip3 install --upgrade telethon``
|
.. code-block:: sh
|
||||||
|
|
||||||
|
pip3 install --upgrade telethon
|
||||||
|
|
||||||
You can also install the library directly from GitHub or a fork:
|
You can also install the library directly from GitHub or a fork:
|
||||||
|
|
||||||
|
@ -38,7 +42,9 @@ which can be really slow when uploading or downloading files. If you don't
|
||||||
mind using a C extension, install `cryptg <https://github.com/Lonami/cryptg>`__
|
mind using a C extension, install `cryptg <https://github.com/Lonami/cryptg>`__
|
||||||
via ``pip`` or as an extra:
|
via ``pip`` or as an extra:
|
||||||
|
|
||||||
``pip3 install telethon[cryptg]``
|
.. code-block:: sh
|
||||||
|
|
||||||
|
pip3 install telethon[cryptg]
|
||||||
|
|
||||||
|
|
||||||
Manual Installation
|
Manual Installation
|
||||||
|
@ -47,14 +53,27 @@ Manual Installation
|
||||||
1. Install the required ``pyaes`` (`GitHub`__ | `PyPi`__) and
|
1. Install the required ``pyaes`` (`GitHub`__ | `PyPi`__) and
|
||||||
``rsa`` (`GitHub`__ | `PyPi`__) modules:
|
``rsa`` (`GitHub`__ | `PyPi`__) modules:
|
||||||
|
|
||||||
``sudo -H pip3 install pyaes rsa``
|
.. code-block:: sh
|
||||||
|
|
||||||
|
pip3 install pyaes rsa
|
||||||
|
|
||||||
2. Clone Telethon's GitHub repository:
|
2. Clone Telethon's GitHub repository:
|
||||||
``git clone https://github.com/LonamiWebs/Telethon.git``
|
|
||||||
|
|
||||||
3. Enter the cloned repository: ``cd Telethon``
|
.. code-block:: sh
|
||||||
|
|
||||||
4. Run the code generator: ``python3 setup.py gen tl errors``
|
git clone https://github.com/LonamiWebs/Telethon.git
|
||||||
|
|
||||||
|
3. Enter the cloned repository:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
cd Telethon
|
||||||
|
|
||||||
|
4. Run the code generator:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
python3 setup.py gen
|
||||||
|
|
||||||
5. Done!
|
5. Done!
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@ Introduction
|
||||||
available methods are in the :ref:`telethon-client` reference, including
|
available methods are in the :ref:`telethon-client` reference, including
|
||||||
detailed descriptions to what they do.
|
detailed descriptions to what they do.
|
||||||
|
|
||||||
The ``TelegramClient`` is the central class of the library, the one
|
The :ref:`TelegramClient <telethon-client>` is the
|
||||||
you will be using most of the time. For this reason, it's important
|
central class of the library, the one you will be using most of the time. For
|
||||||
to know what it offers.
|
this reason, it's important to know what it offers.
|
||||||
|
|
||||||
Since we're working with Python, one must not forget that we can do
|
Since we're working with Python, one must not forget that we can do
|
||||||
``help(client)`` or ``help(TelegramClient)`` at any time for a more
|
``help(client)`` or ``help(TelegramClient)`` at any time for a more
|
||||||
|
@ -27,12 +27,14 @@ methods for any object, even yours!
|
||||||
|
|
||||||
Interacting with the Telegram API is done through sending **requests**,
|
Interacting with the Telegram API is done through sending **requests**,
|
||||||
this is, any "method" listed on the API. There are a few methods (and
|
this is, any "method" listed on the API. There are a few methods (and
|
||||||
growing!) on the ``TelegramClient`` class that abstract you from the
|
growing!) on the :ref:`TelegramClient <telethon-client>` class that abstract
|
||||||
need of manually importing the requests you need.
|
you from the need of manually importing the requests you need.
|
||||||
|
|
||||||
For instance, retrieving your own user can be done in a single line:
|
For instance, retrieving your own user can be done in a single line:
|
||||||
|
|
||||||
``myself = client.get_me()``
|
.. code-block:: python
|
||||||
|
|
||||||
|
myself = client.get_me()
|
||||||
|
|
||||||
Internally, this method has sent a request to Telegram, who replied with
|
Internally, this method has sent a request to Telegram, who replied with
|
||||||
the information about your own user, and then the desired information
|
the information about your own user, and then the desired information
|
||||||
|
@ -91,9 +93,9 @@ Available methods
|
||||||
*****************
|
*****************
|
||||||
|
|
||||||
The :ref:`reference <telethon-package>` lists all the "handy" methods
|
The :ref:`reference <telethon-package>` lists all the "handy" methods
|
||||||
available for you to use in the ``TelegramClient`` class. These are simply
|
available for you to use in the :ref:`TelegramClient <telethon-client>` class.
|
||||||
wrappers around the "raw" Telegram API, making it much more manageable and
|
These are simply wrappers around the "raw" Telegram API, making it much more
|
||||||
easier to work with.
|
manageable and easier to work with.
|
||||||
|
|
||||||
Please refer to :ref:`accessing-the-full-api` if these aren't enough,
|
Please refer to :ref:`accessing-the-full-api` if these aren't enough,
|
||||||
and don't be afraid to read the source code of the InteractiveTelegramClient_
|
and don't be afraid to read the source code of the InteractiveTelegramClient_
|
||||||
|
|
|
@ -5,21 +5,27 @@ Working with Updates
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
|
||||||
The library comes with the :mod:`events` module. *Events* are an abstraction
|
The library comes with the `telethon.events` module. *Events* are an abstraction
|
||||||
over what Telegram calls `updates`__, and are meant to ease simple and common
|
over what Telegram calls `updates`__, and are meant to ease simple and common
|
||||||
usage when dealing with them, since there are many updates. If you're looking
|
usage when dealing with them, since there are many updates. If you're looking
|
||||||
for the method reference, check :ref:`telethon-events-package`, otherwise,
|
for the method reference, check :ref:`telethon-events-package`, otherwise,
|
||||||
let's dive in!
|
let's dive in!
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. important::
|
||||||
|
|
||||||
The library logs by default no output, and any exception that occurs
|
The library logs by default no output, and any exception that occurs
|
||||||
inside your handlers will be "hidden" from you to prevent the thread
|
inside your handlers will be "hidden" from you to prevent the thread
|
||||||
from terminating (so it can still deliver events). You should enable
|
from terminating (so it can still deliver events). You should enable
|
||||||
logging (``import logging; logging.basicConfig(level=logging.ERROR)``)
|
logging when working with events, at least the error level, to see if
|
||||||
when working with events, at least the error level, to see if this is
|
this is happening so you can debug the error.
|
||||||
happening so you can debug the error.
|
|
||||||
|
**When using updates, please enable logging:**
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import logging
|
||||||
|
logging.basicConfig(level=logging.ERROR)
|
||||||
|
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
@ -62,7 +68,8 @@ Nothing we don't know already.
|
||||||
|
|
||||||
|
|
||||||
This Python decorator will attach itself to the ``my_event_handler``
|
This Python decorator will attach itself to the ``my_event_handler``
|
||||||
definition, and basically means that *on* a ``NewMessage`` *event*,
|
definition, and basically means that *on* a `NewMessage
|
||||||
|
<telethon.events.newmessage.NewMessage>` *event*,
|
||||||
the callback function you're about to define will be called:
|
the callback function you're about to define will be called:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -72,8 +79,10 @@ the callback function you're about to define will be called:
|
||||||
event.reply('hi!')
|
event.reply('hi!')
|
||||||
|
|
||||||
|
|
||||||
If a ``NewMessage`` event occurs, and ``'hello'`` is in the text of the
|
If a `NewMessage
|
||||||
message, we ``reply`` to the event with a ``'hi!'`` message.
|
<telethon.events.newmessage.NewMessage>` event occurs,
|
||||||
|
and ``'hello'`` is in the text of the message, we ``reply`` to the event
|
||||||
|
with a ``'hi!'`` message.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -88,10 +97,11 @@ do other things instead idling. For this refer to :ref:`update-modes`.
|
||||||
More on events
|
More on events
|
||||||
**************
|
**************
|
||||||
|
|
||||||
The ``NewMessage`` event has much more than what was shown. You can access
|
The `NewMessage <telethon.events.newmessage.NewMessage>` event has much
|
||||||
the ``.sender`` of the message through that member, or even see if the message
|
more than what was shown. You can access the ``.sender`` of the message
|
||||||
had ``.media``, a ``.photo`` or a ``.document`` (which you could download with
|
through that member, or even see if the message had ``.media``, a ``.photo``
|
||||||
for example ``client.download_media(event.photo)``.
|
or a ``.document`` (which you could download with for example
|
||||||
|
`client.download_media(event.photo) <telethon.client.downloads.DownloadMethods.download_media>`.
|
||||||
|
|
||||||
If you don't want to ``.reply`` as a reply, you can use the ``.respond()``
|
If you don't want to ``.reply`` as a reply, you can use the ``.respond()``
|
||||||
method instead. Of course, there are more events such as ``ChatAction`` or
|
method instead. Of course, there are more events such as ``ChatAction`` or
|
||||||
|
@ -102,8 +112,9 @@ instance, ``NewMessage.Event``), except for the ``Raw`` event which just
|
||||||
passes the ``Update`` object.
|
passes the ``Update`` object.
|
||||||
|
|
||||||
Note that ``.reply()`` and ``.respond()`` are just wrappers around the
|
Note that ``.reply()`` and ``.respond()`` are just wrappers around the
|
||||||
``client.send_message()`` method which supports the ``file=`` parameter.
|
`client.send_message() <telethon.client.messages.MessageMethods.send_message>`
|
||||||
This means you can reply with a photo if you do ``client.reply(file=photo)``.
|
method which supports the ``file=`` parameter.
|
||||||
|
This means you can reply with a photo if you do ``event.reply(file=photo)``.
|
||||||
|
|
||||||
You can put the same event on many handlers, and even different events on
|
You can put the same event on many handlers, and even different events on
|
||||||
the same handler. You can also have a handler work on only specific chats,
|
the same handler. You can also have a handler work on only specific chats,
|
||||||
|
@ -143,15 +154,20 @@ solution. Try it!
|
||||||
Events without decorators
|
Events without decorators
|
||||||
*************************
|
*************************
|
||||||
|
|
||||||
If for any reason you can't use the ``@client.on`` syntax, don't worry.
|
If for any reason you can't use the `@client.on
|
||||||
You can call ``client.add_event_handler(callback, event)`` to achieve
|
<telethon.client.updates.UpdateMethods.on>` syntax, don't worry.
|
||||||
|
You can call `client.add_event_handler(callback, event)
|
||||||
|
<telethon.client.updates.UpdateMethods.add_event_handler>` to achieve
|
||||||
the same effect.
|
the same effect.
|
||||||
|
|
||||||
Similar to that method, you also have :meth:`client.remove_event_handler`
|
Similarly, you also have `client.remove_event_handler
|
||||||
and :meth:`client.list_event_handlers` which do as they names indicate.
|
<telethon.client.updates.UpdateMethods.remove_event_handler>`
|
||||||
|
and `client.list_event_handlers
|
||||||
|
<telethon.client.updates.UpdateMethods.list_event_handlers>`.
|
||||||
|
|
||||||
The ``event`` type is optional in all methods and defaults to ``events.Raw``
|
The ``event`` type is optional in all methods and defaults to
|
||||||
for adding, and ``None`` when removing (so all callbacks would be removed).
|
`events.Raw <telethon.events.raw.Raw>` for adding, and ``None`` when
|
||||||
|
removing (so all callbacks would be removed).
|
||||||
|
|
||||||
|
|
||||||
Stopping propagation of Updates
|
Stopping propagation of Updates
|
||||||
|
@ -159,8 +175,8 @@ Stopping propagation of Updates
|
||||||
|
|
||||||
There might be cases when an event handler is supposed to be used solitary and
|
There might be cases when an event handler is supposed to be used solitary and
|
||||||
it makes no sense to process any other handlers in the chain. For this case,
|
it makes no sense to process any other handlers in the chain. For this case,
|
||||||
it is possible to raise a ``StopPropagation`` exception which will cause the
|
it is possible to raise a `telethon.events.StopPropagation` exception which
|
||||||
propagation of the update through your handlers to stop:
|
will cause the propagation of the update through your handlers to stop:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
|
|
@ -12,27 +12,32 @@ that servers as a nice interface with the most commonly used methods on
|
||||||
Telegram such as sending messages, retrieving the message history,
|
Telegram such as sending messages, retrieving the message history,
|
||||||
handling updates, etc.
|
handling updates, etc.
|
||||||
|
|
||||||
The ``TelegramClient`` inherits the ``TelegramBareClient``. The later is
|
The ``TelegramClient`` inherits from several mixing ``Method`` classes,
|
||||||
basically a pruned version of the ``TelegramClient``, which knows basic
|
since there are so many methods that having them in a single file would
|
||||||
stuff like ``.invoke()``\ 'ing requests, downloading files, or switching
|
make maintenance painful (it was three thousand lines before this separation
|
||||||
between data centers. This is primary to keep the method count per class
|
happened!). It's a "god object", but there is only a way to interact with
|
||||||
and file low and manageable.
|
Telegram really.
|
||||||
|
|
||||||
Both clients make use of the ``network/mtproto_sender.py``. The
|
The ``TelegramBaseClient`` is an ABC which will support all of these mixins
|
||||||
``MtProtoSender`` class handles packing requests with the ``salt``,
|
so they can work together nicely. It doesn't even know how to invoke things
|
||||||
``id``, ``sequence``, etc., and also handles how to process responses
|
because they need to be resolved with user information first (to work with
|
||||||
(i.e. pong, RPC errors). This class communicates through Telegram via
|
input entities comfortably).
|
||||||
its ``.connection`` member.
|
|
||||||
|
|
||||||
The ``Connection`` class uses a ``extensions/tcp_client``, a C#-like
|
The client makes use of the ``network/mtprotosender.py``. The
|
||||||
``TcpClient`` to ease working with sockets in Python. All the
|
``MTProtoSender`` is responsible for connecting, reconnecting,
|
||||||
|
packing, unpacking, sending and receiving items from the network.
|
||||||
|
Basically, the low-level communication with Telegram, and handling
|
||||||
|
MTProto-related functions and types such as ``BadSalt``.
|
||||||
|
|
||||||
|
The sender makes use of a ``Connection`` class which knows the format in
|
||||||
|
which outgoing messages should be sent (how to encode their length and
|
||||||
|
their body, if they're further encrypted).
|
||||||
|
|
||||||
|
For now, all connection modes make use of the ``extensions/tcpclient``,
|
||||||
|
a C#-like ``TcpClient`` to ease working with sockets in Python. All the
|
||||||
``TcpClient`` know is how to connect through TCP and writing/reading
|
``TcpClient`` know is how to connect through TCP and writing/reading
|
||||||
from the socket with optional cancel.
|
from the socket with optional cancel.
|
||||||
|
|
||||||
The ``Connection`` class bundles up all the connections modes and sends
|
|
||||||
and receives the messages accordingly (TCP full, obfuscated,
|
|
||||||
intermediate…).
|
|
||||||
|
|
||||||
Auto-generated code
|
Auto-generated code
|
||||||
*******************
|
*******************
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ be kind and don't forget to mention it helped you!
|
||||||
|
|
||||||
You should start by reading the source code on the `first
|
You should start by reading the source code on the `first
|
||||||
release <https://github.com/LonamiWebs/Telethon/releases/tag/v0.1>`__ of
|
release <https://github.com/LonamiWebs/Telethon/releases/tag/v0.1>`__ of
|
||||||
the project, and start creating a ``MtProtoSender``. Once this is made,
|
the project, and start creating a ``MTProtoSender``. Once this is made,
|
||||||
you should write by hand the code to authenticate on the Telegram's
|
you should write by hand the code to authenticate on the Telegram's
|
||||||
server, which are some steps required to get the key required to talk to
|
server, which are some steps required to get the key required to talk to
|
||||||
them. Save it somewhere! Then, simply mimic, or reinvent other parts of
|
them. Save it somewhere! Then, simply mimic, or reinvent other parts of
|
||||||
|
|
|
@ -31,7 +31,16 @@ class UpdateMethods(UserMethods):
|
||||||
|
|
||||||
def on(self, event):
|
def on(self, event):
|
||||||
"""
|
"""
|
||||||
Decorator helper method around add_event_handler().
|
Decorator helper method around `add_event_handler`. Example:
|
||||||
|
|
||||||
|
>>> from telethon import TelegramClient, events
|
||||||
|
>>> client = TelegramClient(...)
|
||||||
|
>>>
|
||||||
|
>>> @client.on(events.NewMessage)
|
||||||
|
... async def handler(event):
|
||||||
|
... ...
|
||||||
|
...
|
||||||
|
>>>
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
event (`_EventBuilder` | `type`):
|
event (`_EventBuilder` | `type`):
|
||||||
|
|
|
@ -82,7 +82,29 @@ class EventBuilder(abc.ABC):
|
||||||
|
|
||||||
|
|
||||||
class EventCommon(abc.ABC):
|
class EventCommon(abc.ABC):
|
||||||
"""Intermediate class with common things to all events"""
|
"""
|
||||||
|
Intermediate class with common things to all events.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
pattern_match (`obj`):
|
||||||
|
The resulting object from calling the passed ``pattern`` function.
|
||||||
|
Here's an example using a string (defaults to regex match):
|
||||||
|
|
||||||
|
>>> from telethon import TelegramClient, events
|
||||||
|
>>> client = TelegramClient(...)
|
||||||
|
>>>
|
||||||
|
>>> @client.on(events.NewMessage(pattern=r'hi (\w+)!'))
|
||||||
|
... def handler(event):
|
||||||
|
... # In this case, the result is a ``Match`` object
|
||||||
|
... # since the ``str`` pattern was converted into
|
||||||
|
... # the ``re.compile(pattern).match`` function.
|
||||||
|
... print('Welcomed', event.pattern_match.group(1))
|
||||||
|
...
|
||||||
|
>>>
|
||||||
|
|
||||||
|
original_update (:tl:`Update`):
|
||||||
|
The original Telegram update object that caused this event.
|
||||||
|
"""
|
||||||
_event_name = 'Event'
|
_event_name = 'Event'
|
||||||
|
|
||||||
def __init__(self, chat_peer=None, msg_id=None, broadcast=False):
|
def __init__(self, chat_peer=None, msg_id=None, broadcast=False):
|
||||||
|
@ -146,6 +168,9 @@ class EventCommon(abc.ABC):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def client(self):
|
def client(self):
|
||||||
|
"""
|
||||||
|
The `telethon.TelegramClient` that created this event.
|
||||||
|
"""
|
||||||
return self._client
|
return self._client
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -177,6 +177,12 @@ class Message:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
async def chat(self):
|
async def chat(self):
|
||||||
|
"""
|
||||||
|
The (:tl:`User` | :tl:`Chat` | :tl:`Channel`, optional) on which
|
||||||
|
the event occurred. This property may make an API call the first time
|
||||||
|
to get the most up to date version of the chat (mostly when the event
|
||||||
|
doesn't belong to a channel), so keep that in mind.
|
||||||
|
"""
|
||||||
if self._chat is None:
|
if self._chat is None:
|
||||||
try:
|
try:
|
||||||
self._chat =\
|
self._chat =\
|
||||||
|
|
Loading…
Reference in New Issue
Block a user