mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2025-08-04 04:00:18 +03:00
Document asyncio better (#456)
This commit is contained in:
parent
5cb3a9af36
commit
8bf140ca74
|
@ -42,7 +42,7 @@ your disk. This is by default a database file using Python's ``sqlite3``.
|
|||
Before using the client, you must be connected to Telegram.
|
||||
Doing so is very easy:
|
||||
|
||||
``client.connect() # Must return True, otherwise, try again``
|
||||
``await 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:
|
||||
|
@ -54,8 +54,8 @@ If you're not authorized, you need to ``.sign_in()``:
|
|||
.. code-block:: python
|
||||
|
||||
phone_number = '+34600000000'
|
||||
client.send_code_request(phone_number)
|
||||
myself = client.sign_in(phone_number, input('Enter code: '))
|
||||
await client.send_code_request(phone_number)
|
||||
myself = await 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.
|
||||
|
@ -78,10 +78,10 @@ As a full example:
|
|||
.. code-block:: python
|
||||
|
||||
client = TelegramClient('anon', api_id, api_hash)
|
||||
assert client.connect()
|
||||
assert await client.connect()
|
||||
if not client.is_user_authorized():
|
||||
client.send_code_request(phone_number)
|
||||
me = client.sign_in(phone_number, input('Enter code: '))
|
||||
await client.send_code_request(phone_number)
|
||||
me = await client.sign_in(phone_number, input('Enter code: '))
|
||||
|
||||
|
||||
All of this, however, can be done through a call to ``.start()``:
|
||||
|
@ -89,7 +89,7 @@ All of this, however, can be done through a call to ``.start()``:
|
|||
.. code-block:: python
|
||||
|
||||
client = TelegramClient('anon', api_id, api_hash)
|
||||
client.start()
|
||||
await client.start()
|
||||
|
||||
|
||||
The code shown is just what ``.start()`` will be doing behind the scenes
|
||||
|
@ -103,6 +103,19 @@ 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()``.
|
||||
|
||||
Assuming you've written all of this in a ``async def main():``, you can
|
||||
run it with:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import asyncio
|
||||
|
||||
async def main():
|
||||
...
|
||||
|
||||
asyncio.get_event_loop().run_until_complete(main())
|
||||
|
||||
|
||||
.. 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
|
||||
|
@ -141,9 +154,9 @@ account, calling :meth:`telethon.TelegramClient.sign_in` will raise a
|
|||
|
||||
client.sign_in(phone)
|
||||
try:
|
||||
client.sign_in(code=input('Enter code: '))
|
||||
await client.sign_in(code=input('Enter code: '))
|
||||
except SessionPasswordNeededError:
|
||||
client.sign_in(password=getpass.getpass())
|
||||
await client.sign_in(password=getpass.getpass())
|
||||
|
||||
|
||||
The mentioned ``.start()`` method will handle this for you as well, but
|
||||
|
@ -168,7 +181,7 @@ take as example the following code snippet:
|
|||
pw_salted = salt + pw + salt
|
||||
pw_hash = sha256(pw_salted).digest()
|
||||
|
||||
result = client(account.UpdatePasswordSettingsRequest(
|
||||
result = await client(account.UpdatePasswordSettingsRequest(
|
||||
current_password_hash=salt,
|
||||
new_settings=PasswordInputSettings(
|
||||
new_salt=salt,
|
||||
|
|
|
@ -32,17 +32,17 @@ you're able to just do this:
|
|||
# Dialogs are the "conversations you have open".
|
||||
# This method returns a list of Dialog, which
|
||||
# has the .entity attribute and other information.
|
||||
dialogs = client.get_dialogs(limit=200)
|
||||
dialogs = await client.get_dialogs(limit=200)
|
||||
|
||||
# All of these work and do the same.
|
||||
lonami = client.get_entity('lonami')
|
||||
lonami = client.get_entity('t.me/lonami')
|
||||
lonami = client.get_entity('https://telegram.dog/lonami')
|
||||
lonami = await client.get_entity('lonami')
|
||||
lonami = await client.get_entity('t.me/lonami')
|
||||
lonami = await client.get_entity('https://telegram.dog/lonami')
|
||||
|
||||
# Other kind of entities.
|
||||
channel = client.get_entity('telegram.me/joinchat/AAAAAEkk2WdoDrB4-Q8-gg')
|
||||
contact = client.get_entity('+34xxxxxxxxx')
|
||||
friend = client.get_entity(friend_id)
|
||||
channel = await client.get_entity('telegram.me/joinchat/AAAAAEkk2WdoDrB4-Q8-gg')
|
||||
contact = await client.get_entity('+34xxxxxxxxx')
|
||||
friend = await client.get_entity(friend_id)
|
||||
|
||||
# Using Peer/InputPeer (note that the API may return these)
|
||||
# users, chats and channels may all have the same ID, so it's
|
||||
|
@ -51,9 +51,9 @@ you're able to just do this:
|
|||
# NOTICE how the IDs *must* be wrapped inside a Peer() so the
|
||||
# library knows their type.
|
||||
from telethon.tl.types import PeerUser, PeerChat, PeerChannel
|
||||
my_user = client.get_entity(PeerUser(some_id))
|
||||
my_chat = client.get_entity(PeerChat(some_id))
|
||||
my_channel = client.get_entity(PeerChannel(some_id))
|
||||
my_user = await client.get_entity(PeerUser(some_id))
|
||||
my_chat = await client.get_entity(PeerChat(some_id))
|
||||
my_channel = await client.get_entity(PeerChannel(some_id))
|
||||
|
||||
|
||||
.. warning::
|
||||
|
@ -122,7 +122,7 @@ library, the raw requests you make to the API are also able to call
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
client(SendMessageRequest('username', 'hello'))
|
||||
await client(SendMessageRequest('username', 'hello'))
|
||||
|
||||
The library will call the ``.resolve()`` method of the request, which will
|
||||
resolve ``'username'`` with the appropriated :tl:`InputPeer`. Don't worry if
|
||||
|
|
|
@ -27,7 +27,7 @@ Creating a client
|
|||
api_hash = '0123456789abcdef0123456789abcdef'
|
||||
|
||||
client = TelegramClient('session_name', api_id, api_hash)
|
||||
client.start()
|
||||
await client.start()
|
||||
|
||||
**More details**: :ref:`creating-a-client`
|
||||
|
||||
|
@ -38,30 +38,30 @@ Basic Usage
|
|||
.. code-block:: python
|
||||
|
||||
# Getting information about yourself
|
||||
print(client.get_me().stringify())
|
||||
print((await client.get_me()).stringify())
|
||||
|
||||
# Sending a message (you can use 'me' or 'self' to message yourself)
|
||||
client.send_message('username', 'Hello World from Telethon!')
|
||||
await client.send_message('username', 'Hello World from Telethon!')
|
||||
|
||||
# Sending a file
|
||||
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
||||
await client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
||||
|
||||
# Retrieving messages from a chat
|
||||
from telethon import utils
|
||||
for message in client.get_message_history('username', limit=10):
|
||||
async for message in client.get_message_history('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):
|
||||
async for dialog in client.get_dialogs(limit=10):
|
||||
print(utils.get_display_name(dialog.entity), dialog.draft.message)
|
||||
|
||||
# Downloading profile photos (default path is the working directory)
|
||||
client.download_profile_photo('username')
|
||||
await 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_message_history('username')
|
||||
client.download_media(messages[0])
|
||||
messages = await client.get_message_history('username')
|
||||
await client.download_media(messages[0])
|
||||
|
||||
**More details**: :ref:`telegram-client`
|
||||
|
||||
|
@ -71,17 +71,18 @@ Handling Updates
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
import asyncio
|
||||
from telethon import events
|
||||
|
||||
# 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!')
|
||||
async def handler(event):
|
||||
await event.reply('Hello!')
|
||||
|
||||
# If you want to handle updates you can't let the script end.
|
||||
input('Press enter to exit.')
|
||||
asyncio.get_event_loop().run_forever()
|
||||
|
||||
**More details**: :ref:`working-with-updates`
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ how the library refers to either of these:
|
|||
# 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')
|
||||
lonami = await 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
|
||||
|
@ -56,21 +56,21 @@ Many other common methods for quick scripts are also available:
|
|||
.. code-block:: python
|
||||
|
||||
# Note that you can use 'me' or 'self' to message yourself
|
||||
client.send_message('username', 'Hello World from Telethon!')
|
||||
await client.send_message('username', 'Hello World from Telethon!')
|
||||
|
||||
client.send_file('username', '/home/myself/Pictures/holidays.jpg')
|
||||
await 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.get_message_history('username', limit=10):
|
||||
async for message in client.get_message_history('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):
|
||||
async for dialog in client.get_dialogs(limit=10):
|
||||
print(utils.get_display_name(dialog.entity), dialog.draft.message)
|
||||
|
||||
# Default path is the working directory
|
||||
client.download_profile_photo('username')
|
||||
await client.download_profile_photo('username')
|
||||
|
||||
# Call .disconnect() when you're done
|
||||
client.disconnect()
|
||||
|
|
|
@ -30,17 +30,18 @@ Getting Started
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
import asyncio
|
||||
from telethon import TelegramClient, events
|
||||
|
||||
client = TelegramClient(..., update_workers=1, spawn_read_thread=False)
|
||||
client.start()
|
||||
await client.start()
|
||||
|
||||
@client.on(events.NewMessage)
|
||||
def my_event_handler(event):
|
||||
async def my_event_handler(event):
|
||||
if 'hello' in event.raw_text:
|
||||
event.reply('hi!')
|
||||
await event.reply('hi!')
|
||||
|
||||
client.idle()
|
||||
asyncio.get_event_loop().run_forever()
|
||||
|
||||
|
||||
Not much, but there might be some things unclear. What does this code do?
|
||||
|
@ -50,7 +51,7 @@ Not much, but there might be some things unclear. What does this code do?
|
|||
from telethon import TelegramClient, events
|
||||
|
||||
client = TelegramClient(..., update_workers=1, spawn_read_thread=False)
|
||||
client.start()
|
||||
await client.start()
|
||||
|
||||
|
||||
This is normal initialization (of course, pass session name, API ID and hash).
|
||||
|
@ -67,9 +68,9 @@ the callback function you're about to define will be called:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
def my_event_handler(event):
|
||||
async def my_event_handler(event):
|
||||
if 'hello' in event.raw_text:
|
||||
event.reply('hi!')
|
||||
await event.reply('hi!')
|
||||
|
||||
|
||||
If a ``NewMessage`` event occurs, and ``'hello'`` is in the text of the
|
||||
|
@ -77,10 +78,10 @@ message, we ``reply`` to the event with a ``'hi!'`` message.
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
client.idle()
|
||||
asyncio.get_event_loop().run_forever()
|
||||
|
||||
|
||||
Finally, this tells the client that we're done with our code, and want
|
||||
Finally, this tells the script that we're done with our code, and want
|
||||
to listen for all these events to occur. Of course, you might want to
|
||||
do other things instead idling. For this refer to :ref:`update-modes`.
|
||||
|
||||
|
@ -119,17 +120,17 @@ for example:
|
|||
# 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):
|
||||
async def normal_handler(event):
|
||||
if 'roll' in event.raw_text:
|
||||
event.reply(str(random.randint(1, 6)))
|
||||
await 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):
|
||||
async def admin_handler(event):
|
||||
if event.raw_text.startswith('eval'):
|
||||
expression = event.raw_text.replace('eval', '').strip()
|
||||
event.reply(str(ast.literal_eval(expression)))
|
||||
await event.reply(str(ast.literal_eval(expression)))
|
||||
|
||||
|
||||
You can pass one or more chats to the ``chats`` parameter (as a list or tuple),
|
||||
|
@ -167,15 +168,15 @@ propagation of the update through your handlers to stop:
|
|||
from telethon.events import StopPropagation
|
||||
|
||||
@client.on(events.NewMessage)
|
||||
def _(event):
|
||||
async def _(event):
|
||||
# ... some conditions
|
||||
event.delete()
|
||||
await event.delete()
|
||||
|
||||
# Other handlers won't have an event to work with
|
||||
raise StopPropagation
|
||||
|
||||
@client.on(events.NewMessage)
|
||||
def _(event):
|
||||
async def _(event):
|
||||
# Will never be reached, because it is the second handler
|
||||
# in the chain.
|
||||
pass
|
||||
|
|
|
@ -32,4 +32,4 @@ times, in this case, ``22222`` so we can hardcode that:
|
|||
|
||||
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')
|
||||
await client.start(phone='9996621234', code_callback=lambda: '22222')
|
||||
|
|
|
@ -19,7 +19,7 @@ not *interact* with a voting message), by making use of the
|
|||
|
||||
from telethon.tl.functions.messages import GetInlineBotResultsRequest
|
||||
|
||||
bot_results = client(GetInlineBotResultsRequest(
|
||||
bot_results = await client(GetInlineBotResultsRequest(
|
||||
bot, user_or_chat, 'query', ''
|
||||
))
|
||||
|
||||
|
@ -30,7 +30,7 @@ And you can select any of their results by using
|
|||
|
||||
from telethon.tl.functions.messages import SendInlineBotResultRequest
|
||||
|
||||
client(SendInlineBotResultRequest(
|
||||
await client(SendInlineBotResultRequest(
|
||||
get_input_peer(user_or_chat),
|
||||
obtained_query_id,
|
||||
obtained_str_id
|
||||
|
@ -47,7 +47,7 @@ To interact with a message that has a special reply markup, such as
|
|||
|
||||
from telethon.tl.functions.messages import GetBotCallbackAnswerRequest
|
||||
|
||||
client(GetBotCallbackAnswerRequest(
|
||||
await client(GetBotCallbackAnswerRequest(
|
||||
user_or_chat,
|
||||
msg.id,
|
||||
data=msg.reply_markup.rows[wanted_row].buttons[wanted_button].data
|
||||
|
|
|
@ -26,11 +26,11 @@ to, you can make use of the `JoinChannelRequest`__ to join such channel:
|
|||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.channels import JoinChannelRequest
|
||||
client(JoinChannelRequest(channel))
|
||||
await client(JoinChannelRequest(channel))
|
||||
|
||||
# In the same way, you can also leave such channel
|
||||
from telethon.tl.functions.channels import LeaveChannelRequest
|
||||
client(LeaveChannelRequest(input_channel))
|
||||
await client(LeaveChannelRequest(input_channel))
|
||||
|
||||
|
||||
For more on channels, check the `channels namespace`__.
|
||||
|
@ -49,7 +49,7 @@ example, is the ``hash`` of the chat or channel. Now you can use
|
|||
.. code-block:: python
|
||||
|
||||
from telethon.tl.functions.messages import ImportChatInviteRequest
|
||||
updates = client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
|
||||
updates = await client(ImportChatInviteRequest('AAAAAEHbEkejzxUjAUCfYg'))
|
||||
|
||||
|
||||
Adding someone else to such chat or channel
|
||||
|
@ -64,7 +64,7 @@ use is very straightforward, or `InviteToChannelRequest`__ for channels:
|
|||
# For normal chats
|
||||
from telethon.tl.functions.messages import AddChatUserRequest
|
||||
|
||||
client(AddChatUserRequest(
|
||||
await client(AddChatUserRequest(
|
||||
chat_id,
|
||||
user_to_add,
|
||||
fwd_limit=10 # Allow the user to see the 10 last messages
|
||||
|
@ -73,7 +73,7 @@ use is very straightforward, or `InviteToChannelRequest`__ for channels:
|
|||
# For channels
|
||||
from telethon.tl.functions.channels import InviteToChannelRequest
|
||||
|
||||
client(InviteToChannelRequest(
|
||||
await client(InviteToChannelRequest(
|
||||
channel,
|
||||
[users_to_add]
|
||||
))
|
||||
|
@ -122,7 +122,7 @@ a fixed limit:
|
|||
all_participants = []
|
||||
|
||||
while True:
|
||||
participants = client(GetParticipantsRequest(
|
||||
participants = await client(GetParticipantsRequest(
|
||||
channel, ChannelParticipantsSearch(''), offset, limit,
|
||||
hash=0
|
||||
))
|
||||
|
@ -197,7 +197,7 @@ Giving or revoking admin permissions can be done with the `EditAdminRequest`__:
|
|||
# )
|
||||
|
||||
# Once you have a ChannelAdminRights, invoke it
|
||||
client(EditAdminRequest(channel, user, rights))
|
||||
await client(EditAdminRequest(channel, user, rights))
|
||||
|
||||
# User will now be able to change group info, delete other people's
|
||||
# messages and pin messages.
|
||||
|
@ -230,7 +230,7 @@ use `GetMessagesViewsRequest`__, setting ``increment=True``:
|
|||
# Obtain `channel' through dialogs or through client.get_entity() or anyhow.
|
||||
# Obtain `msg_ids' through `.get_message_history()` or anyhow. Must be a list.
|
||||
|
||||
client(GetMessagesViewsRequest(
|
||||
await client(GetMessagesViewsRequest(
|
||||
peer=channel,
|
||||
id=msg_ids,
|
||||
increment=True
|
||||
|
|
|
@ -28,7 +28,7 @@ Message*s*, plural) *always*, since it is more powerful, as follows:
|
|||
from_entity = bar()
|
||||
to_entity = baz()
|
||||
|
||||
client(ForwardMessagesRequest(
|
||||
await 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?
|
||||
|
@ -51,7 +51,7 @@ into issues_. A valid example would be:
|
|||
from telethon.tl.types import InputMessagesFilterEmpty
|
||||
|
||||
filter = InputMessagesFilterEmpty()
|
||||
result = client(SearchRequest(
|
||||
result = await client(SearchRequest(
|
||||
peer=peer, # On which chat/conversation
|
||||
q='query', # What to search for
|
||||
filter=filter, # Filter to use (maybe filter for media)
|
||||
|
@ -95,20 +95,20 @@ send yourself the very first sticker you have:
|
|||
.. code-block:: python
|
||||
|
||||
# Get all the sticker sets this user has
|
||||
sticker_sets = client(GetAllStickersRequest(0))
|
||||
sticker_sets = await client(GetAllStickersRequest(0))
|
||||
|
||||
# Choose a sticker set
|
||||
sticker_set = sticker_sets.sets[0]
|
||||
|
||||
# Get the stickers for this sticker set
|
||||
stickers = client(GetStickerSetRequest(
|
||||
stickers = await 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(
|
||||
await client(SendMediaRequest(
|
||||
peer=client.get_me(),
|
||||
media=InputMediaDocument(
|
||||
id=InputDocument(
|
||||
|
|
|
@ -19,6 +19,18 @@ when you upgrade!
|
|||
looking for the method reference, you should check :ref:`telethon-package`.
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
We assume that you have some experience working with ``asyncio``,
|
||||
if you don't you should probably use the threaded version of the
|
||||
library, or either learn how to use ``asyncio``. All the code
|
||||
here assumes you're writing the code inside an ``async def`` so
|
||||
we can use ``await`` across the examples.
|
||||
|
||||
Then you can ``import asyncio`` and run
|
||||
``asyncio.get_event_loop().run_until_complete(my_method())``
|
||||
|
||||
|
||||
What is this?
|
||||
*************
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user