mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-22 17:36:34 +03:00
Finish up asyncio docs
This commit is contained in:
parent
3d3698562b
commit
f614d3836b
|
@ -93,7 +93,7 @@ every time its used, simply call `telethon.utils.get_input_peer`:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from telethon import utils
|
from telethon import utils
|
||||||
peer = utils.get_input_user(entity)
|
peer = utils.get_input_peer(entity)
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -117,8 +117,8 @@ request we do:
|
||||||
)
|
)
|
||||||
# __call__ is an alias for client.invoke(request). Both will work
|
# __call__ is an alias for client.invoke(request). Both will work
|
||||||
|
|
||||||
Message sent! Of course, this is only an example. There are nearly 250
|
Message sent! Of course, this is only an example. There are over 250
|
||||||
methods available as of layer 73, and you can use every single of them
|
methods available as of layer 80, and you can use every single of them
|
||||||
as you wish. Remember to use the right types! To sum up:
|
as you wish. Remember to use the right types! To sum up:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
|
@ -24,8 +24,8 @@ loop, you should use `client.run_until_disconnected
|
||||||
|
|
||||||
|
|
||||||
Behind the scenes, this method is ``await``'ing on the `client.disconnected
|
Behind the scenes, this method is ``await``'ing on the `client.disconnected
|
||||||
<telethon.client.telegrambaseclient.disconnected>` property, so the code above
|
<telethon.client.telegrambaseclient.TelegramBaseClient.disconnected>` property,
|
||||||
and the following are equivalent:
|
so the code above and the following are equivalent:
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -42,7 +42,8 @@ and the following are equivalent:
|
||||||
|
|
||||||
|
|
||||||
You could also run `client.disconnected
|
You could also run `client.disconnected
|
||||||
<telethon.client.telegrambaseclient.disconnected>` until it completed.
|
<telethon.client.telegrambaseclient.TelegramBaseClient.disconnected>`
|
||||||
|
until it completed.
|
||||||
|
|
||||||
But if you don't want to ``await``, then you should know what you want
|
But if you don't want to ``await``, then you should know what you want
|
||||||
to be doing instead! What matters is that you shouldn't let your script
|
to be doing instead! What matters is that you shouldn't let your script
|
||||||
|
|
|
@ -19,9 +19,9 @@ way. You send your request, and eventually, Telegram will process it and
|
||||||
respond to it. It feels natural to make a library that also behaves this
|
respond to it. It feels natural to make a library that also behaves this
|
||||||
way: you send a request, and you can ``await`` for its result.
|
way: you send a request, and you can ``await`` for its result.
|
||||||
|
|
||||||
Having understood that Telegram's API follows an asynchronous model and
|
Now that we know that Telegram's API follows an asynchronous model, you
|
||||||
developing a library that does the same greatly simplifies the internal
|
should understand the benefits of developing a library that does the same,
|
||||||
code and eases working with the API.
|
it greatly simplifies the internal code and eases working with the API.
|
||||||
|
|
||||||
Using ``asyncio`` keeps a cleaner library that will be easier to understand,
|
Using ``asyncio`` keeps a cleaner library that will be easier to understand,
|
||||||
develop, and that will be faster than using threads, which are harder to get
|
develop, and that will be faster than using threads, which are harder to get
|
||||||
|
@ -54,7 +54,7 @@ To get started with ``asyncio``, all you need is to setup your main
|
||||||
|
|
||||||
Inside ``async def main():``, you can use the ``await`` keyword. Most
|
Inside ``async def main():``, you can use the ``await`` keyword. Most
|
||||||
methods in the :ref:`TelegramClient <telethon-client>` are ``async def``.
|
methods in the :ref:`TelegramClient <telethon-client>` are ``async def``.
|
||||||
You must ``await`` all ``async def``, also known as a coroutine:
|
You must ``await`` all ``async def``, also known as a *coroutines*:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -78,9 +78,9 @@ Another way to use ``async def`` is to use ``loop.run_until_complete(f())``,
|
||||||
but the loop must not be running before.
|
but the loop must not be running before.
|
||||||
|
|
||||||
If you want to handle updates (and don't let the script die), you must
|
If you want to handle updates (and don't let the script die), you must
|
||||||
`await client.disconnected <telethon.client.telegrambaseclient.disconnected>`
|
`await client.disconnected <telethon.client.telegrambaseclient.TelegramBaseClient.disconnected>`
|
||||||
which is a property that you can wait on until you call
|
which is a property that you can wait on until you call
|
||||||
`await client.disconnect() <telethon.client.telegrambaseclient.disconnect>`:
|
`await client.disconnect() <telethon.client.telegrambaseclient.TelegramBaseClient.disconnect>`:
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -115,6 +115,68 @@ This is the same as using the ``run_until_disconnected()`` method:
|
||||||
client.run_until_disconnected()
|
client.run_until_disconnected()
|
||||||
|
|
||||||
|
|
||||||
|
Which methods should I use and when?
|
||||||
|
************************************
|
||||||
|
|
||||||
|
Something to note is that you must always get an event loop if you
|
||||||
|
want to be able to make any API calls. This is done as follows:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
The loop must be running, or things will never get sent.
|
||||||
|
Normally, you use ``run_until_complete``:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def coroutine():
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
|
loop.run_until_complete(coroutine())
|
||||||
|
|
||||||
|
Note that ``asyncio.sleep`` is in itself a coroutine, so this will
|
||||||
|
work too:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
loop.run_until_complete(asyncio.sleep(1))
|
||||||
|
|
||||||
|
Generally, you make an ``async def main()`` if you need to ``await``
|
||||||
|
a lot of things, instead of typing ``run_until_complete`` all the time:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
message = await client.send_message('me', 'Hi')
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
await message.delete()
|
||||||
|
|
||||||
|
loop.run_until_complete(main())
|
||||||
|
|
||||||
|
# vs
|
||||||
|
|
||||||
|
message = loop.run_until_complete(client.send_message('me', 'Hi'))
|
||||||
|
loop.run_until_complete(asyncio.sleep(1))
|
||||||
|
loop.run_until_complete(message.delete())
|
||||||
|
|
||||||
|
You can see that the first version has more lines, but you had to type
|
||||||
|
a lot less. You can also rename the run method to something shorter:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# Note no parenthesis (), we're not running it, just copying the method
|
||||||
|
rc = loop.run_until_complete
|
||||||
|
message = rc(client.send_message('me', 'Hi'))
|
||||||
|
rc(asyncio.sleep(1))
|
||||||
|
rc(message.delete())
|
||||||
|
|
||||||
|
The documentation will use all these three styles so you can get used
|
||||||
|
to them. Which one to use is up to you, but generally you should work
|
||||||
|
inside an ``async def main()`` and just run the loop there.
|
||||||
|
|
||||||
|
|
||||||
More resources to learn asyncio
|
More resources to learn asyncio
|
||||||
*******************************
|
*******************************
|
||||||
|
|
||||||
|
|
|
@ -30,14 +30,16 @@ this is, any "method" listed on the API. There are a few methods (and
|
||||||
growing!) on the :ref:`TelegramClient <telethon-client>` class that abstract
|
growing!) on the :ref:`TelegramClient <telethon-client>` class that abstract
|
||||||
you from the need of manually importing the requests you need.
|
you from the need of manually importing the requests you need.
|
||||||
|
|
||||||
For instance, retrieving your own user can be done in a single line:
|
For instance, retrieving your own user can be done in a single line
|
||||||
|
(if we ignore the boilerplate needed to setup ``asyncio``, which only
|
||||||
|
needs to be done once for your entire program):
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
myself = await client.get_me()
|
myself = await client.get_me() # <- a single line!
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
|
|
|
@ -82,7 +82,8 @@ the callback function you're about to define will be called:
|
||||||
|
|
||||||
If a `NewMessage
|
If a `NewMessage
|
||||||
<telethon.events.newmessage.NewMessage>` event occurs,
|
<telethon.events.newmessage.NewMessage>` event occurs,
|
||||||
and ``'hello'`` is in the text of the message, we ``reply`` to the event
|
and ``'hello'`` is in the text of the message, we `.reply()
|
||||||
|
<telethon.tl.custom.message.Message.reply>` to the event
|
||||||
with a ``'hi!'`` message.
|
with a ``'hi!'`` message.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
@ -101,23 +102,35 @@ More on events
|
||||||
**************
|
**************
|
||||||
|
|
||||||
The `NewMessage <telethon.events.newmessage.NewMessage>` event has much
|
The `NewMessage <telethon.events.newmessage.NewMessage>` event has much
|
||||||
more than what was shown. You can access the ``.sender`` of the message
|
more than what was shown. You can access the `.sender
|
||||||
through that member, or even see if the message had ``.media``, a ``.photo``
|
<telethon.tl.custom.message.Message.sender>` of the message
|
||||||
or a ``.document`` (which you could download with for example
|
through that member, or even see if the message had `.media
|
||||||
`client.download_media(event.photo) <telethon.client.downloads.DownloadMethods.download_media>`.
|
<telethon.tl.custom.message.Message.media>`, a `.photo
|
||||||
|
<telethon.tl.custom.message.Message.photo>` or a `.document
|
||||||
|
<telethon.tl.custom.message.Message.document>` (which you
|
||||||
|
could download with for example `client.download_media(event.photo)
|
||||||
|
<telethon.client.downloads.DownloadMethods.download_media>`.
|
||||||
|
|
||||||
If you don't want to ``.reply`` as a reply, you can use the ``.respond()``
|
If you don't want to `.reply()
|
||||||
method instead. Of course, there are more events such as ``ChatAction`` or
|
<telethon.tl.custom.message.Message.reply>` as a reply,
|
||||||
``UserUpdate``, and they're all used in the same way. Simply add the
|
you can use the `.respond() <telethon.tl.custom.message.Message.respond>`
|
||||||
``@client.on(events.XYZ)`` decorator on the top of your handler and you're
|
method instead. Of course, there are more events such as `ChatAction
|
||||||
done! The event that will be passed always is of type ``XYZ.Event`` (for
|
<telethon.events.chataction.ChatAction>` or `UserUpdate
|
||||||
instance, ``NewMessage.Event``), except for the ``Raw`` event which just
|
<telethon.events.userupdate.UserUpdate>`, and they're all
|
||||||
passes the ``Update`` object.
|
used in the same way. Simply add the `@client.on(events.XYZ)
|
||||||
|
<telethon.client.updates.UpdateMethods.on>` decorator on the top
|
||||||
|
of your handler and you're done! The event that will be passed always
|
||||||
|
is of type ``XYZ.Event`` (for instance, `NewMessage.Event
|
||||||
|
<telethon.events.newmessage.NewMessage.Event>`), except for the `Raw
|
||||||
|
<telethon.events.raw.Raw>` event which just passes the :tl:`Update` object.
|
||||||
|
|
||||||
Note that ``.reply()`` and ``.respond()`` are just wrappers around the
|
Note that `.reply()
|
||||||
|
<telethon.tl.custom.message.Message.reply>` and `.respond()
|
||||||
|
<telethon.tl.custom.message.Message.respond>` are just wrappers around the
|
||||||
`client.send_message() <telethon.client.messages.MessageMethods.send_message>`
|
`client.send_message() <telethon.client.messages.MessageMethods.send_message>`
|
||||||
method which supports the ``file=`` parameter.
|
method which supports the ``file=`` parameter.
|
||||||
This means you can reply with a photo if you do ``event.reply(file=photo)``.
|
This means you can reply with a photo if you do `event.reply(file=photo)
|
||||||
|
<telethon.tl.custom.message.Message.reply>`.
|
||||||
|
|
||||||
You can put the same event on many handlers, and even different events on
|
You can put the same event on many handlers, and even different events on
|
||||||
the same handler. You can also have a handler work on only specific chats,
|
the same handler. You can also have a handler work on only specific chats,
|
||||||
|
@ -154,6 +167,45 @@ random number, while if you say ``'eval 4+4'``, you will reply with the
|
||||||
solution. Try it!
|
solution. Try it!
|
||||||
|
|
||||||
|
|
||||||
|
Properties vs. methods
|
||||||
|
**********************
|
||||||
|
|
||||||
|
The event shown above acts just like a `custom.Message
|
||||||
|
<telethon.tl.custom.message.Message>`, which means you
|
||||||
|
can access all the properties it has, like ``.sender``.
|
||||||
|
|
||||||
|
**However** events are different to other methods in the client, like
|
||||||
|
`client.get_messages <telethon.client.messages.MessageMethods.get_messages>`.
|
||||||
|
Events *may not* send information about the sender or chat, which means it
|
||||||
|
can be ``None``, but all the methods defined in the client always have this
|
||||||
|
information so it doesn't need to be re-fetched. For this reason, you have
|
||||||
|
``get_`` methods, which will make a network call if necessary.
|
||||||
|
|
||||||
|
In short, you should do this:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
@client.on(events.NewMessage)
|
||||||
|
async def handler(event):
|
||||||
|
# event.input_chat may be None, use event.get_input_chat()
|
||||||
|
chat = await event.get_input_chat()
|
||||||
|
sender = await event.get_sender()
|
||||||
|
buttons = await event.get_buttons()
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
async for message in client.iter_messages('me', 10):
|
||||||
|
# Methods from the client always have these properties ready
|
||||||
|
chat = message.input_chat
|
||||||
|
sender = message.sender
|
||||||
|
buttons = message.buttons
|
||||||
|
|
||||||
|
Notice, properties (`message.sender
|
||||||
|
<telethon.tl.custom.message.Message.sender>`) don't need an ``await``, but
|
||||||
|
methods (`message.get_sender
|
||||||
|
<telethon.tl.custom.message.Message.get_sender>`) **do** need an ``await``,
|
||||||
|
and you should use methods in events for these properties that may need network.
|
||||||
|
|
||||||
|
|
||||||
Events without decorators
|
Events without decorators
|
||||||
*************************
|
*************************
|
||||||
|
|
||||||
|
|
|
@ -32,4 +32,6 @@ times, in this case, ``22222`` so we can hardcode that:
|
||||||
|
|
||||||
client = TelegramClient(None, api_id, api_hash)
|
client = TelegramClient(None, api_id, api_hash)
|
||||||
client.session.set_dc(2, '149.154.167.40', 80)
|
client.session.set_dc(2, '149.154.167.40', 80)
|
||||||
client.start(phone='9996621234', code_callback=lambda: '22222')
|
loop.run_until_complete(client.start(
|
||||||
|
phone='9996621234', code_callback=lambda: '22222'
|
||||||
|
))
|
||||||
|
|
|
@ -19,9 +19,9 @@ not *interact* with a voting message), by making use of the
|
||||||
|
|
||||||
from telethon.tl.functions.messages import GetInlineBotResultsRequest
|
from telethon.tl.functions.messages import GetInlineBotResultsRequest
|
||||||
|
|
||||||
bot_results = client(GetInlineBotResultsRequest(
|
bot_results = loop.run_until_complete(client(GetInlineBotResultsRequest(
|
||||||
bot, user_or_chat, 'query', ''
|
bot, user_or_chat, 'query', ''
|
||||||
))
|
)))
|
||||||
|
|
||||||
And you can select any of their results by using
|
And you can select any of their results by using
|
||||||
:tl:`SendInlineBotResultRequest`:
|
:tl:`SendInlineBotResultRequest`:
|
||||||
|
@ -30,16 +30,27 @@ And you can select any of their results by using
|
||||||
|
|
||||||
from telethon.tl.functions.messages import SendInlineBotResultRequest
|
from telethon.tl.functions.messages import SendInlineBotResultRequest
|
||||||
|
|
||||||
client(SendInlineBotResultRequest(
|
loop.run_until_complete(client(SendInlineBotResultRequest(
|
||||||
get_input_peer(user_or_chat),
|
get_input_peer(user_or_chat),
|
||||||
obtained_query_id,
|
obtained_query_id,
|
||||||
obtained_str_id
|
obtained_str_id
|
||||||
))
|
)))
|
||||||
|
|
||||||
|
|
||||||
Talking to Bots with special reply markup
|
Talking to Bots with special reply markup
|
||||||
*****************************************
|
*****************************************
|
||||||
|
|
||||||
|
Generally, you just use the `message.click()
|
||||||
|
<telethon.tl.custom.message.Message.click>` method:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
messages = await client.get_messages('somebot')
|
||||||
|
await messages[0].click(0)
|
||||||
|
|
||||||
|
You can also do it manually.
|
||||||
|
|
||||||
To interact with a message that has a special reply markup, such as
|
To interact with a message that has a special reply markup, such as
|
||||||
`@VoteBot`__ polls, you would use :tl:`GetBotCallbackAnswerRequest`:
|
`@VoteBot`__ polls, you would use :tl:`GetBotCallbackAnswerRequest`:
|
||||||
|
|
||||||
|
@ -47,11 +58,11 @@ To interact with a message that has a special reply markup, such as
|
||||||
|
|
||||||
from telethon.tl.functions.messages import GetBotCallbackAnswerRequest
|
from telethon.tl.functions.messages import GetBotCallbackAnswerRequest
|
||||||
|
|
||||||
client(GetBotCallbackAnswerRequest(
|
loop.run_until_complete(client(GetBotCallbackAnswerRequest(
|
||||||
user_or_chat,
|
user_or_chat,
|
||||||
msg.id,
|
msg.id,
|
||||||
data=msg.reply_markup.rows[wanted_row].buttons[wanted_button].data
|
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
|
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
|
show it visually (button rows, and buttons within each row, each with
|
||||||
|
|
|
@ -12,7 +12,7 @@ Joining a chat or channel
|
||||||
*************************
|
*************************
|
||||||
|
|
||||||
Note that :tl:`Chat` are normal groups, and :tl:`Channel` are a
|
Note that :tl:`Chat` are normal groups, and :tl:`Channel` are a
|
||||||
special form of ``Chat``, which can also be super-groups if
|
special form of :tl:`Chat`, which can also be super-groups if
|
||||||
their ``megagroup`` member is ``True``.
|
their ``megagroup`` member is ``True``.
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,11 +25,11 @@ 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
|
from telethon.tl.functions.channels import JoinChannelRequest
|
||||||
client(JoinChannelRequest(channel))
|
loop.run_until_complete(client(JoinChannelRequest(channel)))
|
||||||
|
|
||||||
# In the same way, you can also leave such channel
|
# In the same way, you can also leave such channel
|
||||||
from telethon.tl.functions.channels import LeaveChannelRequest
|
from telethon.tl.functions.channels import LeaveChannelRequest
|
||||||
client(LeaveChannelRequest(input_channel))
|
loop.run_until_complete(client(LeaveChannelRequest(input_channel)))
|
||||||
|
|
||||||
|
|
||||||
For more on channels, check the `channels namespace`__.
|
For more on channels, check the `channels namespace`__.
|
||||||
|
@ -51,7 +51,9 @@ example, is the ``hash`` of the chat or channel. Now you can use
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from telethon.tl.functions.messages import ImportChatInviteRequest
|
from telethon.tl.functions.messages import ImportChatInviteRequest
|
||||||
updates = client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
|
updates = loop.run_until_complete(
|
||||||
|
client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
Adding someone else to such chat or channel
|
Adding someone else to such chat or channel
|
||||||
|
@ -68,19 +70,19 @@ use is very straightforward, or :tl:`InviteToChannelRequest` for channels:
|
||||||
|
|
||||||
# Note that ``user_to_add`` is NOT the name of the parameter.
|
# 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``).
|
# It's the user you want to add (``user_id=user_to_add``).
|
||||||
client(AddChatUserRequest(
|
loop.run_until_complete(client(AddChatUserRequest(
|
||||||
chat_id,
|
chat_id,
|
||||||
user_to_add,
|
user_to_add,
|
||||||
fwd_limit=10 # Allow the user to see the 10 last messages
|
fwd_limit=10 # Allow the user to see the 10 last messages
|
||||||
))
|
)))
|
||||||
|
|
||||||
# For channels (which includes megagroups)
|
# For channels (which includes megagroups)
|
||||||
from telethon.tl.functions.channels import InviteToChannelRequest
|
from telethon.tl.functions.channels import InviteToChannelRequest
|
||||||
|
|
||||||
client(InviteToChannelRequest(
|
loop.run_until_complete(client(InviteToChannelRequest(
|
||||||
channel,
|
channel,
|
||||||
[users_to_add]
|
[users_to_add]
|
||||||
))
|
)))
|
||||||
|
|
||||||
|
|
||||||
Checking a link without joining
|
Checking a link without joining
|
||||||
|
@ -102,6 +104,14 @@ Retrieving all chat members (channels too)
|
||||||
This method will handle different chat types for you automatically.
|
This method will handle different chat types for you automatically.
|
||||||
|
|
||||||
|
|
||||||
|
Here is the easy way to do it:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
participants = loop.run_until_complete(client.get_participants(group))
|
||||||
|
|
||||||
|
Now we will show how the method works internally.
|
||||||
|
|
||||||
In order to get all the members from a mega-group or channel, you need
|
In order to get all the members from a mega-group or channel, you need
|
||||||
to use :tl:`GetParticipantsRequest`. As we can see it needs an
|
to use :tl:`GetParticipantsRequest`. As we can see it needs an
|
||||||
:tl:`InputChannel`, (passing the mega-group or channel you're going to
|
:tl:`InputChannel`, (passing the mega-group or channel you're going to
|
||||||
|
@ -123,10 +133,9 @@ a fixed limit:
|
||||||
all_participants = []
|
all_participants = []
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
participants = client(GetParticipantsRequest(
|
participants = loop.run_until_complete(client(GetParticipantsRequest(
|
||||||
channel, ChannelParticipantsSearch(''), offset, limit,
|
channel, ChannelParticipantsSearch(''), offset, limit, hash=0
|
||||||
hash=0
|
)))
|
||||||
))
|
|
||||||
if not participants.users:
|
if not participants.users:
|
||||||
break
|
break
|
||||||
all_participants.extend(participants.users)
|
all_participants.extend(participants.users)
|
||||||
|
@ -193,7 +202,7 @@ Giving or revoking admin permissions can be done with the :tl:`EditAdminRequest`
|
||||||
# )
|
# )
|
||||||
|
|
||||||
# Once you have a ChannelAdminRights, invoke it
|
# Once you have a ChannelAdminRights, invoke it
|
||||||
client(EditAdminRequest(channel, user, rights))
|
loop.run_until_complete(client(EditAdminRequest(channel, user, rights)))
|
||||||
|
|
||||||
# User will now be able to change group info, delete other people's
|
# User will now be able to change group info, delete other people's
|
||||||
# messages and pin messages.
|
# messages and pin messages.
|
||||||
|
@ -252,7 +261,7 @@ banned rights of an user through :tl:`EditBannedRequest` and its parameter
|
||||||
embed_links=True
|
embed_links=True
|
||||||
)
|
)
|
||||||
|
|
||||||
client(EditBannedRequest(channel, user, rights))
|
loop.run_until_complete(client(EditBannedRequest(channel, user, rights)))
|
||||||
|
|
||||||
|
|
||||||
Kicking a member
|
Kicking a member
|
||||||
|
@ -267,9 +276,11 @@ is enough:
|
||||||
from telethon.tl.functions.channels import EditBannedRequest
|
from telethon.tl.functions.channels import EditBannedRequest
|
||||||
from telethon.tl.types import ChannelBannedRights
|
from telethon.tl.types import ChannelBannedRights
|
||||||
|
|
||||||
client(EditBannedRequest(channel, user, ChannelBannedRights(
|
loop.run_until_complete(client(EditBannedRequest(
|
||||||
until_date=None,
|
channel, user, ChannelBannedRights(
|
||||||
view_messages=True
|
until_date=None,
|
||||||
|
view_messages=True
|
||||||
|
)
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -291,11 +302,11 @@ use :tl:`GetMessagesViewsRequest`, setting ``increment=True``:
|
||||||
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
|
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
|
||||||
# Obtain `msg_ids' through `.get_messages()` or anyhow. Must be a list.
|
# Obtain `msg_ids' through `.get_messages()` or anyhow. Must be a list.
|
||||||
|
|
||||||
client(GetMessagesViewsRequest(
|
loop.run_until_complete(client(GetMessagesViewsRequest(
|
||||||
peer=channel,
|
peer=channel,
|
||||||
id=msg_ids,
|
id=msg_ids,
|
||||||
increment=True
|
increment=True
|
||||||
))
|
)))
|
||||||
|
|
||||||
|
|
||||||
Note that you can only do this **once or twice a day** per account,
|
Note that you can only do this **once or twice a day** per account,
|
||||||
|
|
|
@ -19,11 +19,12 @@ you should use :tl:`GetFullUser`:
|
||||||
|
|
||||||
from telethon.tl.functions.users import GetFullUserRequest
|
from telethon.tl.functions.users import GetFullUserRequest
|
||||||
|
|
||||||
full = client(GetFullUserRequest(user))
|
async def main():
|
||||||
# or even
|
full = await client(GetFullUserRequest(user))
|
||||||
full = client(GetFullUserRequest('username'))
|
# or even
|
||||||
|
full = await client(GetFullUserRequest('username'))
|
||||||
|
|
||||||
bio = full.about
|
bio = full.about
|
||||||
|
|
||||||
|
|
||||||
See :tl:`UserFull` to know what other fields you can access.
|
See :tl:`UserFull` to know what other fields you can access.
|
||||||
|
@ -39,7 +40,9 @@ request. Omitted fields won't change after invoking :tl:`UpdateProfile`:
|
||||||
|
|
||||||
from telethon.tl.functions.account import UpdateProfileRequest
|
from telethon.tl.functions.account import UpdateProfileRequest
|
||||||
|
|
||||||
client(UpdateProfileRequest(about='This is a test from Telethon'))
|
loop.run_until_complete(client(UpdateProfileRequest(a
|
||||||
|
bout='This is a test from Telethon'
|
||||||
|
)))
|
||||||
|
|
||||||
|
|
||||||
Updating your username
|
Updating your username
|
||||||
|
@ -51,7 +54,7 @@ You need to use :tl:`account.UpdateUsername`:
|
||||||
|
|
||||||
from telethon.tl.functions.account import UpdateUsernameRequest
|
from telethon.tl.functions.account import UpdateUsernameRequest
|
||||||
|
|
||||||
client(UpdateUsernameRequest('new_username'))
|
loop.run_until_complete(client(UpdateUsernameRequest('new_username')))
|
||||||
|
|
||||||
|
|
||||||
Updating your profile photo
|
Updating your profile photo
|
||||||
|
@ -65,6 +68,6 @@ through :tl:`UploadProfilePhoto`:
|
||||||
|
|
||||||
from telethon.tl.functions.photos import UploadProfilePhotoRequest
|
from telethon.tl.functions.photos import UploadProfilePhotoRequest
|
||||||
|
|
||||||
client(UploadProfilePhotoRequest(
|
loop.run_until_complete(client(UploadProfilePhotoRequest(
|
||||||
client.upload_file('/path/to/some/file')
|
client.upload_file('/path/to/some/file')
|
||||||
))
|
)))
|
||||||
|
|
|
@ -13,38 +13,39 @@ Forwarding messages
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Use the `telethon.telegram_client.TelegramClient.forward_messages`
|
Use the `telethon.client.messages.MessageMethods.forward_messages`
|
||||||
friendly method instead unless you have a better reason not to!
|
friendly method instead unless you have a better reason not to!
|
||||||
|
|
||||||
This method automatically accepts either a single message or many of them.
|
This method automatically accepts either a single message or many of them.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# If you only have the message IDs
|
async def main():
|
||||||
client.forward_messages(
|
# If you only have the message IDs
|
||||||
entity, # to which entity you are forwarding the messages
|
await client.forward_messages(
|
||||||
message_ids, # the IDs of the messages (or message) to forward
|
entity, # to which entity you are forwarding the messages
|
||||||
from_entity # who sent the messages?
|
message_ids, # the IDs of the messages (or message) to forward
|
||||||
)
|
from_entity # who sent the messages?
|
||||||
|
)
|
||||||
|
|
||||||
# If you have ``Message`` objects
|
# If you have ``Message`` objects
|
||||||
client.forward_messages(
|
await client.forward_messages(
|
||||||
entity, # to which entity you are forwarding the messages
|
entity, # to which entity you are forwarding the messages
|
||||||
messages # the messages (or message) to forward
|
messages # the messages (or message) to forward
|
||||||
)
|
)
|
||||||
|
|
||||||
# You can also do it manually if you prefer
|
# You can also do it manually if you prefer
|
||||||
from telethon.tl.functions.messages import ForwardMessagesRequest
|
from telethon.tl.functions.messages import ForwardMessagesRequest
|
||||||
|
|
||||||
messages = foo() # retrieve a few messages (or even one, in a list)
|
messages = foo() # retrieve a few messages (or even one, in a list)
|
||||||
from_entity = bar()
|
from_entity = bar()
|
||||||
to_entity = baz()
|
to_entity = baz()
|
||||||
|
|
||||||
client(ForwardMessagesRequest(
|
await client(ForwardMessagesRequest(
|
||||||
from_peer=from_entity, # who sent these messages?
|
from_peer=from_entity, # who sent these messages?
|
||||||
id=[msg.id for msg in messages], # which are the messages?
|
id=[msg.id for msg in messages], # which are the messages?
|
||||||
to_peer=to_entity # who are we forwarding them to?
|
to_peer=to_entity # who are we forwarding them to?
|
||||||
))
|
))
|
||||||
|
|
||||||
The named arguments are there for clarity, although they're not needed because
|
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
|
they appear in order. You can obviously just wrap a single message on the list
|
||||||
|
@ -56,7 +57,7 @@ Searching Messages
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Use the `telethon.telegram_client.TelegramClient.iter_messages`
|
Use the `telethon.client.messages.MessageMethods.iter_messages`
|
||||||
friendly method instead unless you have a better reason not to!
|
friendly method instead unless you have a better reason not to!
|
||||||
|
|
||||||
This method has ``search`` and ``filter`` parameters that will
|
This method has ``search`` and ``filter`` parameters that will
|
||||||
|
@ -71,7 +72,7 @@ into issues_. A valid example would be:
|
||||||
from telethon.tl.types import InputMessagesFilterEmpty
|
from telethon.tl.types import InputMessagesFilterEmpty
|
||||||
|
|
||||||
filter = InputMessagesFilterEmpty()
|
filter = InputMessagesFilterEmpty()
|
||||||
result = client(SearchRequest(
|
result = loop.run_until_complete(client(SearchRequest(
|
||||||
peer=peer, # On which chat/conversation
|
peer=peer, # On which chat/conversation
|
||||||
q='query', # What to search for
|
q='query', # What to search for
|
||||||
filter=filter, # Filter to use (maybe filter for media)
|
filter=filter, # Filter to use (maybe filter for media)
|
||||||
|
@ -84,7 +85,7 @@ into issues_. A valid example would be:
|
||||||
min_id=0, # Minimum message ID
|
min_id=0, # Minimum message ID
|
||||||
from_id=None, # Who must have sent the message (peer)
|
from_id=None, # Who must have sent the message (peer)
|
||||||
hash=0 # Special number to return nothing on no-change
|
hash=0 # Special number to return nothing on no-change
|
||||||
))
|
)))
|
||||||
|
|
||||||
It's important to note that the optional parameter ``from_id`` could have
|
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
|
been omitted (defaulting to ``None``). Changing it to :tl:`InputUserEmpty`, as one
|
||||||
|
@ -99,7 +100,7 @@ you tried setting the ``from_id`` filter, and as the error says, you can't
|
||||||
do that. Leave it set to ``None`` and it should work.
|
do that. Leave it set to ``None`` and it should work.
|
||||||
|
|
||||||
As with every method, make sure you use the right ID/hash combination for
|
As with every method, make sure you use the right ID/hash combination for
|
||||||
your ``InputUser`` or ``InputChat``, or you'll likely run into errors like
|
your :tl:`InputUser` or :tl:`InputChat`, or you'll likely run into errors like
|
||||||
``UserIdInvalidError``.
|
``UserIdInvalidError``.
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,29 +116,25 @@ send yourself the very first sticker you have:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# Get all the sticker sets this user has
|
async def main():
|
||||||
sticker_sets = client(GetAllStickersRequest(0))
|
# Get all the sticker sets this user has
|
||||||
|
from telethon.tl.functions.messages import GetAllStickersRequest
|
||||||
|
sticker_sets = await client(GetAllStickersRequest(0))
|
||||||
|
|
||||||
# Choose a sticker set
|
# Choose a sticker set
|
||||||
sticker_set = sticker_sets.sets[0]
|
from telethon.tl.functions.messages import GetStickerSetRequest
|
||||||
|
from telethon.tl.types import InputStickerSetID
|
||||||
|
sticker_set = sticker_sets.sets[0]
|
||||||
|
|
||||||
# Get the stickers for this sticker set
|
# Get the stickers for this sticker set
|
||||||
stickers = client(GetStickerSetRequest(
|
stickers = await client(GetStickerSetRequest(
|
||||||
stickerset=InputStickerSetID(
|
stickerset=InputStickerSetID(
|
||||||
id=sticker_set.id, access_hash=sticker_set.access_hash
|
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
|
||||||
|
await client.send_file('me', stickers.documents[0])
|
||||||
|
|
||||||
|
|
||||||
.. _issues: https://github.com/LonamiWebs/Telethon/issues/215
|
.. _issues: https://github.com/LonamiWebs/Telethon/issues/215
|
||||||
|
|
|
@ -59,6 +59,11 @@ their methods.
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
.. automodule:: telethon.client.downloads
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
.. automodule:: telethon.client.uploads
|
.. automodule:: telethon.client.uploads
|
||||||
:members:
|
:members:
|
||||||
:undoc-members:
|
:undoc-members:
|
||||||
|
|
|
@ -22,7 +22,7 @@ FILE_PART_X_MISSING=Part {} of the file is missing from storage
|
||||||
FILE_PART_INVALID=The file part number is invalid
|
FILE_PART_INVALID=The file part number is invalid
|
||||||
FIRSTNAME_INVALID=The first name is invalid
|
FIRSTNAME_INVALID=The first name is invalid
|
||||||
INPUT_METHOD_INVALID=The invoked method does not exist anymore or has never existed
|
INPUT_METHOD_INVALID=The invoked method does not exist anymore or has never existed
|
||||||
INPUT_REQUEST_TOO_LONG=The input request was too long. This may be a bug in the library as it can occur when serializing more bytes than it should (likeappending the vector constructor code at the end of a message)
|
INPUT_REQUEST_TOO_LONG=The input request was too long. This may be a bug in the library as it can occur when serializing more bytes than it should (like appending the vector constructor code at the end of a message)
|
||||||
LASTNAME_INVALID=The last name is invalid
|
LASTNAME_INVALID=The last name is invalid
|
||||||
LIMIT_INVALID=An invalid limit was provided. See https://core.telegram.org/api/files#downloading-files
|
LIMIT_INVALID=An invalid limit was provided. See https://core.telegram.org/api/files#downloading-files
|
||||||
LOCATION_INVALID=The location given for a file was invalid. See https://core.telegram.org/api/files#downloading-files
|
LOCATION_INVALID=The location given for a file was invalid. See https://core.telegram.org/api/files#downloading-files
|
||||||
|
|
Loading…
Reference in New Issue
Block a user