mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-11-01 00:17:47 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			761 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			761 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| .. _telegram-client-example:
 | |
| 
 | |
| 
 | |
| ========================
 | |
| Examples with the Client
 | |
| ========================
 | |
| 
 | |
| This section explores the methods defined in the :ref:`telegram-client`
 | |
| with some practical examples. The section assumes that you have imported
 | |
| the ``telethon.sync`` package and that you have a client ready to use.
 | |
| 
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     There are some very common errors (such as forgetting to add
 | |
|     ``import telethon.sync``) for newcomers to ``asyncio``:
 | |
| 
 | |
|     .. code-block:: python
 | |
| 
 | |
|         # AttributeError: 'coroutine' object has no attribute 'first_name'
 | |
|         print(client.get_me().first_name)
 | |
| 
 | |
|         # TypeError: 'AsyncGenerator' object is not iterable
 | |
|         for message in client.iter_messages('me'):
 | |
|             ...
 | |
| 
 | |
|         # RuntimeError: This event loop is already running
 | |
|         with client.conversation('me') as conv:
 | |
|             ...
 | |
| 
 | |
|     That error means you're probably inside an ``async def`` so you
 | |
|     need to use:
 | |
| 
 | |
|     .. code-block:: python
 | |
| 
 | |
|         print((await client.get_me()).first_name)
 | |
|         async for message in client.iter_messages('me'):
 | |
|             ...
 | |
| 
 | |
|         async with client.conversation('me') as conv:
 | |
|             ...
 | |
| 
 | |
|     You can of course call other ``def`` functions from your ``async def``
 | |
|     event handlers, but if they need making API calls, make your own
 | |
|     functions ``async def`` so you can ``await`` things:
 | |
| 
 | |
|     .. code-block:: python
 | |
| 
 | |
|         async def helper(client):
 | |
|             await client.send_message('me', 'Hi')
 | |
| 
 | |
|     If you're not inside an ``async def`` you can enter one like so:
 | |
| 
 | |
|     .. code-block:: python
 | |
| 
 | |
|         import asyncio
 | |
|         loop = asyncio.get_event_loop()
 | |
|         loop.run_until_complete(my_async_def())
 | |
| 
 | |
| 
 | |
| .. contents::
 | |
| 
 | |
| 
 | |
| Authorization
 | |
| *************
 | |
| 
 | |
| Starting the client is as easy as calling `client.start()
 | |
| <telethon.client.auth.AuthMethods.start>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.start()
 | |
|     ...  # code using the client
 | |
|     client.disconnect()
 | |
| 
 | |
| And you can even use a ``with`` block:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     with client:
 | |
|         ... # code using the client
 | |
| 
 | |
| 
 | |
| .. note::
 | |
| 
 | |
|     Remember we assume you have ``import telethon.sync``. You can of course
 | |
|     use the library without importing it. The code would be rewritten as:
 | |
| 
 | |
|     .. code-block:: python
 | |
| 
 | |
|         import asyncio
 | |
|         loop = asyncio.get_event_loop()
 | |
| 
 | |
|         async def main():
 | |
|             await client.start()
 | |
|             ...
 | |
|             await client.disconnect()
 | |
| 
 | |
|             # or
 | |
|             async with client:
 | |
|                 ...
 | |
| 
 | |
|         loop.run_until_complete(main())
 | |
| 
 | |
|     All methods that need access to the network (e.g. to make an API call)
 | |
|     **must** be awaited (or their equivalent such as ``async for`` and
 | |
|     ``async with``). You can do this yourself or you can let the library
 | |
|     do it for you by using ``import telethon.sync``. With event handlers,
 | |
|     you must do this yourself.
 | |
| 
 | |
| The cleanest way to delete your ``*.session`` file is `client.log_out
 | |
| <telethon.client.auth.AuthMethods.log_out>`. Note that you will obviously
 | |
| need to login again if you use this:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     # Logs out and deletes the session file; you will need to sign in again
 | |
|     client.log_out()
 | |
| 
 | |
|     # You often simply want to disconnect. You will not need to sign in again
 | |
|     client.disconnect()
 | |
| 
 | |
| 
 | |
| Group Chats
 | |
| ***********
 | |
| 
 | |
| You can easily iterate over all the :tl:`User` in a chat and
 | |
| do anything you want with them by using `client.iter_participants
 | |
