2017-11-20 07:19:53 +03:00
|
|
|
.. _accessing-the-full-api:
|
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
======================
|
2017-11-20 07:12:31 +03:00
|
|
|
Accessing the Full API
|
2018-01-05 02:59:53 +03:00
|
|
|
======================
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-05-17 13:00:22 +03:00
|
|
|
.. important::
|
|
|
|
|
|
|
|
While you have access to this, you should always use the friendly
|
2018-06-19 22:24:26 +03:00
|
|
|
methods listed on :ref:`telethon-client` unless you have a better
|
2018-05-17 13:00:22 +03:00
|
|
|
reason not to, like a method not existing or you wanting more control.
|
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
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.
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
2018-01-20 13:47:17 +03:00
|
|
|
The reason to keep both https://lonamiwebs.github.io/Telethon and this
|
|
|
|
documentation alive is that the former allows instant search results
|
|
|
|
as you type, and a "Copy import" button. If you like namespaces, you
|
|
|
|
can also do ``from telethon.tl import types, functions``. Both work.
|
2018-01-05 02:59:53 +03:00
|
|
|
|
|
|
|
|
2018-06-25 22:14:58 +03:00
|
|
|
.. important::
|
|
|
|
|
|
|
|
All the examples in this documentation assume that you have
|
2018-10-06 21:20:11 +03:00
|
|
|
``from telethon import sync`` or ``import telethon.sync`` for the
|
|
|
|
sake of simplicity and that you understand what it does (see
|
|
|
|
:ref:`compatibility-and-convenience` for more). Simply add
|
2018-06-25 22:14:58 +03:00
|
|
|
either line at the beginning of your project and it will work.
|
|
|
|
|
|
|
|
|
2017-11-20 07:12:31 +03:00
|
|
|
You should also refer to the documentation to see what the objects
|
|
|
|
(constructors) Telegram returns look like. Every constructor inherits
|
2018-01-05 02:59:53 +03:00
|
|
|
from a common type, and that's the reason for this distinction.
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
Say `client.send_message
|
|
|
|
<telethon.client.messages.MessageMethods.send_message>` didn't exist,
|
2018-05-30 19:55:01 +03:00
|
|
|
we could use the `search`__ to look for "message". There we would find
|
|
|
|
:tl:`SendMessageRequest`, which we can work with.
|
2017-11-20 07:12:31 +03:00
|
|
|
|
|
|
|
Every request is a Python class, and has the parameters needed for you
|
|
|
|
to invoke it. You can also call ``help(request)`` for information on
|
2018-01-05 02:59:53 +03:00
|
|
|
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:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from telethon.tl.functions.messages import SendMessageRequest
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
If you're going to use a lot of these, you may do:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from telethon.tl import types, functions
|
|
|
|
# We now have access to 'functions.messages.SendMessageRequest'
|
2017-11-20 07:12:31 +03:00
|
|
|
|
|
|
|
We see that this request must take at least two parameters, a ``peer``
|
2018-03-23 23:40:24 +03:00
|
|
|
of type :tl:`InputPeer`, and a ``message`` which is just a Python
|
2017-11-20 07:12:31 +03:00
|
|
|
``str``\ ing.
|
|
|
|
|
2018-03-23 23:40:24 +03:00
|
|
|
How can we retrieve this :tl:`InputPeer`? We have two options. We manually
|
|
|
|
construct one, for instance:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
from telethon.tl.types import InputPeerUser
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
peer = InputPeerUser(user_id, user_hash)
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
Or we call `client.get_input_entity
|
|
|
|
<telethon.client.users.UserMethods.get_input_entity>`:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-25 22:14:58 +03:00
|
|
|
import telethon.sync
|
|
|
|
peer = client.get_input_entity('someone')
|
|
|
|
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
When you're going to invoke an API method, most require you to pass an
|
2018-03-23 23:40:24 +03:00
|
|
|
:tl:`InputUser`, :tl:`InputChat`, or so on, this is why using
|
2018-06-20 12:05:33 +03:00
|
|
|
`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:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-25 22:14:58 +03:00
|
|
|
entity = client.get_entity('someone')
|
2017-11-20 07:12:31 +03:00
|
|
|
|
|
|
|
In the later case, when you use the entity, the library will cast it to
|
2018-01-05 02:59:53 +03:00
|
|
|
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
|
2018-05-30 19:55:01 +03:00
|
|
|
every time its used, simply call `telethon.utils.get_input_peer`:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
from telethon import utils
|
2018-06-22 15:44:59 +03:00
|
|
|
peer = utils.get_input_peer(entity)
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-01-20 13:47:17 +03:00
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
Since ``v0.16.2`` this is further simplified. The ``Request`` itself
|
2018-10-06 21:20:11 +03:00
|
|
|
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.
|
2018-01-20 13:47:17 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
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
|
2017-11-20 07:12:31 +03:00
|
|
|
request we do:
|
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-25 22:14:58 +03:00
|
|
|
result = client(SendMessageRequest(peer, 'Hello there!'))
|
2018-06-20 12:05:33 +03:00
|
|
|
# __call__ is an alias for client.invoke(request). Both will work
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-22 15:44:59 +03:00
|
|
|
Message sent! Of course, this is only an example. There are over 250
|
|
|
|
methods available as of layer 80, and you can use every single of them
|
2018-01-05 02:59:53 +03:00
|
|
|
as you wish. Remember to use the right types! To sum up:
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-06-25 22:14:58 +03:00
|
|
|
result = client(SendMessageRequest(
|
2018-06-20 12:05:33 +03:00
|
|
|
client.get_input_entity('username'), 'Hello there!'
|
2018-06-25 22:14:58 +03:00
|
|
|
))
|
2017-11-20 07:12:31 +03:00
|
|
|
|
|
|
|
|
2018-03-04 01:51:35 +03:00
|
|
|
This can further be simplified to:
|
|
|
|
|
2018-06-20 12:05:33 +03:00
|
|
|
.. code-block:: python
|
2018-03-04 01:51:35 +03:00
|
|
|
|
2018-06-25 22:14:58 +03:00
|
|
|
result = client(SendMessageRequest('username', 'Hello there!'))
|
|
|
|
# Or even
|
|
|
|
result = client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
|
2018-03-04 01:51:35 +03:00
|
|
|
|
2017-11-20 07:12:31 +03:00
|
|
|
.. note::
|
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
Note that some requests have a "hash" parameter. This is **not**
|
|
|
|
your ``api_hash``! It likely isn't your self-user ``.access_hash`` either.
|
|
|
|
|
2017-11-20 07:12:31 +03:00
|
|
|
It's a special hash used by Telegram to only send a difference of new data
|
2018-01-05 02:59:53 +03:00
|
|
|
that you don't already have with that request, so you can leave it to 0,
|
|
|
|
and it should work (which means no hash is known yet).
|
2017-11-20 07:12:31 +03:00
|
|
|
|
2018-01-05 02:59:53 +03:00
|
|
|
For those requests having a "limit" parameter, you can often set it to
|
|
|
|
zero to signify "return default amount". This won't work for all of them
|
|
|
|
though, for instance, in "messages.search" it will actually return 0 items.
|
2017-11-20 07:12:31 +03:00
|
|
|
|
|
|
|
|
2018-08-24 21:14:29 +03:00
|
|
|
Requests in Parallel
|
|
|
|
********************
|
|
|
|
|
|
|
|
The library will automatically merge outgoing requests into a single
|
|
|
|
*container*. Telegram's API supports sending multiple requests in a
|
|
|
|
single container, which is faster because it has less overhead and
|
|
|
|
the server can run them without waiting for others. You can also
|
|
|
|
force using a container manually:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
async def main():
|
|
|
|
|
|
|
|
# Letting the library do it behind the scenes
|
|
|
|
await asyncio.wait([
|
|
|
|
client.send_message('me', 'Hello'),
|
|
|
|
client.send_message('me', ','),
|
|
|
|
client.send_message('me', 'World'),
|
|
|
|
client.send_message('me', '.')
|
|
|
|
])
|
|
|
|
|
|
|
|
# Manually invoking many requests at once
|
|
|
|
await client([
|
|
|
|
SendMessageRequest('me', 'Hello'),
|
|
|
|
SendMessageRequest('me', ', '),
|
|
|
|
SendMessageRequest('me', 'World'),
|
|
|
|
SendMessageRequest('me', '.')
|
|
|
|
])
|
|
|
|
|
|
|
|
Note that you cannot guarantee the order in which they are run.
|
|
|
|
Try running the above code more than one time. You will see the
|
|
|
|
order in which the messages arrive is different.
|
|
|
|
|
|
|
|
If you use the raw API (the first option), you can use ``ordered``
|
|
|
|
to tell the server that it should run the requests sequentially.
|
|
|
|
This will still be faster than going one by one, since the server
|
|
|
|
knows all requests directly:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
client([
|
|
|
|
SendMessageRequest('me', 'Hello'),
|
|
|
|
SendMessageRequest('me', ', '),
|
|
|
|
SendMessageRequest('me', 'World'),
|
|
|
|
SendMessageRequest('me', '.')
|
|
|
|
], ordered=True)
|
|
|
|
|
|
|
|
If any of the requests fails with a Telegram error (not connection
|
|
|
|
errors or any other unexpected events), the library will raise
|
|
|
|
`telethon.errors.common.MultiError`. You can ``except`` this
|
|
|
|
and still access the successful results:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from telethon.errors import MultiError
|
|
|
|
|
|
|
|
try:
|
|
|
|
client([
|
|
|
|
SendMessageRequest('me', 'Hello'),
|
|
|
|
SendMessageRequest('me', ''),
|
|
|
|
SendMessageRequest('me', 'World')
|
|
|
|
], ordered=True)
|
|
|
|
except MultiError as e:
|
|
|
|
# The first and third requests worked.
|
|
|
|
first = e.results[0]
|
|
|
|
third = e.results[2]
|
|
|
|
# The second request failed.
|
|
|
|
second = e.exceptions[1]
|
|
|
|
|
2017-11-20 07:12:31 +03:00
|
|
|
__ https://lonamiwebs.github.io/Telethon
|
|
|
|
__ https://lonamiwebs.github.io/Telethon/methods/index.html
|
2018-04-14 13:03:08 +03:00
|
|
|
__ https://lonamiwebs.github.io/Telethon/?q=message&redirect=no
|