Revisit documentation, cross-references and unnecessary indents

This commit is contained in:
Lonami Exo
2018-06-20 11:05:33 +02:00
parent 1b7e7320a4
commit c85ba4accc
20 changed files with 651 additions and 522 deletions

View File

@@ -24,15 +24,15 @@ Once that's ready, the next step is to create a ``TelegramClient``.
This class will be your main interface with Telegram's API, and creating
one is very simple:
.. code-block:: python
.. code-block:: python
from telethon import TelegramClient
from telethon import TelegramClient
# Use your own values here
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
# Use your own values here
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('some_name', api_id, api_hash)
client = TelegramClient('some_name', api_id, api_hash)
Note that ``'some_name'`` will be used to save your session (persistent
@@ -46,26 +46,44 @@ 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.
.. 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.
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
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
.. code-block:: python
If you're not authorized, you need to `.sign_in
<telethon.client.auth.AuthMethods.sign_in>`:
phone_number = '+34600000000'
client.send_code_request(phone_number)
myself = client.sign_in(phone_number, input('Enter code: '))
# If .sign_in raises PhoneNumberUnoccupiedError, use .sign_up instead
# If .sign_in raises SessionPasswordNeeded error, call .sign_in(password=...)
# You can import both exceptions from telethon.errors.
.. code-block:: python
phone_number = '+34600000000'
client.send_code_request(phone_number)
myself = client.sign_in(phone_number, input('Enter code: '))
# If .sign_in raises PhoneNumberUnoccupiedError, use .sign_up instead
# If .sign_in raises SessionPasswordNeeded error, call .sign_in(password=...)
# You can import both exceptions from telethon.errors.
.. note::
@@ -82,24 +100,26 @@ mentioned ``.stringify()`` method, and printing these might prove useful.
As a full example:
.. code-block:: python
.. code-block:: python
client = TelegramClient('anon', api_id, api_hash)
assert client.connect()
if not client.is_user_authorized():
client.send_code_request(phone_number)
me = client.sign_in(phone_number, input('Enter code: '))
client = TelegramClient('anon', api_id, api_hash)
assert client.connect()
if not client.is_user_authorized():
client.send_code_request(phone_number)
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
client = TelegramClient('anon', api_id, api_hash)
client.start()
client = TelegramClient('anon', api_id, api_hash)
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
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
@@ -108,25 +128,27 @@ method also accepts a ``phone=`` and ``bot_token`` parameters.
You can use either, as both will work. Determining which
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::
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
receive a ``FloodWaitError`` of around 22 hours, so be careful not to mess
this up! This shouldn't happen if you're doing things as explained, though.
parameter of the :ref:`TelegramClient <telethon-client>`, which is the session
name) you will receive a ``FloodWaitError`` of around 22 hours, so be
careful not to mess this up! This shouldn't happen if you're doing things
as explained, though.
.. note::
If you want to use a **proxy**, you have to `install PySocks`__
(via pip or manual) and then set the appropriated parameters:
.. code-block:: python
.. code-block:: python
import socks
client = TelegramClient('session_id',
api_id=12345, api_hash='0123456789abcdef0123456789abcdef',
proxy=(socks.SOCKS5, 'localhost', 4444)
)
import socks
client = TelegramClient('session_id',
api_id=12345, api_hash='0123456789abcdef0123456789abcdef',
proxy=(socks.SOCKS5, 'localhost', 4444)
)
The ``proxy=`` argument should be a tuple, a list or a dict,
consisting of parameters described `here`__.
@@ -137,64 +159,69 @@ Two Factor Authorization (2FA)
******************************
If you have Two Factor Authorization (from now on, 2FA) enabled on your
account, calling :meth:`telethon.TelegramClient.sign_in` will raise a
``SessionPasswordNeededError``. When this happens, just
:meth:`telethon.TelegramClient.sign_in` again with a ``password=``:
account, calling `.sign_in()
<telethon.client.auth.AuthMethods.sign_in>` will raise a
``SessionPasswordNeededError``. When this happens, just use the method
again with a ``password=``:
.. code-block:: python
.. code-block:: python
import getpass
from telethon.errors import SessionPasswordNeededError
import getpass
from telethon.errors import SessionPasswordNeededError
client.sign_in(phone)
try:
client.sign_in(code=input('Enter code: '))
except SessionPasswordNeededError:
client.sign_in(password=getpass.getpass())
client.sign_in(phone)
try:
client.sign_in(code=input('Enter code: '))
except SessionPasswordNeededError:
client.sign_in(password=getpass.getpass())
The mentioned ``.start()`` method will handle this for you as well, but
you must set the ``password=`` parameter beforehand (it won't be asked).
The mentioned `.start()
<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
you won't run into any problems.
Take note that if you want to set only the email/hint and leave
the current password unchanged, you need to "redo" the 2fa.
you won't run into any problems. Take note that if you want to
set only the email/hint and leave the current password unchanged,
you need to "redo" the 2fa.
See the examples below:
.. code-block:: python
.. code-block:: python
from telethon.errors import EmailUnconfirmedError
# Sets 2FA password for first time:
client.edit_2fa(new_password='supersecurepassword')
# Changes password:
client.edit_2fa(current_password='supersecurepassword',
new_password='changedmymind')
# Clears current password (i.e. removes 2FA):
client.edit_2fa(current_password='changedmymind', new_password=None)
# Sets new password with recovery email:
try:
client.edit_2fa(new_password='memes and dreams',
email='JohnSmith@example.com')
# Raises error (you need to check your email to complete 2FA setup.)
except EmailUnconfirmedError:
# You can put email checking code here if desired.
pass
# Also take note that unless you remove 2FA or explicitly
# give email parameter again it will keep the last used setting
# Set hint after already setting password:
client.edit_2fa(current_password='memes and dreams',
new_password='memes and dreams',
hint='It keeps you alive')
from telethon.errors import EmailUnconfirmedError
# Sets 2FA password for first time:
client.edit_2fa(new_password='supersecurepassword')
# Changes password:
client.edit_2fa(current_password='supersecurepassword',
new_password='changedmymind')
# Clears current password (i.e. removes 2FA):
client.edit_2fa(current_password='changedmymind', new_password=None)
# Sets new password with recovery email:
try:
client.edit_2fa(new_password='memes and dreams',
email='JohnSmith@example.com')
# Raises error (you need to check your email to complete 2FA setup.)
except EmailUnconfirmedError:
# You can put email checking code here if desired.
pass
# Also take note that unless you remove 2FA or explicitly
# give email parameter again it will keep the last used setting
# Set hint after already setting password:
client.edit_2fa(current_password='memes and dreams',
new_password='memes and dreams',
hint='It keeps you alive')
__ https://github.com/Anorov/PySocks#installation
__ https://github.com/Anorov/PySocks#usage-1

View File

@@ -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
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
`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
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))
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.
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.
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
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,
or the entity retrieved by other means like ``.get_dialogs()``.
don't call `client.get_entity() <telethon.client.users.UserMethods.get_entity>`
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
@@ -108,21 +112,27 @@ before you can "use them".
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,
``.get_input_entity()`` is available. This will always use the cache while
possible, making zero API calls most of the time. When a request is made,
if you provided the full entity, e.g. an :tl:`User`, the library will convert
it to the required :tl:`InputPeer` automatically for you.
`client.get_input_entity() <telethon.client.users.UserMethods.get_input_entity>`
is available. This will always use the cache while possible, making zero API
calls most of the time. When a request is made, if you provided the full
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
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.
of the entity.
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
``.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

View File

@@ -9,83 +9,85 @@ Getting Started
Simple Installation
*******************
``pip3 install telethon``
.. code-block:: sh
**More details**: :ref:`installation`
pip3 install telethon
**More details**: :ref:`installation`
Creating a client
*****************
.. code-block:: python
.. code-block:: python
from telethon import TelegramClient
from telethon import TelegramClient
# These example values won't work. You must get your own api_id and
# api_hash from https://my.telegram.org, under API Development.
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
# These example values won't work. You must get your own api_id and
# api_hash from https://my.telegram.org, under API Development.
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('session_name', api_id, api_hash)
client.start()
client = TelegramClient('session_name', api_id, api_hash)
client.start()
**More details**: :ref:`creating-a-client`
**More details**: :ref:`creating-a-client`
Basic Usage
***********
.. code-block:: python
.. code-block:: python
# Getting information about yourself
print(client.get_me().stringify())
# Getting information about yourself
print(client.get_me().stringify())
# Sending a message (you can use 'me' or 'self' to message yourself)
client.send_message('username', 'Hello World from Telethon!')
# Sending a message (you can use 'me' or 'self' to message yourself)
client.send_message('username', 'Hello World from Telethon!')
# Sending a file
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
# Sending a file
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
# Retrieving messages from a chat
from telethon import utils
for message in client.iter_messages('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Retrieving messages from a chat
from telethon import utils
for message in client.iter_messages('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Listing all the dialogs (conversations you have open)
for dialog in client.get_dialogs(limit=10):
print(utils.get_display_name(dialog.entity), dialog.draft.text)
# Listing all the dialogs (conversations you have open)
for dialog in client.get_dialogs(limit=10):
print(utils.get_display_name(dialog.entity), dialog.draft.text)
# Downloading profile photos (default path is the working directory)
client.download_profile_photo('username')
# Downloading profile photos (default path is the working directory)
client.download_profile_photo('username')
# Once you have a message with .media (if message.media)
# you can download it using client.download_media():
messages = client.get_messages('username')
client.download_media(messages[0])
# Once you have a message with .media (if message.media)
# you can download it using client.download_media():
messages = client.get_messages('username')
client.download_media(messages[0])
**More details**: :ref:`telegram-client`
**More details**: :ref:`telegram-client`
See :ref:`telethon-client` for all available friendly methods.
See :ref:`telethon-client` for all available friendly methods.
Handling Updates
****************
.. code-block:: python
.. code-block:: python
from telethon import events
from telethon import events
# We need to have some worker running
client.updates.workers = 1
# We need to have some worker running
client.updates.workers = 1
@client.on(events.NewMessage(incoming=True, pattern='(?i)hi'))
def handler(event):
event.reply('Hello!')
@client.on(events.NewMessage(incoming=True, pattern='(?i)hi'))
def handler(event):
event.reply('Hello!')
# If you want to handle updates you can't let the script end.
input('Press enter to exit.')
# If you want to handle updates you can't let the script end.
input('Press enter to exit.')
**More details**: :ref:`working-with-updates`
**More details**: :ref:`working-with-updates`
----------

View File

@@ -10,24 +10,28 @@ Automatic Installation
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.
See https://python.org and https://pypi.python.org/pypi/pip for more.
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:
.. code-block:: sh
.. code-block:: sh
# pip3 install git+https://github.com/LonamiWebs/Telethon.git
or
$ git clone https://github.com/LonamiWebs/Telethon.git
$ cd Telethon/
# pip install -Ue .
# pip3 install git+https://github.com/LonamiWebs/Telethon.git
or
$ git clone https://github.com/LonamiWebs/Telethon.git
$ cd Telethon/
# pip install -Ue .
If you don't have root access, simply pass the ``--user`` flag to the pip
command. If you want to install a specific branch, append ``@branch`` to
@@ -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>`__
via ``pip`` or as an extra:
``pip3 install telethon[cryptg]``
.. code-block:: sh
pip3 install telethon[cryptg]
Manual Installation
@@ -47,14 +53,27 @@ Manual Installation
1. Install the required ``pyaes`` (`GitHub`__ | `PyPi`__) and
``rsa`` (`GitHub`__ | `PyPi`__) modules:
``sudo -H pip3 install pyaes rsa``
.. code-block:: sh
pip3 install pyaes rsa
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!

View File

@@ -15,9 +15,9 @@ Introduction
available methods are in the :ref:`telethon-client` reference, including
detailed descriptions to what they do.
The ``TelegramClient`` is the central class of the library, the one
you will be using most of the time. For this reason, it's important
to know what it offers.
The :ref:`TelegramClient <telethon-client>` is the
central class of the library, the one you will be using most of the time. For
this reason, it's important to know what it offers.
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
@@ -27,12 +27,14 @@ methods for any object, even yours!
Interacting with the Telegram API is done through sending **requests**,
this is, any "method" listed on the API. There are a few methods (and
growing!) on the ``TelegramClient`` class that abstract you from the
need of manually importing the requests you need.
growing!) on the :ref:`TelegramClient <telethon-client>` class that abstract
you from the need of manually importing the requests you need.
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
the information about your own user, and then the desired information
@@ -42,12 +44,12 @@ If you want to retrieve any other user, chat or channel (channels are a
special subset of chats), you want to retrieve their "entity". This is
how the library refers to either of these:
.. code-block:: python
.. code-block:: python
# The method will infer that you've passed an username
# It also accepts phone numbers, and will get the user
# from your contact list.
lonami = client.get_entity('lonami')
# The method will infer that you've passed an username
# It also accepts phone numbers, and will get the user
# from your contact list.
lonami = client.get_entity('lonami')
The so called "entities" are another important whole concept on its own,
but for now you don't need to worry about it. Simply know that they are
@@ -55,32 +57,32 @@ a good way to get information about an user, chat or channel.
Many other common methods for quick scripts are also available:
.. code-block:: python
.. code-block:: python
# Note that you can use 'me' or 'self' to message yourself
client.send_message('username', 'Hello World from Telethon!')
# Note that you can use 'me' or 'self' to message yourself
client.send_message('username', 'Hello World from Telethon!')
# .send_message's parse mode defaults to markdown, so you
# can use **bold**, __italics__, [links](https://example.com), `code`,
# and even [mentions](@username)/[mentions](tg://user?id=123456789)
client.send_message('username', '**Using** __markdown__ `too`!')
# .send_message's parse mode defaults to markdown, so you
# can use **bold**, __italics__, [links](https://example.com), `code`,
# and even [mentions](@username)/[mentions](tg://user?id=123456789)
client.send_message('username', '**Using** __markdown__ `too`!')
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
# The utils package has some goodies, like .get_display_name()
from telethon import utils
for message in client.iter_messages('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# The utils package has some goodies, like .get_display_name()
from telethon import utils
for message in client.iter_messages('username', limit=10):
print(utils.get_display_name(message.sender), message.message)
# Dialogs are the conversations you have open
for dialog in client.get_dialogs(limit=10):
print(utils.get_display_name(dialog.entity), dialog.draft.text)
# Dialogs are the conversations you have open
for dialog in client.get_dialogs(limit=10):
print(utils.get_display_name(dialog.entity), dialog.draft.text)
# Default path is the working directory
client.download_profile_photo('username')
# Default path is the working directory
client.download_profile_photo('username')
# Call .disconnect() when you're done
client.disconnect()
# Call .disconnect() when you're done
client.disconnect()
Remember that you can call ``.stringify()`` to any object Telegram returns
to pretty print it. Calling ``str(result)`` does the same operation, but on
@@ -91,9 +93,9 @@ Available methods
*****************
The :ref:`reference <telethon-package>` lists all the "handy" methods
available for you to use in the ``TelegramClient`` class. These are simply
wrappers around the "raw" Telegram API, making it much more manageable and
easier to work with.
available for you to use in the :ref:`TelegramClient <telethon-client>` class.
These are simply wrappers around the "raw" Telegram API, making it much more
manageable and easier to work with.
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_

View File

@@ -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
usage when dealing with them, since there are many updates. If you're looking
for the method reference, check :ref:`telethon-events-package`, otherwise,
let's dive in!
.. note::
.. important::
The library logs by default no output, and any exception that occurs
inside your handlers will be "hidden" from you to prevent the thread
from terminating (so it can still deliver events). You should enable
logging (``import logging; logging.basicConfig(level=logging.ERROR)``)
when working with events, at least the error level, to see if this is
happening so you can debug the error.
logging when working with events, at least the error level, to see if
this is happening so you can debug the error.
**When using updates, please enable logging:**
.. code-block:: python
import logging
logging.basicConfig(level=logging.ERROR)
.. contents::
@@ -62,7 +68,8 @@ Nothing we don't know already.
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:
.. code-block:: python
@@ -72,8 +79,10 @@ the callback function you're about to define will be called:
event.reply('hi!')
If a ``NewMessage`` event occurs, and ``'hello'`` is in the text of the
message, we ``reply`` to the event with a ``'hi!'`` message.
If a `NewMessage
<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
@@ -88,10 +97,11 @@ do other things instead idling. For this refer to :ref:`update-modes`.
More on events
**************
The ``NewMessage`` event has much more than what was shown. You can access
the ``.sender`` of the message through that member, or even see if the message
had ``.media``, a ``.photo`` or a ``.document`` (which you could download with
for example ``client.download_media(event.photo)``.
The `NewMessage <telethon.events.newmessage.NewMessage>` event has much
more than what was shown. You can access the ``.sender`` of the message
through that member, or even see if the message had ``.media``, a ``.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()``
method instead. Of course, there are more events such as ``ChatAction`` or
@@ -102,34 +112,35 @@ instance, ``NewMessage.Event``), except for the ``Raw`` event which just
passes the ``Update`` object.
Note that ``.reply()`` and ``.respond()`` are just wrappers around the
``client.send_message()`` method which supports the ``file=`` parameter.
This means you can reply with a photo if you do ``client.reply(file=photo)``.
`client.send_message() <telethon.client.messages.MessageMethods.send_message>`
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
the same handler. You can also have a handler work on only specific chats,
for example:
.. code-block:: python
.. code-block:: python
import ast
import random
import ast
import random
# Either a single item or a list of them will work for the chats.
# You can also use the IDs, Peers, or even User/Chat/Channel objects.
@client.on(events.NewMessage(chats=('TelethonChat', 'TelethonOffTopic')))
def normal_handler(event):
if 'roll' in event.raw_text:
event.reply(str(random.randint(1, 6)))
# Either a single item or a list of them will work for the chats.
# You can also use the IDs, Peers, or even User/Chat/Channel objects.
@client.on(events.NewMessage(chats=('TelethonChat', 'TelethonOffTopic')))
def normal_handler(event):
if 'roll' in event.raw_text:
event.reply(str(random.randint(1, 6)))
# Similarly, you can use incoming=True for messages that you receive
@client.on(events.NewMessage(chats='TelethonOffTopic', outgoing=True))
def admin_handler(event):
if event.raw_text.startswith('eval'):
expression = event.raw_text.replace('eval', '').strip()
event.reply(str(ast.literal_eval(expression)))
# Similarly, you can use incoming=True for messages that you receive
@client.on(events.NewMessage(chats='TelethonOffTopic', outgoing=True))
def admin_handler(event):
if event.raw_text.startswith('eval'):
expression = event.raw_text.replace('eval', '').strip()
event.reply(str(ast.literal_eval(expression)))
You can pass one or more chats to the ``chats`` parameter (as a list or tuple),
@@ -143,15 +154,20 @@ solution. Try it!
Events without decorators
*************************
If for any reason you can't use the ``@client.on`` syntax, don't worry.
You can call ``client.add_event_handler(callback, event)`` to achieve
If for any reason you can't use the `@client.on
<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.
Similar to that method, you also have :meth:`client.remove_event_handler`
and :meth:`client.list_event_handlers` which do as they names indicate.
Similarly, you also have `client.remove_event_handler
<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``
for adding, and ``None`` when removing (so all callbacks would be removed).
The ``event`` type is optional in all methods and defaults to
`events.Raw <telethon.events.raw.Raw>` for adding, and ``None`` when
removing (so all callbacks would be removed).
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
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
propagation of the update through your handlers to stop:
it is possible to raise a `telethon.events.StopPropagation` exception which
will cause the propagation of the update through your handlers to stop:
.. code-block:: python