| <telethon.client.chats.ChatMethods.iter_participants>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     for user in client.iter_participants(chat):
 | |
|         ...  # do something with the user
 | |
| 
 | |
| You can also search by their name:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     for user in client.iter_participants(chat, search='name'):
 | |
|         ...
 | |
| 
 | |
| Or by their type (e.g. if they are admin) with :tl:`ChannelParticipantsFilter`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     from telethon.tl.types import ChannelParticipantsAdmins
 | |
| 
 | |
|     for user in client.iter_participants(chat, filter=ChannelParticipantsAdmins):
 | |
|         ...
 | |
| 
 | |
| 
 | |
| Open Conversations and Joined Channels
 | |
| **************************************
 | |
| 
 | |
| The conversations you have open and the channels you have joined
 | |
| are in your "dialogs", so to get them you need to `client.get_dialogs
 | |
| <telethon.client.dialogs.DialogMethods.get_dialogs>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     dialogs = client.get_dialogs()
 | |
|     first = dialogs[0]
 | |
|     print(first.title)
 | |
| 
 | |
| You can then use the dialog as if it were a peer:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_message(first, 'hi')
 | |
| 
 | |
| 
 | |
| You can access `dialog.draft <telethon.tl.custom.draft.Draft>` or you can
 | |
| get them all at once without getting the dialogs:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     drafts = client.get_drafts()
 | |
| 
 | |
| 
 | |
| Downloading Media
 | |
| *****************
 | |
| 
 | |
| It's easy to `download_profile_photo
 | |
| <telethon.client.downloads.DownloadMethods.download_profile_photo>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.download_profile_photo(user)
 | |
| 
 | |
| Or `download_media <telethon.client.downloads.DownloadMethods.download_media>`
 | |
| from a message:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.download_media(message)
 | |
|     client.download_media(message, filename)
 | |
|     # or
 | |
|     message.download_media()
 | |
|     message.download_media(filename)
 | |
| 
 | |
| Remember that these methods return the final filename where the
 | |
| media was downloaded (e.g. it may add the extension automatically).
 | |
| 
 | |
| Getting Messages
 | |
| ****************
 | |
| 
 | |
| You can easily iterate over all the `messages
 | |
| <telethon.tl.custom.message.Message>` of a chat with `iter_messages
 | |
| <telethon.client.messages.MessageMethods.iter_messages>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     for message in client.iter_messages(chat):
 | |
|         ...  # do something with the message from recent to older
 | |
| 
 | |
|     for message in client.iter_messages(chat, reverse=True):
 | |
|         ...  # going from the oldest to the most recent
 | |
| 
 | |
| You can also use it to search for messages from a specific person:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     for message in client.iter_messages(chat, from_user='me'):
 | |
|         ...
 | |
| 
 | |
| Or you can search by text:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     for message in client.iter_messages(chat, search='hello'):
 | |
|         ...
 | |
| 
 | |
| Or you can search by media with a :tl:`MessagesFilter`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     from telethon.tl.types import InputMessagesFilterPhotos
 | |
| 
 | |
|     for message in client.iter_messages(chat, filter=InputMessagesFilterPhotos):
 | |
|         ...
 | |
| 
 | |
| If you want a list instead, use the get variant. The second
 | |
| argument is the limit, and ``None`` means "get them all":
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
| 
 | |
|     from telethon.tl.types import InputMessagesFilterPhotos
 | |
| 
 | |
|     # Get 0 photos and print the total
 | |
|     photos = client.get_messages(chat, 0, filter=InputMessagesFilterPhotos)
 | |
|     print(photos.total)
 | |
| 
 | |
|     # Get all the photos
 | |
|     photos = client.get_messages(chat, None, filter=InputMessagesFilterPhotos)
 | |
| 
 | |
| Or just some IDs:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     message_1337 = client.get_messages(chats, ids=1337)
 | |
| 
 | |
| 
 | |
| Exporting Messages
 | |
| ******************
 | |
| 
 | |
| If you plan on exporting data from your Telegram account, such as the entire
 | |
| message history from your private conversations, chats or channels, or if you
 | |
| plan to download a lot of media, you may prefer to do this within a *takeout*
 | |
| session. Takeout sessions let you export data from your account with lower
 | |
| flood wait limits.
 | |
| 
 | |
| To start a takeout session, simply call `client.takeout()
 | |
