mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-22 09:26:37 +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.
|
||||
|
||||
|
||||
The `telethon.telegram_client.TelegramClient` doesn't offer a method for every
|
||||
single request the Telegram API supports. However, it's very simple to *call*
|
||||
or *invoke* any request. Whenever you need something, don't forget to `check
|
||||
the documentation`__ and look for the `method you need`__. There you can go
|
||||
through a sorted list of everything you can do.
|
||||
The :ref:`TelegramClient <telethon-client>` doesn't offer a method for
|
||||
every single request the Telegram API supports. However, it's very simple to
|
||||
*call* or *invoke* any request. Whenever you need something, don't forget to
|
||||
`check the documentation`__ and look for the `method you need`__. There you
|
||||
can go through a sorted list of everything you can do.
|
||||
|
||||
|
||||
.. 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
|
||||
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
|
||||
:tl:`SendMessageRequest`, which we can work with.
|
||||
|
||||
|
@ -39,16 +40,16 @@ to invoke it. You can also call ``help(request)`` for information on
|
|||
what input parameters it takes. Remember to "Copy import to the
|
||||
clipboard", or your script won't be aware of this class! Now we have:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import SendMessageRequest
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import SendMessageRequest
|
||||
|
||||
If you're going to use a lot of these, you may do:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl import types, functions
|
||||
# We now have access to 'functions.messages.SendMessageRequest'
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl import types, functions
|
||||
# We now have access to 'functions.messages.SendMessageRequest'
|
||||
|
||||
We see that this request must take at least two parameters, a ``peer``
|
||||
of type :tl:`InputPeer`, and a ``message`` which is just a Python
|
||||
|
@ -57,74 +58,79 @@ of type :tl:`InputPeer`, and a ``message`` which is just a Python
|
|||
How can we retrieve this :tl:`InputPeer`? We have two options. We manually
|
||||
construct one, for instance:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.types import InputPeerUser
|
||||
from telethon.tl.types import InputPeerUser
|
||||
|
||||
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
|
||||
|
||||
peer = client.get_input_entity('someone')
|
||||
peer = client.get_input_entity('someone')
|
||||
|
||||
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
|
||||
``.get_input_entity()`` is more straightforward (and often
|
||||
immediate, if you've seen the user before, know their ID, etc.).
|
||||
If you also need to have information about the whole user, use
|
||||
`telethon.telegram_client.TelegramClient.get_entity()` instead:
|
||||
`client.get_input_entity <telethon.client.users.UserMethods.get_input_entity>`
|
||||
is more straightforward (and often immediate, if you've seen the user before,
|
||||
know their ID, etc.). If you also **need** to have information about the whole
|
||||
user, use `client.get_entity <telethon.client.users.UserMethods.get_entity>`
|
||||
instead:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
entity = client.get_entity('someone')
|
||||
entity = client.get_entity('someone')
|
||||
|
||||
In the later case, when you use the entity, the library will cast it to
|
||||
its "input" version for you. If you already have the complete user and
|
||||
want to cache its input version so the library doesn't have to do this
|
||||
every time its used, simply call `telethon.utils.get_input_peer`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon import utils
|
||||
peer = utils.get_input_user(entity)
|
||||
from telethon import utils
|
||||
peer = utils.get_input_user(entity)
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Since ``v0.16.2`` this is further simplified. The ``Request`` itself
|
||||
will call ``client.get_input_entity()`` for you when required, but
|
||||
it's good to remember what's happening.
|
||||
will call `client.get_input_entity <
|
||||
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
|
||||
``.get_input_entity``, we have everything we need. To ``.invoke()`` our
|
||||
After this small parenthesis about `client.get_entity
|
||||
<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:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
result = client(SendMessageRequest(peer, 'Hello there!'))
|
||||
# __call__ is an alias for client.invoke(request). Both will work
|
||||
result = client(SendMessageRequest(peer, 'Hello there!'))
|
||||
# __call__ is an alias for client.invoke(request). Both will work
|
||||
|
||||
Message sent! Of course, this is only an example. There are nearly 250
|
||||
methods available as of layer 73, and you can use every single of them
|
||||
as you wish. Remember to use the right types! To sum up:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
result = client(SendMessageRequest(
|
||||
client.get_input_entity('username'), 'Hello there!'
|
||||
))
|
||||
result = client(SendMessageRequest(
|
||||
client.get_input_entity('username'), 'Hello there!'
|
||||
))
|
||||
|
||||
|
||||
This can further be simplified to:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
result = client(SendMessageRequest('username', 'Hello there!'))
|
||||
# Or even
|
||||
result = client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
|
||||
result = client(SendMessageRequest('username', 'Hello there!'))
|
||||
# Or even
|
||||
result = client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
|
||||
|
||||
|
||||
.. note::
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
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,
|
||||
if you create a ``TelegramClient('anon')`` instance and connect, an
|
||||
``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.
|
||||
|
||||
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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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`
|
||||
|
||||
|
||||
----------
|
||||
|
|
|
@ -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!
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
handling updates, etc.
|
||||
|
||||
The ``TelegramClient`` inherits the ``TelegramBareClient``. The later is
|
||||
basically a pruned version of the ``TelegramClient``, which knows basic
|
||||
stuff like ``.invoke()``\ 'ing requests, downloading files, or switching
|
||||
between data centers. This is primary to keep the method count per class
|
||||
and file low and manageable.
|
||||
The ``TelegramClient`` inherits from several mixing ``Method`` classes,
|
||||
since there are so many methods that having them in a single file would
|
||||
make maintenance painful (it was three thousand lines before this separation
|
||||
happened!). It's a "god object", but there is only a way to interact with
|
||||
Telegram really.
|
||||
|
||||
Both clients make use of the ``network/mtproto_sender.py``. The
|
||||
``MtProtoSender`` class handles packing requests with the ``salt``,
|
||||
``id``, ``sequence``, etc., and also handles how to process responses
|
||||
(i.e. pong, RPC errors). This class communicates through Telegram via
|
||||
its ``.connection`` member.
|
||||
The ``TelegramBaseClient`` is an ABC which will support all of these mixins
|
||||
so they can work together nicely. It doesn't even know how to invoke things
|
||||
because they need to be resolved with user information first (to work with
|
||||
input entities comfortably).
|
||||
|
||||
The ``Connection`` class uses a ``extensions/tcp_client``, a C#-like
|
||||
``TcpClient`` to ease working with sockets in Python. All the
|
||||
The client makes use of the ``network/mtprotosender.py``. 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
|
||||
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
|
||||
*******************
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ Test Servers
|
|||
|
||||
To run Telethon on a test server, use the following code:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
client = TelegramClient(None, api_id, api_hash)
|
||||
client.session.set_dc(dc_id, '149.154.167.40', 80)
|
||||
client = TelegramClient(None, api_id, api_hash)
|
||||
client.session.set_dc(dc_id, '149.154.167.40', 80)
|
||||
|
||||
You can check your ``'test ip'`` on https://my.telegram.org.
|
||||
|
||||
|
@ -28,8 +28,8 @@ Valid phone numbers are ``99966XYYYY``, where ``X`` is the ``dc_id`` and
|
|||
be ``9996621234``. The code sent by Telegram will be ``dc_id`` repeated five
|
||||
times, in this case, ``22222`` so we can hardcode that:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
client = TelegramClient(None, api_id, api_hash)
|
||||
client.session.set_dc(2, '149.154.167.40', 80)
|
||||
client.start(phone='9996621234', code_callback=lambda: '22222')
|
||||
client = TelegramClient(None, api_id, api_hash)
|
||||
client.session.set_dc(2, '149.154.167.40', 80)
|
||||
client.start(phone='9996621234', code_callback=lambda: '22222')
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -15,26 +15,26 @@ You can query an inline bot, such as `@VoteBot`__ (note, *query*,
|
|||
not *interact* with a voting message), by making use of the
|
||||
:tl:`GetInlineBotResultsRequest` request:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import GetInlineBotResultsRequest
|
||||
from telethon.tl.functions.messages import GetInlineBotResultsRequest
|
||||
|
||||
bot_results = client(GetInlineBotResultsRequest(
|
||||
bot, user_or_chat, 'query', ''
|
||||
))
|
||||
bot_results = client(GetInlineBotResultsRequest(
|
||||
bot, user_or_chat, 'query', ''
|
||||
))
|
||||
|
||||
And you can select any of their results by using
|
||||
:tl:`SendInlineBotResultRequest`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import SendInlineBotResultRequest
|
||||
from telethon.tl.functions.messages import SendInlineBotResultRequest
|
||||
|
||||
client(SendInlineBotResultRequest(
|
||||
get_input_peer(user_or_chat),
|
||||
obtained_query_id,
|
||||
obtained_str_id
|
||||
))
|
||||
client(SendInlineBotResultRequest(
|
||||
get_input_peer(user_or_chat),
|
||||
obtained_query_id,
|
||||
obtained_str_id
|
||||
))
|
||||
|
||||
|
||||
Talking to Bots with special reply markup
|
||||
|
@ -43,15 +43,15 @@ Talking to Bots with special reply markup
|
|||
To interact with a message that has a special reply markup, such as
|
||||
`@VoteBot`__ polls, you would use :tl:`GetBotCallbackAnswerRequest`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import GetBotCallbackAnswerRequest
|
||||
from telethon.tl.functions.messages import GetBotCallbackAnswerRequest
|
||||
|
||||
client(GetBotCallbackAnswerRequest(
|
||||
user_or_chat,
|
||||
msg.id,
|
||||
data=msg.reply_markup.rows[wanted_row].buttons[wanted_button].data
|
||||
))
|
||||
client(GetBotCallbackAnswerRequest(
|
||||
user_or_chat,
|
||||
msg.id,
|
||||
data=msg.reply_markup.rows[wanted_row].buttons[wanted_button].data
|
||||
))
|
||||
|
||||
It's a bit verbose, but it has all the information you would need to
|
||||
show it visually (button rows, and buttons within each row, each with
|
||||
|
|
|
@ -22,14 +22,14 @@ Joining a public channel
|
|||
Once you have the :ref:`entity <entities>` of the channel you want to join
|
||||
to, you can make use of the :tl:`JoinChannelRequest` to join such channel:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.channels import JoinChannelRequest
|
||||
client(JoinChannelRequest(channel))
|
||||
from telethon.tl.functions.channels import JoinChannelRequest
|
||||
client(JoinChannelRequest(channel))
|
||||
|
||||
# In the same way, you can also leave such channel
|
||||
from telethon.tl.functions.channels import LeaveChannelRequest
|
||||
client(LeaveChannelRequest(input_channel))
|
||||
# In the same way, you can also leave such channel
|
||||
from telethon.tl.functions.channels import LeaveChannelRequest
|
||||
client(LeaveChannelRequest(input_channel))
|
||||
|
||||
|
||||
For more on channels, check the `channels namespace`__.
|
||||
|
@ -48,10 +48,10 @@ enough information to join! The part after the
|
|||
example, is the ``hash`` of the chat or channel. Now you can use
|
||||
:tl:`ImportChatInviteRequest` as follows:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import ImportChatInviteRequest
|
||||
updates = client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
|
||||
from telethon.tl.functions.messages import ImportChatInviteRequest
|
||||
updates = client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
|
||||
|
||||
|
||||
Adding someone else to such chat or channel
|
||||
|
@ -61,26 +61,26 @@ If you don't want to add yourself, maybe because you're already in,
|
|||
you can always add someone else with the :tl:`AddChatUserRequest`, which
|
||||
use is very straightforward, or :tl:`InviteToChannelRequest` for channels:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
# For normal chats
|
||||
from telethon.tl.functions.messages import AddChatUserRequest
|
||||
# For normal chats
|
||||
from telethon.tl.functions.messages import AddChatUserRequest
|
||||
|
||||
# Note that ``user_to_add`` is NOT the name of the parameter.
|
||||
# It's the user you want to add (``user_id=user_to_add``).
|
||||
client(AddChatUserRequest(
|
||||
chat_id,
|
||||
user_to_add,
|
||||
fwd_limit=10 # Allow the user to see the 10 last messages
|
||||
))
|
||||
# Note that ``user_to_add`` is NOT the name of the parameter.
|
||||
# It's the user you want to add (``user_id=user_to_add``).
|
||||
client(AddChatUserRequest(
|
||||
chat_id,
|
||||
user_to_add,
|
||||
fwd_limit=10 # Allow the user to see the 10 last messages
|
||||
))
|
||||
|
||||
# For channels (which includes megagroups)
|
||||
from telethon.tl.functions.channels import InviteToChannelRequest
|
||||
# For channels (which includes megagroups)
|
||||
from telethon.tl.functions.channels import InviteToChannelRequest
|
||||
|
||||
client(InviteToChannelRequest(
|
||||
channel,
|
||||
[users_to_add]
|
||||
))
|
||||
client(InviteToChannelRequest(
|
||||
channel,
|
||||
[users_to_add]
|
||||
))
|
||||
|
||||
|
||||
Checking a link without joining
|
||||
|
@ -112,25 +112,25 @@ closest thing to "no filter" is to simply use
|
|||
If we want to get *all* the members, we need to use a moving offset and
|
||||
a fixed limit:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.channels import GetParticipantsRequest
|
||||
from telethon.tl.types import ChannelParticipantsSearch
|
||||
from time import sleep
|
||||
from telethon.tl.functions.channels import GetParticipantsRequest
|
||||
from telethon.tl.types import ChannelParticipantsSearch
|
||||
from time import sleep
|
||||
|
||||
offset = 0
|
||||
limit = 100
|
||||
all_participants = []
|
||||
offset = 0
|
||||
limit = 100
|
||||
all_participants = []
|
||||
|
||||
while True:
|
||||
participants = client(GetParticipantsRequest(
|
||||
channel, ChannelParticipantsSearch(''), offset, limit,
|
||||
hash=0
|
||||
))
|
||||
if not participants.users:
|
||||
break
|
||||
all_participants.extend(participants.users)
|
||||
offset += len(participants.users)
|
||||
while True:
|
||||
participants = client(GetParticipantsRequest(
|
||||
channel, ChannelParticipantsSearch(''), offset, limit,
|
||||
hash=0
|
||||
))
|
||||
if not participants.users:
|
||||
break
|
||||
all_participants.extend(participants.users)
|
||||
offset += len(participants.users)
|
||||
|
||||
|
||||
.. note::
|
||||
|
@ -164,39 +164,39 @@ Admin Permissions
|
|||
|
||||
Giving or revoking admin permissions can be done with the :tl:`EditAdminRequest`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.channels import EditAdminRequest
|
||||
from telethon.tl.types import ChannelAdminRights
|
||||
from telethon.tl.functions.channels import EditAdminRequest
|
||||
from telethon.tl.types import ChannelAdminRights
|
||||
|
||||
# You need both the channel and who to grant permissions
|
||||
# They can either be channel/user or input channel/input user.
|
||||
#
|
||||
# ChannelAdminRights is a list of granted permissions.
|
||||
# Set to True those you want to give.
|
||||
rights = ChannelAdminRights(
|
||||
post_messages=None,
|
||||
add_admins=None,
|
||||
invite_users=None,
|
||||
change_info=True,
|
||||
ban_users=None,
|
||||
delete_messages=True,
|
||||
pin_messages=True,
|
||||
invite_link=None,
|
||||
edit_messages=None
|
||||
)
|
||||
# Equivalent to:
|
||||
# rights = ChannelAdminRights(
|
||||
# change_info=True,
|
||||
# delete_messages=True,
|
||||
# pin_messages=True
|
||||
# )
|
||||
# You need both the channel and who to grant permissions
|
||||
# They can either be channel/user or input channel/input user.
|
||||
#
|
||||
# ChannelAdminRights is a list of granted permissions.
|
||||
# Set to True those you want to give.
|
||||
rights = ChannelAdminRights(
|
||||
post_messages=None,
|
||||
add_admins=None,
|
||||
invite_users=None,
|
||||
change_info=True,
|
||||
ban_users=None,
|
||||
delete_messages=True,
|
||||
pin_messages=True,
|
||||
invite_link=None,
|
||||
edit_messages=None
|
||||
)
|
||||
# Equivalent to:
|
||||
# rights = ChannelAdminRights(
|
||||
# change_info=True,
|
||||
# delete_messages=True,
|
||||
# pin_messages=True
|
||||
# )
|
||||
|
||||
# Once you have a ChannelAdminRights, invoke it
|
||||
client(EditAdminRequest(channel, user, rights))
|
||||
# Once you have a ChannelAdminRights, invoke it
|
||||
client(EditAdminRequest(channel, user, rights))
|
||||
|
||||
# User will now be able to change group info, delete other people's
|
||||
# messages and pin messages.
|
||||
# User will now be able to change group info, delete other people's
|
||||
# messages and pin messages.
|
||||
|
||||
|
||||
.. note::
|
||||
|
@ -218,41 +218,41 @@ Similar to how you give or revoke admin permissions, you can edit the
|
|||
banned rights of an user through :tl:`EditBannedRequest` and its parameter
|
||||
:tl:`ChannelBannedRights`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.channels import EditBannedRequest
|
||||
from telethon.tl.types import ChannelBannedRights
|
||||
from telethon.tl.functions.channels import EditBannedRequest
|
||||
from telethon.tl.types import ChannelBannedRights
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Restricting an user for 7 days, only allowing view/send messages.
|
||||
#
|
||||
# Note that it's "reversed". You must set to ``True`` the permissions
|
||||
# you want to REMOVE, and leave as ``None`` those you want to KEEP.
|
||||
rights = ChannelBannedRights(
|
||||
until_date=datetime.now() + timedelta(days=7),
|
||||
view_messages=None,
|
||||
send_messages=None,
|
||||
send_media=True,
|
||||
send_stickers=True,
|
||||
send_gifs=True,
|
||||
send_games=True,
|
||||
send_inline=True,
|
||||
embed_links=True
|
||||
)
|
||||
# Restricting an user for 7 days, only allowing view/send messages.
|
||||
#
|
||||
# Note that it's "reversed". You must set to ``True`` the permissions
|
||||
# you want to REMOVE, and leave as ``None`` those you want to KEEP.
|
||||
rights = ChannelBannedRights(
|
||||
until_date=datetime.now() + timedelta(days=7),
|
||||
view_messages=None,
|
||||
send_messages=None,
|
||||
send_media=True,
|
||||
send_stickers=True,
|
||||
send_gifs=True,
|
||||
send_games=True,
|
||||
send_inline=True,
|
||||
embed_links=True
|
||||
)
|
||||
|
||||
# The above is equivalent to
|
||||
rights = ChannelBannedRights(
|
||||
until_date=datetime.now() + timedelta(days=7),
|
||||
send_media=True,
|
||||
send_stickers=True,
|
||||
send_gifs=True,
|
||||
send_games=True,
|
||||
send_inline=True,
|
||||
embed_links=True
|
||||
)
|
||||
# The above is equivalent to
|
||||
rights = ChannelBannedRights(
|
||||
until_date=datetime.now() + timedelta(days=7),
|
||||
send_media=True,
|
||||
send_stickers=True,
|
||||
send_gifs=True,
|
||||
send_games=True,
|
||||
send_inline=True,
|
||||
embed_links=True
|
||||
)
|
||||
|
||||
client(EditBannedRequest(channel, user, rights))
|
||||
client(EditBannedRequest(channel, user, rights))
|
||||
|
||||
|
||||
Kicking a member
|
||||
|
@ -262,15 +262,15 @@ Telegram doesn't actually have a request to kick an user from a group.
|
|||
Instead, you need to restrict them so they can't see messages. Any date
|
||||
is enough:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.channels import EditBannedRequest
|
||||
from telethon.tl.types import ChannelBannedRights
|
||||
from telethon.tl.functions.channels import EditBannedRequest
|
||||
from telethon.tl.types import ChannelBannedRights
|
||||
|
||||
client(EditBannedRequest(channel, user, ChannelBannedRights(
|
||||
until_date=None,
|
||||
view_messages=True
|
||||
)))
|
||||
client(EditBannedRequest(channel, user, ChannelBannedRights(
|
||||
until_date=None,
|
||||
view_messages=True
|
||||
)))
|
||||
|
||||
|
||||
__ https://github.com/Kyle2142
|
||||
|
@ -285,17 +285,17 @@ It has been asked `quite`__ `a few`__ `times`__ (really, `many`__), and
|
|||
while I don't understand why so many people ask this, the solution is to
|
||||
use :tl:`GetMessagesViewsRequest`, setting ``increment=True``:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
|
||||
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
|
||||
# Obtain `msg_ids' through `.get_messages()` or anyhow. Must be a list.
|
||||
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
|
||||
# Obtain `msg_ids' through `.get_messages()` or anyhow. Must be a list.
|
||||
|
||||
client(GetMessagesViewsRequest(
|
||||
peer=channel,
|
||||
id=msg_ids,
|
||||
increment=True
|
||||
))
|
||||
client(GetMessagesViewsRequest(
|
||||
peer=channel,
|
||||
id=msg_ids,
|
||||
increment=True
|
||||
))
|
||||
|
||||
|
||||
Note that you can only do this **once or twice a day** per account,
|
||||
|
|
|
@ -15,15 +15,15 @@ If you need to retrieve the bio, biography or about information for an user
|
|||
you should use :tl:`GetFullUser`:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.users import GetFullUserRequest
|
||||
from telethon.tl.functions.users import GetFullUserRequest
|
||||
|
||||
full = client(GetFullUserRequest(user))
|
||||
# or even
|
||||
full = client(GetFullUserRequest('username'))
|
||||
full = client(GetFullUserRequest(user))
|
||||
# or even
|
||||
full = client(GetFullUserRequest('username'))
|
||||
|
||||
bio = full.about
|
||||
bio = full.about
|
||||
|
||||
|
||||
See :tl:`UserFull` to know what other fields you can access.
|
||||
|
@ -35,11 +35,11 @@ Updating your name and/or bio
|
|||
The first name, last name and bio (about) can all be changed with the same
|
||||
request. Omitted fields won't change after invoking :tl:`UpdateProfile`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.account import UpdateProfileRequest
|
||||
from telethon.tl.functions.account import UpdateProfileRequest
|
||||
|
||||
client(UpdateProfileRequest(about='This is a test from Telethon'))
|
||||
client(UpdateProfileRequest(about='This is a test from Telethon'))
|
||||
|
||||
|
||||
Updating your username
|
||||
|
@ -47,11 +47,11 @@ Updating your username
|
|||
|
||||
You need to use :tl:`account.UpdateUsername`:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.account import UpdateUsernameRequest
|
||||
from telethon.tl.functions.account import UpdateUsernameRequest
|
||||
|
||||
client(UpdateUsernameRequest('new_username'))
|
||||
client(UpdateUsernameRequest('new_username'))
|
||||
|
||||
|
||||
Updating your profile photo
|
||||
|
@ -61,10 +61,10 @@ The easiest way is to upload a new file and use that as the profile photo
|
|||
through :tl:`UploadProfilePhoto`:
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.photos import UploadProfilePhotoRequest
|
||||
from telethon.tl.functions.photos import UploadProfilePhotoRequest
|
||||
|
||||
client(UploadProfilePhotoRequest(
|
||||
client.upload_file('/path/to/some/file')
|
||||
))
|
||||
client(UploadProfilePhotoRequest(
|
||||
client.upload_file('/path/to/some/file')
|
||||
))
|
||||
|
|
|
@ -20,31 +20,31 @@ Forwarding messages
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
# If you only have the message IDs
|
||||
client.forward_messages(
|
||||
entity, # to which entity you are forwarding the messages
|
||||
message_ids, # the IDs of the messages (or message) to forward
|
||||
from_entity # who sent the messages?
|
||||
)
|
||||
# If you only have the message IDs
|
||||
client.forward_messages(
|
||||
entity, # to which entity you are forwarding the messages
|
||||
message_ids, # the IDs of the messages (or message) to forward
|
||||
from_entity # who sent the messages?
|
||||
)
|
||||
|
||||
# If you have ``Message`` objects
|
||||
client.forward_messages(
|
||||
entity, # to which entity you are forwarding the messages
|
||||
messages # the messages (or message) to forward
|
||||
)
|
||||
# If you have ``Message`` objects
|
||||
client.forward_messages(
|
||||
entity, # to which entity you are forwarding the messages
|
||||
messages # the messages (or message) to forward
|
||||
)
|
||||
|
||||
# You can also do it manually if you prefer
|
||||
from telethon.tl.functions.messages import ForwardMessagesRequest
|
||||
# You can also do it manually if you prefer
|
||||
from telethon.tl.functions.messages import ForwardMessagesRequest
|
||||
|
||||
messages = foo() # retrieve a few messages (or even one, in a list)
|
||||
from_entity = bar()
|
||||
to_entity = baz()
|
||||
messages = foo() # retrieve a few messages (or even one, in a list)
|
||||
from_entity = bar()
|
||||
to_entity = baz()
|
||||
|
||||
client(ForwardMessagesRequest(
|
||||
from_peer=from_entity, # who sent these messages?
|
||||
id=[msg.id for msg in messages], # which are the messages?
|
||||
to_peer=to_entity # who are we forwarding them to?
|
||||
))
|
||||
client(ForwardMessagesRequest(
|
||||
from_peer=from_entity, # who sent these messages?
|
||||
id=[msg.id for msg in messages], # which are the messages?
|
||||
to_peer=to_entity # who are we forwarding them to?
|
||||
))
|
||||
|
||||
The named arguments are there for clarity, although they're not needed because
|
||||
they appear in order. You can obviously just wrap a single message on the list
|
||||
|
@ -65,26 +65,26 @@ Searching Messages
|
|||
Messages are searched through the obvious :tl:`SearchRequest`, but you may run
|
||||
into issues_. A valid example would be:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import SearchRequest
|
||||
from telethon.tl.types import InputMessagesFilterEmpty
|
||||
from telethon.tl.functions.messages import SearchRequest
|
||||
from telethon.tl.types import InputMessagesFilterEmpty
|
||||
|
||||
filter = InputMessagesFilterEmpty()
|
||||
result = client(SearchRequest(
|
||||
peer=peer, # On which chat/conversation
|
||||
q='query', # What to search for
|
||||
filter=filter, # Filter to use (maybe filter for media)
|
||||
min_date=None, # Minimum date
|
||||
max_date=None, # Maximum date
|
||||
offset_id=0, # ID of the message to use as offset
|
||||
add_offset=0, # Additional offset
|
||||
limit=10, # How many results
|
||||
max_id=0, # Maximum message ID
|
||||
min_id=0, # Minimum message ID
|
||||
from_id=None, # Who must have sent the message (peer)
|
||||
hash=0 # Special number to return nothing on no-change
|
||||
))
|
||||
filter = InputMessagesFilterEmpty()
|
||||
result = client(SearchRequest(
|
||||
peer=peer, # On which chat/conversation
|
||||
q='query', # What to search for
|
||||
filter=filter, # Filter to use (maybe filter for media)
|
||||
min_date=None, # Minimum date
|
||||
max_date=None, # Maximum date
|
||||
offset_id=0, # ID of the message to use as offset
|
||||
add_offset=0, # Additional offset
|
||||
limit=10, # How many results
|
||||
max_id=0, # Maximum message ID
|
||||
min_id=0, # Minimum message ID
|
||||
from_id=None, # Who must have sent the message (peer)
|
||||
hash=0 # Special number to return nothing on no-change
|
||||
))
|
||||
|
||||
It's important to note that the optional parameter ``from_id`` could have
|
||||
been omitted (defaulting to ``None``). Changing it to :tl:`InputUserEmpty`, as one
|
||||
|
@ -113,31 +113,31 @@ referenced through this pair of ID/hash (unique per user), and you need to
|
|||
use this handle when sending a "document" message. This working example will
|
||||
send yourself the very first sticker you have:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
# Get all the sticker sets this user has
|
||||
sticker_sets = client(GetAllStickersRequest(0))
|
||||
# Get all the sticker sets this user has
|
||||
sticker_sets = client(GetAllStickersRequest(0))
|
||||
|
||||
# Choose a sticker set
|
||||
sticker_set = sticker_sets.sets[0]
|
||||
# Choose a sticker set
|
||||
sticker_set = sticker_sets.sets[0]
|
||||
|
||||
# Get the stickers for this sticker set
|
||||
stickers = client(GetStickerSetRequest(
|
||||
stickerset=InputStickerSetID(
|
||||
id=sticker_set.id, access_hash=sticker_set.access_hash
|
||||
# Get the stickers for this sticker set
|
||||
stickers = client(GetStickerSetRequest(
|
||||
stickerset=InputStickerSetID(
|
||||
id=sticker_set.id, access_hash=sticker_set.access_hash
|
||||
)
|
||||
))
|
||||
|
||||
# Stickers are nothing more than files, so send that
|
||||
client(SendMediaRequest(
|
||||
peer=client.get_me(),
|
||||
media=InputMediaDocument(
|
||||
id=InputDocument(
|
||||
id=stickers.documents[0].id,
|
||||
access_hash=stickers.documents[0].access_hash
|
||||
)
|
||||
))
|
||||
|
||||
# Stickers are nothing more than files, so send that
|
||||
client(SendMediaRequest(
|
||||
peer=client.get_me(),
|
||||
media=InputMediaDocument(
|
||||
id=InputDocument(
|
||||
id=stickers.documents[0].id,
|
||||
access_hash=stickers.documents[0].access_hash
|
||||
)
|
||||
)
|
||||
))
|
||||
)
|
||||
))
|
||||
|
||||
|
||||
.. _issues: https://github.com/LonamiWebs/Telethon/issues/215
|
||||
|
|
|
@ -14,25 +14,25 @@ will be printed unless you explicitly enable it.
|
|||
|
||||
You can also `use the module`__ on your own project very easily:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.debug('Debug messages')
|
||||
logger.info('Useful information')
|
||||
logger.warning('This is a warning!')
|
||||
logger.debug('Debug messages')
|
||||
logger.info('Useful information')
|
||||
logger.warning('This is a warning!')
|
||||
|
||||
|
||||
If you want to enable ``logging`` for your project *but* use a different
|
||||
log level for the library:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: python
|
||||
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
# For instance, show only warnings and above
|
||||
logging.getLogger('telethon').setLevel(level=logging.WARNING)
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
# For instance, show only warnings and above
|
||||
logging.getLogger('telethon').setLevel(level=logging.WARNING)
|
||||
|
||||
|
||||
__ https://docs.python.org/3/library/logging.html
|
||||
|
|
|
@ -50,14 +50,14 @@ The current winner is `issue
|
|||
|
||||
**Issue:**
|
||||
|
||||
.. figure:: https://user-images.githubusercontent.com/6297805/29822978-9a9a6ef0-8ccd-11e7-9ec5-934ea0f57681.jpg
|
||||
:alt: Winner issue
|
||||
.. figure:: https://user-images.githubusercontent.com/6297805/29822978-9a9a6ef0-8ccd-11e7-9ec5-934ea0f57681.jpg
|
||||
:alt: Winner issue
|
||||
|
||||
Winner issue
|
||||
Winner issue
|
||||
|
||||
**Answer:**
|
||||
|
||||
.. figure:: https://user-images.githubusercontent.com/6297805/29822983-9d523402-8ccd-11e7-9fb1-5783740ee366.jpg
|
||||
:alt: Winner issue answer
|
||||
.. figure:: https://user-images.githubusercontent.com/6297805/29822983-9d523402-8ccd-11e7-9fb1-5783740ee366.jpg
|
||||
:alt: Winner issue answer
|
||||
|
||||
Winner issue answer
|
||||
Winner issue answer
|
||||
|
|
|
@ -31,7 +31,16 @@ class UpdateMethods(UserMethods):
|
|||
|
||||
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:
|
||||
event (`_EventBuilder` | `type`):
|
||||
|
|
|
@ -82,7 +82,29 @@ class EventBuilder(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'
|
||||
|
||||
def __init__(self, chat_peer=None, msg_id=None, broadcast=False):
|
||||
|
@ -146,6 +168,9 @@ class EventCommon(abc.ABC):
|
|||
|
||||
@property
|
||||
def client(self):
|
||||
"""
|
||||
The `telethon.TelegramClient` that created this event.
|
||||
"""
|
||||
return self._client
|
||||
|
||||
@property
|
||||
|
|
|
@ -177,6 +177,12 @@ class Message:
|
|||
|
||||
@property
|
||||
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:
|
||||
try:
|
||||
self._chat =\
|
||||
|
|
Loading…
Reference in New Issue
Block a user