Avoid using telethon.sync in the examples

This commit is contained in:
Lonami Exo 2019-08-13 23:33:39 +02:00
parent 61c0e63bbe
commit e1905d0d7a
28 changed files with 283 additions and 217 deletions

View File

@ -8,15 +8,16 @@ use these if possible.
.. code-block:: python
from telethon.sync import TelegramClient
from telethon import TelegramClient
# Remember to use your own values from my.telegram.org!
api_id = 12345
api_hash = '0123456789abcdef0123456789abcdef'
client = TelegramClient('anon', api_id, api_hash)
with TelegramClient('anon', api_id, api_hash) as client:
async def main():
# Getting information about yourself
me = client.get_me()
me = await client.get_me()
# "me" is an User object. You can pretty-print
# any Telegram object with the "stringify" method:
@ -30,20 +31,20 @@ use these if possible.
print(me.phone)
# You can print all the dialogs/conversations that you are part of:
for dialog in client.iter_dialogs():
async for dialog in client.iter_dialogs():
print(dialog.name, 'has ID', dialog.id)
# You can send messages to yourself...
client.send_message('me', 'Hello, myself!')
await client.send_message('me', 'Hello, myself!')
# ...to some chat ID
client.send_message(-100123456, 'Hello, group!')
await client.send_message(-100123456, 'Hello, group!')
# ...to your contacts
client.send_message('+34600123123', 'Hello, friend!')
await client.send_message('+34600123123', 'Hello, friend!')
# ...or even to any username
client.send_message('TelethonChat', 'Hello, Telethon!')
await client.send_message('TelethonChat', 'Hello, Telethon!')
# You can, of course, use markdown in your messages:
message = client.send_message(
message = await client.send_message(
'me',
'This message has **bold**, `code`, __italics__ and '
'a [nice website](https://lonamiwebs.github.io)!',
@ -54,20 +55,23 @@ use these if possible.
print(message.raw_text)
# You can reply to messages directly if you have a message object
message.reply('Cool!')
await message.reply('Cool!')
# Or send files, songs, documents, albums...
client.send_file('me', '/home/me/Pictures/holidays.jpg')
await client.send_file('me', '/home/me/Pictures/holidays.jpg')
# You can print the message history of any chat:
for message in client.iter_messages('me'):
async for message in client.iter_messages('me'):
print(message.id, message.text)
# You can download media from messages, too!
# The method will return the path where the file was saved.
if message.photo:
path = message.download_media()
print('File saved to', path)
path = await message.download_media()
print('File saved to', path) # printed after download is done
with client:
client.loop.run_until_complete(main())
Here, we show how to sign in, get information about yourself, send
@ -77,3 +81,31 @@ files.
You should make sure that you understand what the code shown here
does, take note on how methods are called and used and so on before
proceeding. We will see all the available methods later on.
.. important::
Note that Telethon is an asynchronous library, and as such, you should
get used to it and learn a bit of basic `asyncio`. This will help a lot.
As a quick start, this means you generally want to write all your code
inside some ``async def`` like so:
.. code-block:: python
client = ...
async def do_something(me):
...
async def main():
# Most of your code should go here.
# You can of course make and use your own async def (do_something).
# They only need to be async if they need to await things.
me = await client.get_me()
await do_something(me)
with client:
client.loop.run_until_complete(main())
After you understand this, you may use the ``telethon.sync`` hack if you
want do so (see :ref:`compatibility-and-convenience`), but note you may
run into other issues (iPython, Anaconda, etc. have some issues with it).

View File

@ -49,7 +49,7 @@ We can finally write some code to log into our account!
.. code-block:: python
from telethon.sync import TelegramClient
from telethon import TelegramClient
# Use your own values from my.telegram.org
api_id = 12345
@ -57,7 +57,7 @@ We can finally write some code to log into our account!
# The first parameter is the .session file name (absolute paths allowed)
with TelegramClient('anon', api_id, api_hash) as client:
client.send_message('me', 'Hello, myself!')
client.loop.run_until_complete(client.send_message('me', 'Hello, myself!'))
In the first line, we import the class name so we can create an instance
@ -68,6 +68,16 @@ At last, we create a new `TelegramClient <telethon.client.telegramclient.Telegra
instance and call it ``client``. We can now use the client variable
for anything that we want, such as sending a message to ourselves.
.. note::
Since Telethon is an asynchronous library, you need to ``await``
coroutine functions to have them run (or otherwise, run the loop
until they are complete). In this tiny example, we don't bother
making an ``async def main()``.
See :ref:`mastering-asyncio` to find out more.
Using a ``with`` block is the preferred way to use the library. It will
automatically `start() <telethon.client.auth.AuthMethods.start>` the client,
logging or signing up if necessary.

View File

@ -96,8 +96,12 @@ Instead of this:
.. code-block:: python
me = client.loop.run_until_complete(client.get_me())
print(me.username)
# or, using asyncio's default loop (it's the same)
import asyncio
loop = asyncio.get_event_loop()
loop = asyncio.get_event_loop() # == client.loop
me = loop.run_until_complete(client.get_me())
print(me.username)

View File

@ -102,33 +102,35 @@ you're able to just do this:
.. code-block:: python
# (These examples assume you are inside an "async def")
#
# Dialogs are the "conversations you have open".
# This method returns a list of Dialog, which
# has the .entity attribute and other information.
#
# This part is IMPORTANT, because it feels the entity cache.
dialogs = client.get_dialogs()
dialogs = await client.get_dialogs()
# 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)
# Getting entities through their ID (User, Chat or Channel)
entity = client.get_entity(some_id)
entity = await client.get_entity(some_id)
# You can be more explicit about the type for said ID by wrapping
# it inside a Peer instance. This is recommended but not necessary.
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))
.. note::
@ -212,7 +214,7 @@ wherever needed, so you can even do things like:
.. 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
@ -258,7 +260,7 @@ That means you can do this:
message.is_private
message.chat_id
message.get_chat()
await message.get_chat()
# ...etc
`SenderGetter <telethon.tl.custom.sendergetter.SenderGetter>` is similar:
@ -266,7 +268,7 @@ That means you can do this:
.. code-block:: python
message.user_id
message.get_input_user()
await message.get_input_user()
message.user
# ...etc
@ -285,22 +287,25 @@ applications"? Now do the same with the library. Use what applies:
.. code-block:: python
with client:
# (These examples assume you are inside an "async def")
async with client:
# Does it have an username? Use it!
entity = client.get_entity(username)
entity = await client.get_entity(username)
# Do you have a conversation open with them? Get dialogs.
client.get_dialogs()
await client.get_dialogs()
# Are they participant of some group? Get them.
client.get_participants('TelethonChat')
await client.get_participants('TelethonChat')
# Is the entity the original sender of a forwarded message? Get it.
client.get_messages('TelethonChat', 100)
await client.get_messages('TelethonChat', 100)
# NOW you can use the ID, anywhere!
entity = client.get_entity(123456)
client.send_message(123456, 'Hi!')
await client.send_message(123456, 'Hi!')
entity = await client.get_entity(123456)
print(entity)
Once the library has "seen" the entity, you can use their **integer** ID.
You can't use entities from IDs the library hasn't seen. You must make the

View File

@ -19,7 +19,8 @@ available in :ref:`telethon-errors`, but some examples are:
from telethon import errors
try:
print(client.get_messages(chat)[0].text)
messages = await client.get_messages(chat)
print(messages[0].text)
except errors.FloodWaitError as e:
print('Have to sleep', e.seconds, 'seconds')
time.sleep(e.seconds)

View File

@ -78,8 +78,17 @@ Or we call `client.get_input_entity()
.. code-block:: python
import telethon.sync
peer = client.get_input_entity('someone')
import telethon
async def main():
peer = await client.get_input_entity('someone')
client.loop.run_until_complete(main())
.. note::
Remember that ``await`` must occur inside an ``async def``.
Every full API example assumes you already know and do this.
When you're going to invoke an API method, most require you to pass an
@ -92,7 +101,7 @@ instead:
.. code-block:: python
entity = client.get_entity('someone')
entity = await 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
@ -120,7 +129,7 @@ request we do:
.. code-block:: python
result = client(SendMessageRequest(peer, 'Hello there!'))
result = await client(SendMessageRequest(peer, 'Hello there!'))
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
@ -128,8 +137,8 @@ as you wish. Remember to use the right types! To sum up:
.. code-block:: python
result = client(SendMessageRequest(
client.get_input_entity('username'), 'Hello there!'
result = await client(SendMessageRequest(
await client.get_input_entity('username'), 'Hello there!'
))
@ -137,9 +146,9 @@ This can further be simplified to:
.. code-block:: python
result = client(SendMessageRequest('username', 'Hello there!'))
result = await client(SendMessageRequest('username', 'Hello there!'))
# Or even
result = client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
result = await client(SendMessageRequest(PeerChannel(id), 'Hello there!'))
.. note::
@ -195,7 +204,7 @@ knows all requests directly:
.. code-block:: python
client([
await client([
SendMessageRequest('me', 'Hello'),
SendMessageRequest('me', ', '),
SendMessageRequest('me', 'World'),
@ -212,7 +221,7 @@ and still access the successful results:
from telethon.errors import MultiError
try:
client([
await client([
SendMessageRequest('me', 'Hello'),
SendMessageRequest('me', ''),
SendMessageRequest('me', 'World')

View File

@ -154,7 +154,7 @@ you can save it in a variable directly:
string = '1aaNk8EX-YRfwoRsebUkugFvht6DUPi_Q25UOCzOAqzc...'
with TelegramClient(StringSession(string), api_id, api_hash) as client:
client.send_message('me', 'Hi')
client.loop.run_until_complete(client.send_message('me', 'Hi'))
These strings are really convenient for using in places like Heroku since

View File

@ -8,7 +8,7 @@ does a result have? Well, the easiest thing to do is printing it:
.. code-block:: python
user = client.get_entity('Lonami')
user = await client.get_entity('Lonami')
print(user)
That will show a huge **string** similar to the following:

View File

@ -27,11 +27,11 @@ to, you can make use of the :tl:`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`__.
@ -53,7 +53,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
@ -70,7 +70,7 @@ use is very straightforward, or :tl:`InviteToChannelRequest` for channels:
# 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(
await client(AddChatUserRequest(
chat_id,
user_to_add,
fwd_limit=10 # Allow the user to see the 10 last messages
@ -79,7 +79,7 @@ use is very straightforward, or :tl:`InviteToChannelRequest` for channels:
# For channels (which includes megagroups)
from telethon.tl.functions.channels import InviteToChannelRequest
client(InviteToChannelRequest(
await client(InviteToChannelRequest(
channel,
[users_to_add]
))
@ -127,7 +127,7 @@ Giving or revoking admin permissions can be done with the :tl:`EditAdminRequest`
# )
# Once you have a ChatAdminRights, 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.
@ -135,7 +135,7 @@ Giving or revoking admin permissions can be done with the :tl:`EditAdminRequest`
# In a normal chat, you should do this instead:
from telethon.tl.functions.messages import EditChatAdminRequest
client(EditChatAdminRequest(chat_id, user, is_admin=True))
await client(EditChatAdminRequest(chat_id, user, is_admin=True))
@ -192,7 +192,7 @@ banned rights of a user through :tl:`EditBannedRequest` and its parameter
embed_links=True
)
client(EditBannedRequest(channel, user, rights))
await client(EditBannedRequest(channel, user, rights))
You can use a `datetime.datetime` object for ``until_date=``,
@ -214,7 +214,7 @@ is enough:
from telethon.tl.functions.channels import EditBannedRequest
from telethon.tl.types import ChatBannedRights
client(EditBannedRequest(
await client(EditBannedRequest(
channel, user, ChatBannedRights(
until_date=None,
view_messages=True
@ -240,7 +240,7 @@ use :tl:`GetMessagesViewsRequest`, setting ``increment=True``:
# 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(
await client(GetMessagesViewsRequest(
peer=channel,
id=msg_ids,
increment=True

View File

@ -21,9 +21,9 @@ you should use :tl:`GetFullUser`:
from telethon.tl.functions.users import GetFullUserRequest
full = client(GetFullUserRequest(user))
full = await client(GetFullUserRequest(user))
# or even
full = client(GetFullUserRequest('username'))
full = await client(GetFullUserRequest('username'))
bio = full.about
@ -41,7 +41,7 @@ request. Omitted fields won't change after invoking :tl:`UpdateProfile`:
from telethon.tl.functions.account import UpdateProfileRequest
client(UpdateProfileRequest(
await client(UpdateProfileRequest(
about='This is a test from Telethon'
))
@ -55,7 +55,7 @@ You need to use :tl:`account.UpdateUsername`:
from telethon.tl.functions.account import UpdateUsernameRequest
client(UpdateUsernameRequest('new_username'))
await client(UpdateUsernameRequest('new_username'))
Updating your profile photo
@ -69,6 +69,6 @@ through :tl:`UploadProfilePhoto`:
from telethon.tl.functions.photos import UploadProfilePhotoRequest
client(UploadProfilePhotoRequest(
await client(UploadProfilePhotoRequest(
client.upload_file('/path/to/some/file')
)))

View File

@ -24,7 +24,7 @@ send yourself the very first sticker you have:
# Get all the sticker sets this user has
from telethon.tl.functions.messages import GetAllStickersRequest
sticker_sets = client(GetAllStickersRequest(0))
sticker_sets = await client(GetAllStickersRequest(0))
# Choose a sticker set
from telethon.tl.functions.messages import GetStickerSetRequest
@ -32,14 +32,14 @@ send yourself the very first sticker you have:
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.send_file('me', stickers.documents[0])
await client.send_file('me', stickers.documents[0])
.. _issues: https://github.com/LonamiWebs/Telethon/issues/215

View File

@ -14,15 +14,16 @@ Each mixin has its own methods, which you all can use.
.. code-block:: python
import asyncio
from telethon import TelegramClient
client = TelegramClient(name, api_id, api_hash)
async def main():
client = await TelegramClient(name, api_id, api_hash).start()
# Now you can use all client methods listed below, like for example...
await client.send_message('me', 'Hello to myself!')
asyncio.get_event_loop().run_until_complete(main())
with client:
client.loop.run_until_complete(main())
You **don't** need to import these `AuthMethods`, `MessageMethods`, etc.

View File

@ -50,7 +50,7 @@ And except them as such:
.. code-block:: python
try:
client.send_message(chat, 'Hi')
await client.send_message(chat, 'Hi')
except errors.FloodWaitError as e:
# e.seconds is how many seconds you have
# to wait before making the request again.
@ -98,11 +98,11 @@ This is basic Python knowledge. You should use the dot operator:
.. code-block:: python
me = client.get_me()
me = await client.get_me()
print(me.username)
# ^ we used the dot operator to access the username attribute
result = client(functions.photos.GetUserPhotosRequest(
result = await client(functions.photos.GetUserPhotosRequest(
user_id='me',
offset=0,
max_id=0,

View File

@ -190,11 +190,11 @@ class AccountMethods:
from telethon import errors
try:
with client.takeout() as takeout:
client.get_messages('me') # normal call
takeout.get_messages('me') # wrapped through takeout (less limits)
async with client.takeout() as takeout:
await client.get_messages('me') # normal call
await takeout.get_messages('me') # wrapped through takeout (less limits)
for message in takeout.iter_messages(chat, wait_time=0):
async for message in takeout.iter_messages(chat, wait_time=0):
... # Do something with the message
except errors.TakeoutInitDelayError as e:
@ -233,7 +233,7 @@ class AccountMethods:
Example
.. code-block:: python
client.end_takeout(success=False)
await client.end_takeout(success=False)
"""
try:
async with _TakeoutClient(True, self, None) as takeout:

View File

@ -89,10 +89,10 @@ class AuthMethods:
client = TelegramClient('anon', api_id, api_hash)
# Starting as a bot account
client.start(bot_token=bot_token)
await client.start(bot_token=bot_token)
# Starting as an user account
client.start(phone)
await client.start(phone)
# Please enter the code you received: 12345
# Please enter your password: *******
# (You are now logged in)
@ -306,10 +306,10 @@ class AuthMethods:
.. code-block:: python
phone = '+34 123 123 123'
client.sign_in(phone) # send code
await client.sign_in(phone) # send code
code = input('enter code: ')
client.sign_in(phone, code)
await client.sign_in(phone, code)
"""
me = await self.get_me()
if me:
@ -388,10 +388,10 @@ class AuthMethods:
.. code-block:: python
phone = '+34 123 123 123'
client.send_code_request(phone)
await client.send_code_request(phone)
code = input('enter code: ')
client.sign_up(code, first_name='Anna', last_name='Banana')
await client.sign_up(code, first_name='Anna', last_name='Banana')
"""
me = await self.get_me()
if me:
@ -456,7 +456,7 @@ class AuthMethods:
.. code-block:: python
phone = '+34 123 123 123'
sent = client.send_code_request(phone)
sent = await client.send_code_request(phone)
print(sent)
if sent.phone_registered:
@ -501,7 +501,7 @@ class AuthMethods:
.. code-block:: python
# Note: you will need to login again!
client.log_out()
await client.log_out()
"""
try:
await self(functions.auth.LogOutRequest())
@ -573,10 +573,10 @@ class AuthMethods:
.. code-block:: python
# Setting a password for your account which didn't have
client.edit_2fa(new_password='I_<3_Telethon')
await client.edit_2fa(new_password='I_<3_Telethon')
# Removing the password
client.edit_2fa(current_password='I_<3_Telethon')
await client.edit_2fa(current_password='I_<3_Telethon')
"""
if new_password is None and current_password is None:
return False

View File

@ -40,10 +40,10 @@ class BotMethods:
.. code-block:: python
# Make an inline query to @like
results = client.inline_query('like', 'Do you like Telethon?')
results = await client.inline_query('like', 'Do you like Telethon?')
# Send the first result to some chat
message = results[0].click('TelethonOffTopic')
message = await results[0].click('TelethonOffTopic')
"""
bot = await self.get_input_entity(bot)
result = await self(functions.messages.GetInlineBotResultsRequest(

View File

@ -35,7 +35,7 @@ class ButtonMethods:
from telethon import Button
markup = client.build_reply_markup(Button.inline('hi'))
client.send_message('click me', buttons=markup)
await client.send_message('click me', buttons=markup)
"""
if buttons is None:
return None

View File

@ -406,16 +406,16 @@ class ChatMethods:
.. code-block:: python
# Show all user IDs in a chat
for user in client.iter_participants(chat):
async for user in client.iter_participants(chat):
print(user.id)
# Search by name
for user in client.iter_participants(chat, search='name'):
async for user in client.iter_participants(chat, search='name'):
print(user.username)
# Filter by admins
from telethon.tl.types import ChannelParticipantsAdmins
for user in client.iter_participants(chat, filter=ChannelParticipantsAdmins):
async for user in client.iter_participants(chat, filter=ChannelParticipantsAdmins):
print(user.first_name)
"""
return _ParticipantsIter(
@ -438,7 +438,7 @@ class ChatMethods:
Example
.. code-block:: python
users = client.get_participants(chat)
users = await client.get_participants(chat)
print(users[0].first_name)
for user in users:
@ -562,7 +562,7 @@ class ChatMethods:
Example
.. code-block:: python
for event in client.iter_admin_log(channel):
async for event in client.iter_admin_log(channel):
if event.changed_title:
print('The title changed from', event.old, 'to', event.new)
"""
@ -601,7 +601,7 @@ class ChatMethods:
.. code-block:: python
# Get a list of deleted message events which said "heck"
events = client.get_admin_log(channel, search='heck', delete=True)
events = await client.get_admin_log(channel, search='heck', delete=True)
# Print the old message before it was deleted
print(events[0].old)
@ -643,8 +643,8 @@ class ChatMethods:
.. code-block:: python
# Download all the profile photos of some user
for photo in client.iter_profile_photos(user):
client.download_media(photo)
async for photo in client.iter_profile_photos(user):
await client.download_media(photo)
"""
return _ProfilePhotoIter(
self,
@ -666,10 +666,10 @@ class ChatMethods:
.. code-block:: python
# Get the photos of a channel
photos = client.get_profile_photos(channel)
photos = await client.get_profile_photos(channel)
# Download the oldest photo
client.download_media(photos[-1])
await client.download_media(photos[-1])
"""
return await self.iter_profile_photos(*args, **kwargs).collect()
@ -746,7 +746,7 @@ class ChatMethods:
# Upload a document, showing its progress (most clients ignore this)
async with client.action(chat, 'document') as action:
client.send_file(chat, zip_file, progress_callback=action.progress)
await client.send_file(chat, zip_file, progress_callback=action.progress)
"""
if isinstance(action, str):
try:
@ -841,10 +841,10 @@ class ChatMethods:
.. code-block:: python
# Allowing `user` to pin messages in `chat`
client.edit_admin(chat, user, pin_messages=True)
await client.edit_admin(chat, user, pin_messages=True)
# Granting all permissions except for `add_admins`
client.edit_admin(chat, user, is_admin=True, add_admins=False)
await client.edit_admin(chat, user, is_admin=True, add_admins=False)
"""
entity = await self.get_input_entity(entity)
user = await self.get_input_entity(user)
@ -978,15 +978,15 @@ class ChatMethods:
from datetime import timedelta
# Banning `user` from `chat` for 1 minute
client.edit_permissions(chat, user, timedelta(minutes=1),
view_messages=False)
await client.edit_permissions(chat, user, timedelta(minutes=1),
view_messages=False)
# Banning `user` from `chat` forever
client.edit_permissions(chat, user, view_messages=False)
await client.edit_permissions(chat, user, view_messages=False)
# Kicking someone (ban + un-ban)
client.edit_permissions(chat, user, view_messages=False)
client.edit_permissions(chat, user)
await client.edit_permissions(chat, user, view_messages=False)
await client.edit_permissions(chat, user)
"""
entity = await self.get_input_entity(entity)
if not isinstance(entity, types.InputPeerChannel):
@ -1053,10 +1053,10 @@ class ChatMethods:
.. code-block:: python
# Kick some user from some chat
client.kick_participant(chat, user)
await client.kick_participant(chat, user)
# Leaving chat
client.kick_participant(chat, 'me')
await client.kick_participant(chat, 'me')
"""
entity = await self.get_input_entity(entity)
user = await self.get_input_entity(user)

View File

@ -205,7 +205,7 @@ class DialogMethods:
.. code-block:: python
# Print all dialog IDs and the title, nicely formatted
for dialog in client.iter_dialogs():
async for dialog in client.iter_dialogs():
print('{:>14}: {}'.format(dialog.id, dialog.title))
"""
if archived is not None:
@ -231,20 +231,20 @@ class DialogMethods:
.. code-block:: python
# Get all open conversation, print the title of the first
dialogs = client.get_dialogs()
dialogs = await client.get_dialogs()
first = dialogs[0]
print(first.title)
# Use the dialog somewhere else
client.send_message(first, 'hi')
await client.send_message(first, 'hi')
# Getting only non-archived dialogs (both equivalent)
non_archived = client.get_dialogs(folder=0)
non_archived = client.get_dialogs(archived=False)
non_archived = await client.get_dialogs(folder=0)
non_archived = await client.get_dialogs(archived=False)
# Getting only archived dialogs (both equivalent)
archived = client.get_dialogs(folder=1)
non_archived = client.get_dialogs(archived=True)
archived = await client.get_dialogs(folder=1)
non_archived = await client.get_dialogs(archived=True)
"""
return await self.iter_dialogs(*args, **kwargs).collect()
@ -269,11 +269,11 @@ class DialogMethods:
.. code-block:: python
# Clear all drafts
for draft in client.get_drafts():
draft.delete()
async for draft in client.get_drafts():
await draft.delete()
# Getting the drafts with 'bot1' and 'bot2'
for draft in client.iter_drafts(['bot1', 'bot2']):
async for draft in client.iter_drafts(['bot1', 'bot2']):
print(draft.text)
"""
if entity and not utils.is_list_like(entity):
@ -293,11 +293,11 @@ class DialogMethods:
.. code-block:: python
# Get drafts, print the text of the first
drafts = client.get_drafts()
drafts = await client.get_drafts()
print(drafts[0].text)
# Get the draft in your chat
draft = client.get_drafts('me')
draft = await client.get_drafts('me')
print(drafts.text)
"""
items = await self.iter_drafts(entity).collect()
@ -350,18 +350,18 @@ class DialogMethods:
.. code-block:: python
# Archiving the first 5 dialogs
dialogs = client.get_dialogs(5)
client.edit_folder(dialogs, 1)
dialogs = await client.get_dialogs(5)
await client.edit_folder(dialogs, 1)
# Un-archiving the third dialog (archiving to folder 0)
client.edit_folder(dialog[2], 0)
await client.edit_folder(dialog[2], 0)
# Moving the first dialog to folder 0 and the second to 1
dialogs = client.get_dialogs(2)
client.edit_folder(dialogs, [0, 1])
dialogs = await client.get_dialogs(2)
await client.edit_folder(dialogs, [0, 1])
# Un-archiving all dialogs
client.archive(unpack=1)
await client.archive(unpack=1)
"""
if (entity is None) == (unpack is None):
raise ValueError('You can only set either entities or unpack, not both')
@ -419,11 +419,11 @@ class DialogMethods:
.. code-block:: python
# Deleting the first dialog
dialogs = client.get_dialogs(5)
client.delete_dialog(dialogs[0])
dialogs = await client.get_dialogs(5)
await client.delete_dialog(dialogs[0])
# Leaving a channel by username
client.delete_dialog('username')
await client.delete_dialog('username')
"""
entity = await self.get_input_entity(entity)
if isinstance(entity, types.InputPeerChannel):

View File

@ -196,7 +196,7 @@ class DownloadMethods:
.. code-block:: python
# Download your own profile photo
path = client.download_profile_photo('me')
path = await client.download_profile_photo('me')
print(path)
"""
# hex(crc32(x.encode('ascii'))) for x in
@ -322,11 +322,11 @@ class DownloadMethods:
Example
.. code-block:: python
path = client.download_media(message)
client.download_media(message, filename)
path = await client.download_media(message)
await client.download_media(message, filename)
# or
path = message.download_media()
message.download_media(filename)
path = await message.download_media()
await message.download_media(filename)
"""
# TODO This won't work for messageService
if isinstance(message, types.Message):
@ -406,7 +406,7 @@ class DownloadMethods:
.. code-block:: python
# Download a file and print its header
data = client.download_file(input_file, bytes)
data = await client.download_file(input_file, bytes)
print(data[:16])
"""
if not part_size_kb:
@ -531,11 +531,14 @@ class DownloadMethods:
# Streaming `media` to an output file
# After the iteration ends, the sender is cleaned up
with open('photo.jpg', 'wb') as fd:
for chunk client.iter_download(media):
async for chunk client.iter_download(media):
fd.write(chunk)
# Fetching only the header of a file (32 bytes)
# You should manually close the iterator in this case.
#
# telethon.sync must be imported for this to work,
# and you must not be inside an "async def".
stream = client.iter_download(media, request_size=32)
header = next(stream)
stream.close()

View File

@ -421,24 +421,24 @@ class MessageMethods:
.. code-block:: python
# From most-recent to oldest
for message in client.iter_messages(chat):
async for message in client.iter_messages(chat):
print(message.id, message.text)
# From oldest to most-recent
for message in client.iter_messages(chat, reverse=True):
async for message in client.iter_messages(chat, reverse=True):
print(message.id, message.text)
# Filter by sender
for message in client.iter_messages(chat, from_user='me'):
async for message in client.iter_messages(chat, from_user='me'):
print(message.text)
# Server-side search with fuzzy text
for message in client.iter_messages(chat, search='hello'):
async for message in client.iter_messages(chat, search='hello'):
print(message.id)
# Filter by message type:
from telethon.tl.types import InputMessagesFilterPhotos
for message in client.iter_messages(chat, filter=InputMessagesFilterPhotos):
async for message in client.iter_messages(chat, filter=InputMessagesFilterPhotos):
print(message.photo)
"""
if ids is not None:
@ -482,14 +482,14 @@ class MessageMethods:
# Get 0 photos and print the total to show how many photos there are
from telethon.tl.types import InputMessagesFilterPhotos
photos = client.get_messages(chat, 0, filter=InputMessagesFilterPhotos)
photos = await client.get_messages(chat, 0, filter=InputMessagesFilterPhotos)
print(photos.total)
# Get all the photos
photos = client.get_messages(chat, None, filter=InputMessagesFilterPhotos)
photos = await client.get_messages(chat, None, filter=InputMessagesFilterPhotos)
# Get messages by ID:
message_1337 = client.get_messages(chats, ids=1337)
message_1337 = await client.get_messages(chats, ids=1337)
"""
if len(args) == 1 and 'limit' not in kwargs:
if 'min_id' in kwargs and 'max_id' in kwargs:
@ -605,25 +605,25 @@ class MessageMethods:
.. code-block:: python
# Markdown is the default
client.send_message('lonami', 'Thanks for the **Telethon** library!')
await client.send_message('lonami', 'Thanks for the **Telethon** library!')
# Default to another parse mode
client.parse_mode = 'html'
client.send_message('me', 'Some <b>bold</b> and <i>italic</i> text')
client.send_message('me', 'An <a href="https://example.com">URL</a>')
await client.send_message('me', 'Some <b>bold</b> and <i>italic</i> text')
await client.send_message('me', 'An <a href="https://example.com">URL</a>')
# code and pre tags also work, but those break the documentation :)
client.send_message('me', '<a href="tg://user?id=me">Mentions</a>')
await client.send_message('me', '<a href="tg://user?id=me">Mentions</a>')
# Explicit parse mode
# No parse mode by default
client.parse_mode = None
# ...but here I want markdown
client.send_message('me', 'Hello, **world**!', parse_mode='md')
await client.send_message('me', 'Hello, **world**!', parse_mode='md')
# ...and here I need HTML
client.send_message('me', 'Hello, <i>world</i>!', parse_mode='html')
await client.send_message('me', 'Hello, <i>world</i>!', parse_mode='html')
# If you logged in as a bot account, you can send buttons
from telethon import events, Button
@ -633,25 +633,25 @@ class MessageMethods:
await event.edit('Thank you for clicking {}!'.format(event.data))
# Single inline button
client.send_message(chat, 'A single button, with "clk1" as data',
buttons=Button.inline('Click me', b'clk1'))
await client.send_message(chat, 'A single button, with "clk1" as data',
buttons=Button.inline('Click me', b'clk1'))
# Matrix of inline buttons
client.send_message(chat, 'Pick one from this grid', buttons=[
await client.send_message(chat, 'Pick one from this grid', buttons=[
[Button.inline('Left'), Button.inline('Right')],
[Button.url('Check this site!', 'https://lonamiwebs.github.io')]
])
# Reply keyboard
client.send_message(chat, 'Welcome', buttons=[
await client.send_message(chat, 'Welcome', buttons=[
Button.text('Thanks!', resize=True, single_use=True),
Button.request_phone('Send phone'),
Button.request_location('Send location')
])
# Forcing replies or clearing buttons.
client.send_message(chat, 'Reply to me', buttons=Button.force_reply())
client.send_message(chat, 'Bye Keyboard!', buttons=Button.clear())
await client.send_message(chat, 'Reply to me', buttons=Button.force_reply())
await client.send_message(chat, 'Bye Keyboard!', buttons=Button.clear())
"""
if file is not None:
return await self.send_file(
@ -788,19 +788,19 @@ class MessageMethods:
.. code-block:: python
# a single one
client.forward_messages(chat, message)
await client.forward_messages(chat, message)
# or
client.forward_messages(chat, message_id, from_chat)
await client.forward_messages(chat, message_id, from_chat)
# or
message.forward_to(chat)
await message.forward_to(chat)
# multiple
client.forward_messages(chat, messages)
await client.forward_messages(chat, messages)
# or
client.forward_messages(chat, message_ids, from_chat)
await client.forward_messages(chat, message_ids, from_chat)
# Forwarding as a copy
client.send_message(chat, message)
await client.send_message(chat, message)
"""
single = not utils.is_list_like(messages)
if single:
@ -945,13 +945,13 @@ class MessageMethods:
Example
.. code-block:: python
message = client.send_message(chat, 'hello')
message = await client.send_message(chat, 'hello')
client.edit_message(chat, message, 'hello!')
await client.edit_message(chat, message, 'hello!')
# or
client.edit_message(chat, message.id, 'hello!!')
await client.edit_message(chat, message.id, 'hello!!')
# or
client.edit_message(message, 'hello!!!')
await client.edit_message(message, 'hello!!!')
"""
if isinstance(entity, types.InputBotInlineMessageID):
text = message
@ -1036,7 +1036,7 @@ class MessageMethods:
Example
.. code-block:: python
client.delete_messages(chat, messages)
await client.delete_messages(chat, messages)
"""
if not utils.is_list_like(message_ids):
message_ids = (message_ids,)
@ -1097,11 +1097,11 @@ class MessageMethods:
.. code-block:: python
# using a Message object
client.send_read_acknowledge(chat, message)
await client.send_read_acknowledge(chat, message)
# ...or using the int ID of a Message
client.send_read_acknowledge(chat, message_id)
await client.send_read_acknowledge(chat, message_id)
# ...or passing a list of messages to mark as read
client.send_read_acknowledge(chat, messages)
await client.send_read_acknowledge(chat, messages)
"""
if max_id is None:
if not message:
@ -1158,8 +1158,8 @@ class MessageMethods:
.. code-block:: python
# Send and pin a message to annoy everyone
message = client.send_message(chat, 'Pinotifying is fun!')
client.pin_message(chat, message, notify=True)
message = await client.send_message(chat, 'Pinotifying is fun!')
await client.pin_message(chat, message, notify=True)
"""
if not message:
message = 0

View File

@ -401,7 +401,7 @@ class TelegramBaseClient(abc.ABC):
.. code-block:: python
try:
client.connect()
await client.connect()
except OSError:
print('Failed to connect')
"""
@ -451,7 +451,7 @@ class TelegramBaseClient(abc.ABC):
.. code-block:: python
# You don't need to use this if you used "with client"
client.disconnect()
await client.disconnect()
"""
if self._loop.is_running():
return self._disconnect_coro()

View File

@ -59,7 +59,7 @@ class UpdateMethods:
#
# You will still receive updates, since this prevents the
# script from exiting.
client.run_until_disconnected()
await client.run_until_disconnected()
"""
if self.loop.is_running():
return self._run_until_disconnected()
@ -218,7 +218,7 @@ class UpdateMethods:
Example
.. code-block:: python
client.catch_up()
await client.catch_up()
"""
pts, date = self._state_cache[None]
if not pts:

View File

@ -237,22 +237,22 @@ class UploadMethods:
.. code-block:: python
# Normal files like photos
client.send_file(chat, '/my/photos/me.jpg', caption="It's me!")
await client.send_file(chat, '/my/photos/me.jpg', caption="It's me!")
# or
client.send_message(chat, "It's me!", file='/my/photos/me.jpg')
await client.send_message(chat, "It's me!", file='/my/photos/me.jpg')
# Voice notes or round videos
client.send_file(chat, '/my/songs/song.mp3', voice_note=True)
client.send_file(chat, '/my/videos/video.mp4', video_note=True)
await client.send_file(chat, '/my/songs/song.mp3', voice_note=True)
await client.send_file(chat, '/my/videos/video.mp4', video_note=True)
# Custom thumbnails
client.send_file(chat, '/my/documents/doc.txt', thumb='photo.jpg')
await client.send_file(chat, '/my/documents/doc.txt', thumb='photo.jpg')
# Only documents
client.send_file(chat, '/my/photos/photo.png', force_document=True)
await client.send_file(chat, '/my/photos/photo.png', force_document=True)
# Albums
client.send_file(chat, [
await client.send_file(chat, [
'/my/photos/holiday1.jpg',
'/my/photos/holiday2.jpg',
'/my/drawings/portrait.png'
@ -467,17 +467,17 @@ class UploadMethods:
.. code-block:: python
# Photos as photo and document
file = client.upload_file('photo.jpg')
client.send_file(chat, file) # sends as photo
client.send_file(chat, file, force_document=True) # sends as document
file = await client.upload_file('photo.jpg')
await client.send_file(chat, file) # sends as photo
await client.send_file(chat, file, force_document=True) # sends as document
file.name = 'not a photo.jpg'
client.send_file(chat, file, force_document=True) # document, new name
await client.send_file(chat, file, force_document=True) # document, new name
# As song or as voice note
file = client.upload_file('song.ogg')
client.send_file(chat, file) # sends as song
client.send_file(chat, file, voice_note=True) # sends as voice note
file = await client.upload_file('song.ogg')
await client.send_file(chat, file) # sends as song
await client.send_file(chat, file, voice_note=True) # sends as voice note
"""
if isinstance(file, (types.InputFile, types.InputFileBig)):
return file # Already uploaded

View File

@ -128,7 +128,8 @@ class UserMethods:
Example
.. code-block:: python
print(client.get_me().username)
me = await client.get_me()
print(me.username)
"""
if input_peer and self._self_input_peer:
return self._self_input_peer
@ -154,7 +155,7 @@ class UserMethods:
Example
.. code-block:: python
if client.is_bot():
if await client.is_bot():
print('Beep')
else:
print('Hello')
@ -171,10 +172,10 @@ class UserMethods:
Example
.. code-block:: python
if not client.is_user_authorized():
client.send_code_request(phone)
if not await client.is_user_authorized():
await client.send_code_request(phone)
code = input('enter code: ')
client.sign_in(phone, code)
await client.sign_in(phone, code)
"""
if self._authorized is None:
try:
@ -227,20 +228,20 @@ class UserMethods:
from telethon import utils
me = client.get_entity('me')
me = await client.get_entity('me')
print(utils.get_display_name(me))
chat = client.get_input_entity('username')
for message in client.iter_messages(chat):
chat = await client.get_input_entity('username')
async for message in client.iter_messages(chat):
...
# Note that you could have used the username directly, but it's
# good to use get_input_entity if you will reuse it a lot.
for message in client.iter_messages('username'):
async for message in client.iter_messages('username'):
...
# Note that for this to work the phone number must be in your contacts
some_id = client.get_peer_id('+34123456789')
some_id = await client.get_peer_id('+34123456789')
"""
single = not utils.is_list_like(entity)
if single:
@ -360,10 +361,10 @@ class UserMethods:
# If you're going to use "username" often in your code
# (make a lot of calls), consider getting its input entity
# once, and then using the "user" everywhere instead.
user = client.get_input_entity('username')
user = await client.get_input_entity('username')
# The same applies to IDs, chats or channels.
chat = client.get_input_entity(-123456789)
chat = await client.get_input_entity(-123456789)
"""
# Short-circuit if the input parameter directly maps to an InputPeer
try:
@ -444,7 +445,7 @@ class UserMethods:
Example
.. code-block:: python
print(client.get_peer_id('me'))
print(await client.get_peer_id('me'))
"""
if isinstance(peer, int):
return utils.get_peer_id(peer, add_mark=add_mark)

View File

@ -167,7 +167,7 @@ class TotalList(list):
# Telethon returns these lists in some cases (for example,
# only when a chunk is returned, but the "total" count
# is available).
result = client.get_messages(chat, limit=10)
result = await client.get_messages(chat, limit=10)
print(result.total) # large number
print(len(result)) # 10

View File

@ -762,7 +762,7 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC):
>>> # [button1] [button2]
>>> # [ button3 ]
>>> # [button4] [button5]
>>> message.click(2) # index
>>> await message.click(2) # index
j (`int`):
Clicks the button at position (i, j), these being the
@ -772,7 +772,7 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC):
>>> # [button1] [button2]
>>> # [ button3 ]
>>> # [button4] [button5]
>>> message.click(0, 1) # (row, column)
>>> await message.click(0, 1) # (row, column)
This is equivalent to ``message.buttons[0][1].click()``.
@ -799,16 +799,16 @@ class Message(ChatGetter, SenderGetter, TLObject, abc.ABC):
.. code-block:: python
# Click the first button
message.click(0)
await message.click(0)
# Click some row/column
message.click(row, column)
await message.click(row, column)
# Click by text
message.click(text='👍')
await message.click(text='👍')
# Click by data
message.click(data=b'payload')
await message.click(data=b'payload')
"""
if not self._client:
return

View File

@ -1177,14 +1177,14 @@ def encode_waveform(waveform):
file = 'my.ogg'
# Send 'my.ogg' with a ascending-triangle waveform
client.send_file(chat, file, attributes=[types.DocumentAttributeAudio(
await client.send_file(chat, file, attributes=[types.DocumentAttributeAudio(
duration=7,
voice=True,
waveform=utils.encode_waveform(bytes(range(2 ** 5)) # 2**5 because 5-bit
)]
# Send 'my.ogg' with a square waveform
client.send_file(chat, file, attributes=[types.DocumentAttributeAudio(
await client.send_file(chat, file, attributes=[types.DocumentAttributeAudio(
duration=7,
voice=True,
waveform=utils.encode_waveform(bytes((31, 31, 15, 15, 15, 15, 31, 31)) * 4)