| <telethon.client.account.AccountMethods.takeout>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     from telethon import errors
 | |
| 
 | |
|     try:
 | |
|         with client.takeout() as takeout:
 | |
|             for message in takeout.iter_messages(chat, wait_time=0):
 | |
|                 ...  # Do something with the message
 | |
| 
 | |
|     except errors.TakeoutInitDelayError as e:
 | |
|         print('Must wait', e.seconds, 'before takeout')
 | |
| 
 | |
| 
 | |
| Depending on the condition of the session (for example, when it's very
 | |
| young and the method has not been called before), you may or not need
 | |
| to ``except errors.TakeoutInitDelayError``. However, it is good practice.
 | |
| 
 | |
| 
 | |
| Sending Messages
 | |
| ****************
 | |
| 
 | |
| Just use `send_message <telethon.client.messages.MessageMethods.send_message>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_message('lonami', 'Thanks for the Telethon library!')
 | |
| 
 | |
| The function returns the `custom.Message <telethon.tl.custom.message.Message>`
 | |
| that was sent so you can do more things with it if you want.
 | |
| 
 | |
| You can also `reply <telethon.tl.custom.message.Message.reply>` or
 | |
| `respond <telethon.tl.custom.message.Message.respond>` to messages:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     message.reply('Hello')
 | |
|     message.respond('World')
 | |
| 
 | |
| Sending Markdown or HTML messages
 | |
| *********************************
 | |
| 
 | |
| Markdown (``'md'`` or ``'markdown'``) is the default `parse_mode
 | |
| <telethon.client.messageparse.MessageParseMethods.parse_mode>`
 | |
| for the client. You can change the default parse mode like so:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.parse_mode = 'html'
 | |
| 
 | |
| 
 | |
| Now all messages will be formatted as HTML by default:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     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>')
 | |
|     client.send_message('me', '<code>code</code> and <pre>pre\nblocks</pre>')
 | |
|     client.send_message('me', '<a href="tg://user?id=me">Mentions</a>')
 | |
| 
 | |
| 
 | |
| You can override the default parse mode to use for special cases:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     # No parse mode by default
 | |
|     client.parse_mode = None
 | |
| 
 | |
|     # ...but here I want markdown
 | |
|     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')
 | |
| 
 | |
| The rules are the same as for Bot API, so please refer to
 | |
| https://core.telegram.org/bots/api#formatting-options.
 | |
| 
 | |
| Sending Messages with Media
 | |
| ***************************
 | |
| 
 | |
| Sending media can be done with `send_file
 | |
| <telethon.client.uploads.UploadMethods.send_file>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     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')
 | |
| 
 | |
| You can send voice notes or round videos by setting the right arguments:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_file(chat, '/my/songs/song.mp3', voice_note=True)
 | |
|     client.send_file(chat, '/my/videos/video.mp4', video_note=True)
 | |
| 
 | |
| You can set a JPG thumbnail for any document:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_file(chat, '/my/documents/doc.txt', thumb='photo.jpg')
 | |
| 
 | |
| You can force sending images as documents:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_file(chat, '/my/photos/photo.png', force_document=True)
 | |
| 
 | |
| You can send albums if you pass more than one file:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_file(chat, [
 | |
|         '/my/photos/holiday1.jpg',
 | |
|         '/my/photos/holiday2.jpg',
 | |
|         '/my/drawings/portrait.png'
 | |
|     ])
 | |
| 
 | |
| The caption can also be a list to match the different photos.
 | |
| 
 | |
| Reusing Uploaded Files
 | |
| **********************
 | |
| 
 | |
| All files you send are automatically cached, so if you do:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_file(first_chat, 'document.txt')
 | |
|     client.send_file(second_chat, 'document.txt')
 | |
| 
 | |
| The ``'document.txt'`` file will only be uploaded once. You
 | |
| can disable this behaviour by settings ``allow_cache=False``:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_file(first_chat, 'document.txt', allow_cache=False)
 | |
|     client.send_file(second_chat, 'document.txt', allow_cache=False)
 | |
| 
 | |
| Disabling cache is the only way to send the same document with different
 | |
| attributes (for example, you send an ``.ogg`` as a song but now you want
 | |
| it to show as a voice note; you probably need to disable the cache).
 | |
| 
 | |
| However, you can *upload* the file once (not sending it yet!), and *then*
 | |
| you can send it with different attributes. This means you can send an image
 | |
| as a photo and a document:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     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.name = 'not a photo.jpg'
 | |
|     client.send_file(chat, file, force_document=True)  # document, new name
 | |
| 
 | |
| Or, the example described before:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     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
 | |
| 
 | |
| The ``file`` returned by `client.upload_file
 | |
| <telethon.client.uploads.UploadMethods.upload_file>` represents the uploaded
 | |
| file, not an immutable document (that's why the attributes can change, because
 | |
| they are set later). This handle can be used only for a limited amount of time
 | |
| (somewhere within a day). Telegram decides this limit and it is not public.
 | |
| However, a day is often more than enough.
 | |
| 
 | |
| 
 | |
| Sending Messages with Buttons
 | |
| *****************************
 | |
| 
 | |
| You must sign in as a bot in order to add inline buttons (or normal
 | |
| keyboards) to your messages. Once you have signed in as a bot specify
 | |
| the `Button <telethon.tl.custom.button.Button>` or buttons to use:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     from telethon.tl.custom import Button
 | |
| 
 | |
|     async def callback(event):
 | |
|         await event.edit('Thank you!')
 | |
| 
 | |
|     client.send_message(chat, 'Hello!',
 | |
|                         buttons=Button.inline('Click me', callback))
 | |
| 
 | |
| 
 | |
| You can also add the event handler yourself, or change the data payload:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     from telethon import events
 | |
| 
 | |
|     @client.on(events.CallbackQuery)
 | |
|     async def handler(event):
 | |
|         await event.answer('You clicked {}!'.format(event.data))
 | |
| 
 | |
|     client.send_message(chat, 'Pick one', buttons=[
 | |
|         [Button.inline('Left'), Button.inline('Right')],
 | |
|         [Button.url('Check my site!', 'https://lonamiwebs.github.io')]
 | |
|     ])
 | |
| 
 | |
| You can also use normal buttons (not inline) to request the user's
 | |
| location, phone number, or simply for them to easily send a message:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     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 a reply or removing the keyboard can also be done:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_message(chat, 'Reply to me', buttons=Button.force_reply())
 | |
|     client.send_message(chat, 'Bye Keyboard!', buttons=Button.clear())
 | |
| 
 | |
| Remember to check `Button <telethon.tl.custom.button.Button>` for more.
 | |
| 
 | |
| Making Inline Queries
 | |
| *********************
 | |
| 
 | |
| You can send messages ``via @bot`` by first making an inline query:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     results = client.inline_query('like', 'Do you like Telethon?')
 | |
| 
 | |
| Then access the result you want and `click
 | |
| <telethon.tl.custom.inlineresult.InlineResult.click>` it in the chat
 | |
| where you want to send it to:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     message = results[0].click('TelethonOffTopic')
 | |
| 
 | |
| Sending messages through inline bots lets you use buttons as a normal user.
 | |
| 
 | |
| It can look a bit strange at first, but you can make inline queries in no
 | |
| chat in particular, and then click a *result* to send it to some chat.
 | |
| 
 | |
| Clicking Buttons
 | |
| ****************
 | |
| 
 | |
| Let's `click <telethon.tl.custom.message.Message.click>`
 | |
| the message we sent in the example above!
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     message.click(0)
 | |
| 
 | |
| This will click the first button in the message. You could also
 | |
| ``click(row, column)``, using some text such as ``click(text='👍')``
 | |
| or even the data directly ``click(data=b'payload')``.
 | |
| 
 | |
| Answering Inline Queries
 | |
| ************************
 | |
| 
 | |
| As a bot, you can answer to inline queries with `events.InlineQuery
 | |
| <telethon.events.inlinequery.InlineQuery>`. You should make use of the
 | |
| `builder <telethon.tl.custom.inlinebuilder.InlineBuilder>` property
 | |
| to conveniently build the list of results to show to the user. Remember
 | |
| to check the properties of the `InlineQuery.Event
 | |
| <telethon.events.inlinequery.InlineQuery.Event>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     @bot.on(events.InlineQuery)
 | |
|     async def handler(event):
 | |
|         builder = event.builder
 | |
| 
 | |
|         rev_text = event.text[::-1]
 | |
|         await event.answer([
 | |
|             builder.article('Reverse text', text=rev_text),
 | |
|             builder.photo('/path/to/photo.jpg')
 | |
|         ])
 | |
| 
 | |
| Conversations: Waiting for Messages or Replies
 | |
| **********************************************
 | |
| 
 | |
| This one is really useful for unit testing your bots, which you can
 | |
| even write within Telethon itself! You can open a `Conversation
 | |
| <telethon.tl.custom.conversation.Conversation>` in any chat as:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     with client.conversation(chat) as conv:
 | |
|         ...
 | |
| 
 | |
| Conversations let you program a finite state machine with the
 | |
| higher-level constructs we are all used to, such as ``while``
 | |
| and ``if`` conditionals instead setting the state and jumping
 | |
| from one place to another which is less clean.
 | |
| 
 | |
| For instance, let's imagine ``you`` are the bot talking to ``usr``:
 | |
| 
 | |
| .. code-block:: text
 | |
| 
 | |
|     <you> Hi!
 | |
|     <usr> Hello!
 | |
|     <you> Please tell me your name
 | |
|     <usr> ?
 | |
|     <you> Your name didn't have any letters! Try again
 | |
|     <usr> Lonami
 | |
|     <you> Thanks Lonami!
 | |
| 
 | |
| This can be programmed as follows:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     with bot.conversation(chat) as conv:
 | |
|         conv.send_message('Hi!')
 | |
|         hello = conv.get_response()
 | |
| 
 | |
|         conv.send_message('Please tell me your name')
 | |
|         name = conv.get_response().raw_text
 | |
|         while not any(x.isalpha() for x in name):
 | |
|             conv.send_message("Your name didn't have any letters! Try again")
 | |
|             name = conv.get_response().raw_text
 | |
| 
 | |
|         conv.send_message('Thanks {}!'.format(name))
 | |
| 
 | |
| Note how we sent a message **with the conversation**, not with the client.
 | |
| This is important so the conversation remembers what messages you sent.
 | |
| 
 | |
| The method reference for getting a response, getting a reply or marking
 | |
| the conversation as read can be found by clicking here: `Conversation
 | |
| <telethon.tl.custom.conversation.Conversation>`.
 | |
| 
 | |
| Sending a message or getting a response returns a `Message
 | |
| <telethon.tl.custom.message.Message>`. Reading its documentation
 | |
| will also be really useful!
 | |
| 
 | |
| If a reply never arrives or too many messages come in, getting
 | |
| responses will raise ``asyncio.TimeoutError`` or ``ValueError``
 | |
| respectively. You may want to ``except`` these and tell the user
 | |
| they were too slow, or simply drop the conversation.
 | |
| 
 | |
| 
 | |
| Forwarding Messages
 | |
| *******************
 | |
| 
 | |
| You can forward up to 100 messages with `forward_messages
 | |
| <telethon.client.messages.MessageMethods.forward_messages>`,
 | |
| or a single one if you have the message with `forward_to
 | |
| <telethon.tl.custom.message.Message.forward_to>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     # a single one
 | |
|     client.forward_messages(chat, message)
 | |
|     # or
 | |
|     client.forward_messages(chat, message_id, from_chat)
 | |
|     # or
 | |
|     message.forward_to(chat)
 | |
| 
 | |
|     # multiple
 | |
|     client.forward_messages(chat, messages)
 | |
|     # or
 | |
|     client.forward_messages(chat, message_ids, from_chat)
 | |
| 
 | |
| You can also "forward" messages without showing "Forwarded from" by
 | |
| re-sending the message:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_message(chat, message)
 | |
| 
 | |
| 
 | |
| Editing Messages
 | |
| ****************
 | |
| 
 | |
| With `edit_message <telethon.client.messages.MessageMethods.edit_message>`
 | |
| or  `message.edit <telethon.tl.custom.message.Message.edit>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.edit_message(message, 'New text')
 | |
|     # or
 | |
|     message.edit('New text')
 | |
|     # or
 | |
|     client.edit_message(chat, message_id, 'New text')
 | |
| 
 | |
| Deleting Messages
 | |
| *****************
 | |
| 
 | |
| With `delete_messages <telethon.client.messages.MessageMethods.delete_messages>`
 | |
| or  `message.delete <telethon.tl.custom.message.Message.delete>`. Note that the
 | |
| first one supports deleting entire chats at once!:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.delete_messages(chat, messages)
 | |
|     # or
 | |
|     message.delete()
 | |
| 
 | |
| 
 | |
| Marking Messages as Read
 | |
| ************************
 | |
| 
 | |
| Marking messages up to a certain point as read with `send_read_acknowledge
 | |
| <telethon.client.messages.MessageMethods.send_read_acknowledge>`:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     client.send_read_acknowledge(last_message)
 | |
|     # or
 | |
|     client.send_read_acknowledge(last_message_id)
 | |
|     # or
 | |
|     client.send_read_acknowledge(messages)
 | |
| 
 | |
| 
 | |
| Getting Entities
 | |
| ****************
 | |
| 
 | |
| Entities are users, chats, or channels. You can get them by their ID if
 | |
| you have seen them before (e.g. you probably need to get all dialogs or
 | |
| all the members from a chat first):
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     from telethon import utils
 | |
| 
 | |
|     me = client.get_entity('me')
 | |
|     print(utils.get_display_name(me))
 | |
| 
 | |
|     chat = client.get_input_entity('username')
 | |
|     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'):
 | |
|         ...
 | |
| 
 | |
|     # Note that for this to work the phone number must be in your contacts
 | |
|     some_id = client.get_peer_id('+34123456789')
 | |
| 
 | |
| The documentation for shown methods are `get_entity
 | |
| <telethon.client.users.UserMethods.get_entity>`, `get_input_entity
 | |
| <telethon.client.users.UserMethods.get_input_entity>` and `get_peer_id
 | |
| <telethon.client.users.UserMethods.get_peer_id>`.
 | |
| 
 | |
| Note that the utils package also has a `get_peer_id
 | |
| <telethon.utils.get_peer_id>` but it won't work with things
 | |
| that need access to the network such as usernames or phones,
 | |
| which need to be in your contact list.
 | |
| 
 | |
| Getting the Admin Log
 | |
| *********************
 | |
| 
 | |
| If you're an administrator in a channel or megagroup, then you have access
 | |
| to the admin log. This is a list of events within the last 48 hours of
 | |
| different actions, such as joining or leaving members, edited or deleted
 | |
| messages, new promotions, bans or restrictions.
 | |
| 
 | |
| You can iterate over all the available actions like so:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     for event in client.iter_admin_log(channel):
 | |
|         if event.changed_title:
 | |
|             print('The title changed from', event.old, 'to', event.new)
 | |
| 
 | |
| You can also filter to only show some text or actions.
 | |
| Let's find people who swear to ban them:
 | |
| 
 | |
| .. code-block:: python
 | |
| 
 | |
|     # Get a list of deleted message events which said "heck"
 | |
|     events = client.get_admin_log(channel, search='heck', delete=True)
 | |
| 
 | |
|     # Print the old message before it was deleted
 | |
|     print(events[0].old)
 | |
| 
 | |
| You can find here the documentation for `client.iter_admin_log
 | |
| <telethon.client.chats.ChatMethods.iter_admin_log>`, and be sure
 | |
| to also check the properties of the returned `AdminLogEvent
 | |
| <telethon.tl.custom.adminlogevent.AdminLogEvent>` to know what
 | |
| you can access.
 |