mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-11-04 01:47:27 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			334 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			334 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
.. _botapi:
 | 
						|
 | 
						|
=======================
 | 
						|
HTTP Bot API vs MTProto
 | 
						|
=======================
 | 
						|
 | 
						|
 | 
						|
Telethon is more than just another viable alternative when developing bots
 | 
						|
for Telegram. If you haven't decided which wrapper library for bots to use
 | 
						|
yet, using Telethon from the beginning may save you some headaches later.
 | 
						|
 | 
						|
.. contents::
 | 
						|
 | 
						|
 | 
						|
What is Bot API?
 | 
						|
================
 | 
						|
 | 
						|
The `Telegram Bot API`_, also known as HTTP Bot API and from now on referred
 | 
						|
to as simply "Bot API" is Telegram's official way for developers to control
 | 
						|
their own Telegram bots. Quoting their main page:
 | 
						|
 | 
						|
    The Bot API is an HTTP-based interface created for developers keen on
 | 
						|
    building bots for Telegram.
 | 
						|
 | 
						|
    To learn how to create and set up a bot, please consult our
 | 
						|
    `Introduction to Bots`_ and `Bot FAQ`_.
 | 
						|
 | 
						|
Bot API is simply an HTTP endpoint which translates your requests to it into
 | 
						|
MTProto calls through tdlib_, their bot backend.
 | 
						|
 | 
						|
 | 
						|
What is MTProto?
 | 
						|
================
 | 
						|
 | 
						|
MTProto_ is Telegram's own protocol to communicate with their API when you
 | 
						|
connect to their servers.
 | 
						|
 | 
						|
Telethon is an alternative MTProto-based backend written entirely in Python
 | 
						|
and much easier to setup and use.
 | 
						|
 | 
						|
Both official applications and third-party clients (like your own
 | 
						|
applications) logged in as either user or bots **can use MTProto** to
 | 
						|
communicate directly with Telegram's API (which is not the HTTP bot API).
 | 
						|
 | 
						|
When we talk about MTProto, we often mean "MTProto-based clients".
 | 
						|
 | 
						|
 | 
						|
Advantages of MTProto over Bot API
 | 
						|
==================================
 | 
						|
 | 
						|
MTProto clients (like Telethon) connect directly to Telegram's servers,
 | 
						|
which means there is no HTTP connection, no "polling" or "web hooks". This
 | 
						|
means **less overhead**, since the protocol used between you and the server
 | 
						|
is much more compact than HTTP requests with responses in wasteful JSON.
 | 
						|
 | 
						|
Since there is a direct connection to Telegram's servers, even if their
 | 
						|
Bot API endpoint is down, you can still have connection to Telegram directly.
 | 
						|
 | 
						|
Using a MTProto client, you are also not limited to the public API that
 | 
						|
they expose, and instead, **you have full control** of what your bot can do.
 | 
						|
Telethon offers you all the power with often **much easier usage** than any
 | 
						|
of the available Python Bot API wrappers.
 | 
						|
 | 
						|
If your application ever needs user features because bots cannot do certain
 | 
						|
things, you will be able to easily login as a user and even keep your bot
 | 
						|
without having to learn a new library.
 | 
						|
 | 
						|
If less overhead and full control didn't convince you to use Telethon yet,
 | 
						|
check out the repository `HTTP Bot API vs MTProto comparison`_ with a more
 | 
						|
exhaustive and up-to-date list of differences.
 | 
						|
 | 
						|
 | 
						|
Migrating from Bot API to Telethon
 | 
						|
==================================
 | 
						|
 | 
						|
It doesn't matter if you wrote your bot with requests_ and you were
 | 
						|
making API requests manually, or if you used a wrapper library like
 | 
						|
python-telegram-bot_ or pyTelegramBotAPI_. It's never too late to
 | 
						|
migrate to Telethon!
 | 
						|
 | 
						|
If you were using an asynchronous library like aiohttp_ or a wrapper like
 | 
						|
aiogram_ or dumbot_, it will be even easier, because Telethon is also an
 | 
						|
asynchronous library.
 | 
						|
 | 
						|
Next, we will see some examples from the most popular libraries.
 | 
						|
 | 
						|
 | 
						|
Migrating from python-telegram-bot
 | 
						|
----------------------------------
 | 
						|
 | 
						|
Let's take their `echobot2.py`_ example and shorten it a bit:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
 | 
						|
 | 
						|
    def start(update, context):
 | 
						|
        """Send a message when the command /start is issued."""
 | 
						|
        update.message.reply_text('Hi!')
 | 
						|
 | 
						|
    def echo(update, context):
 | 
						|
        """Echo the user message."""
 | 
						|
        update.message.reply_text(update.message.text)
 | 
						|
 | 
						|
    def main():
 | 
						|
        """Start the bot."""
 | 
						|
        updater = Updater("TOKEN")
 | 
						|
        dp = updater.dispatcher
 | 
						|
        dp.add_handler(CommandHandler("start", start))
 | 
						|
        dp.add_handler(MessageHandler(Filters.text, echo))
 | 
						|
 | 
						|
        updater.start_polling()
 | 
						|
 | 
						|
        updater.idle()
 | 
						|
 | 
						|
    if __name__ == '__main__':
 | 
						|
        main()
 | 
						|
 | 
						|
 | 
						|
After using Telethon:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from telethon import TelegramClient, events
 | 
						|
 | 
						|
    bot = TelegramClient('bot', 11111, 'a1b2c3d4').start(bot_token='TOKEN')
 | 
						|
 | 
						|
    @bot.on(events.NewMessage(pattern='/start'))
 | 
						|
    async def start(event):
 | 
						|
        """Send a message when the command /start is issued."""
 | 
						|
        await event.respond('Hi!')
 | 
						|
        raise events.StopPropagation
 | 
						|
 | 
						|
    @bot.on(events.NewMessage)
 | 
						|
    async def echo(event):
 | 
						|
        """Echo the user message."""
 | 
						|
        await event.respond(event.text)
 | 
						|
 | 
						|
    def main():
 | 
						|
        """Start the bot."""
 | 
						|
        bot.run_until_disconnected()
 | 
						|
 | 
						|
    if __name__ == '__main__':
 | 
						|
        main()
 | 
						|
 | 
						|
Key differences:
 | 
						|
 | 
						|
* The recommended way to do it imports less things.
 | 
						|
* All handlers trigger by default, so we need ``events.StopPropagation``.
 | 
						|
* Adding handlers, responding and running is a lot less verbose.
 | 
						|
* Telethon needs ``async def`` and ``await``.
 | 
						|
* The ``bot`` isn't hidden away by ``Updater`` or ``Dispatcher``.
 | 
						|
 | 
						|
 | 
						|
Migrating from pyTelegramBotAPI
 | 
						|
-------------------------------
 | 
						|
 | 
						|
Let's show another echobot from their README:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    import telebot
 | 
						|
 | 
						|
    bot = telebot.TeleBot("TOKEN")
 | 
						|
 | 
						|
    @bot.message_handler(commands=['start'])
 | 
						|
    def send_welcome(message):
 | 
						|
        bot.reply_to(message, "Howdy, how are you doing?")
 | 
						|
 | 
						|
    @bot.message_handler(func=lambda m: True)
 | 
						|
    def echo_all(message):
 | 
						|
        bot.reply_to(message, message.text)
 | 
						|
 | 
						|
    bot.polling()
 | 
						|
 | 
						|
Now we rewrite it to use Telethon:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from telethon import TelegramClient, events
 | 
						|
 | 
						|
    bot = TelegramClient('bot', 11111, 'a1b2c3d4').start(bot_token='TOKEN')
 | 
						|
 | 
						|
    @bot.on(events.NewMessage(pattern='/start'))
 | 
						|
    async def send_welcome(event):
 | 
						|
        await event.reply('Howdy, how are you doing?')
 | 
						|
 | 
						|
    @bot.on(events.NewMessage)
 | 
						|
    async def echo_all(event):
 | 
						|
        await event.reply(event.text)
 | 
						|
 | 
						|
    bot.run_until_disconnected()
 | 
						|
 | 
						|
Key differences:
 | 
						|
 | 
						|
* Instead of doing ``bot.reply_to(message)``, we can do ``event.reply``.
 | 
						|
  Note that the ``event`` behaves just like their ``message``.
 | 
						|
* Telethon also supports ``func=lambda m: True``, but it's not necessary.
 | 
						|
 | 
						|
 | 
						|
Migrating from aiogram
 | 
						|
----------------------
 | 
						|
 | 
						|
From their GitHub:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from aiogram import Bot, Dispatcher, executor, types
 | 
						|
 | 
						|
    API_TOKEN = 'BOT TOKEN HERE'
 | 
						|
 | 
						|
    # Initialize bot and dispatcher
 | 
						|
    bot = Bot(token=API_TOKEN)
 | 
						|
    dp = Dispatcher(bot)
 | 
						|
 | 
						|
    @dp.message_handler(commands=['start'])
 | 
						|
    async def send_welcome(message: types.Message):
 | 
						|
        """
 | 
						|
        This handler will be called when client send `/start` command.
 | 
						|
        """
 | 
						|
        await message.reply("Hi!\nI'm EchoBot!\nPowered by aiogram.")
 | 
						|
 | 
						|
    @dp.message_handler(regexp='(^cat[s]?$|puss)')
 | 
						|
    async def cats(message: types.Message):
 | 
						|
        with open('data/cats.jpg', 'rb') as photo:
 | 
						|
            await bot.send_photo(message.chat.id, photo, caption='Cats is here 😺',
 | 
						|
                                 reply_to_message_id=message.message_id)
 | 
						|
 | 
						|
    @dp.message_handler()
 | 
						|
    async def echo(message: types.Message):
 | 
						|
        await bot.send_message(message.chat.id, message.text)
 | 
						|
 | 
						|
    if __name__ == '__main__':
 | 
						|
        executor.start_polling(dp, skip_updates=True)
 | 
						|
 | 
						|
 | 
						|
After rewrite:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from telethon import TelegramClient, events
 | 
						|
 | 
						|
    # Initialize bot and... just the bot!
 | 
						|
    bot = TelegramClient('bot', 11111, 'a1b2c3d4').start(bot_token='TOKEN')
 | 
						|
 | 
						|
    @bot.on(events.NewMessage(pattern='/start'))
 | 
						|
    async def send_welcome(event):
 | 
						|
        await event.reply('Howdy, how are you doing?')
 | 
						|
 | 
						|
    @bot.on(events.NewMessage(pattern='(^cat[s]?$|puss)'))
 | 
						|
    async def cats(event):
 | 
						|
        await event.reply('Cats is here 😺', file='data/cats.jpg')
 | 
						|
 | 
						|
    @bot.on(events.NewMessage)
 | 
						|
    async def echo_all(event):
 | 
						|
        await event.reply(event.text)
 | 
						|
 | 
						|
    if __name__ == '__main__':
 | 
						|
        bot.run_until_disconnected()
 | 
						|
 | 
						|
 | 
						|
Key differences:
 | 
						|
 | 
						|
* Telethon offers convenience methods to avoid retyping
 | 
						|
  ``bot.send_photo(message.chat.id, ...)`` all the time,
 | 
						|
  and instead let you type ``event.reply``.
 | 
						|
* Sending files is **a lot** easier. The methods for sending
 | 
						|
  photos, documents, audios, etc. are all the same!
 | 
						|
 | 
						|
Migrating from dumbot
 | 
						|
---------------------
 | 
						|
 | 
						|
Showcasing their subclassing example:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from dumbot import Bot
 | 
						|
 | 
						|
    class Subbot(Bot):
 | 
						|
        async def init(self):
 | 
						|
            self.me = await self.getMe()
 | 
						|
 | 
						|
        async def on_update(self, update):
 | 
						|
            await self.sendMessage(
 | 
						|
                chat_id=update.message.chat.id,
 | 
						|
                text='i am {}'.format(self.me.username)
 | 
						|
            )
 | 
						|
 | 
						|
    Subbot(token).run()
 | 
						|
 | 
						|
After rewriting:
 | 
						|
 | 
						|
.. code-block:: python
 | 
						|
 | 
						|
    from telethon import TelegramClient, events
 | 
						|
 | 
						|
    class Subbot(TelegramClient):
 | 
						|
        def __init__(self, *a, **kw):
 | 
						|
            await super().__init__(*a, **kw)
 | 
						|
            self.add_event_handler(self.on_update, events.NewMessage)
 | 
						|
 | 
						|
        async def connect():
 | 
						|
            await super().connect()
 | 
						|
            self.me = await self.get_me()
 | 
						|
 | 
						|
        async def on_update(event):
 | 
						|
            await event.reply('i am {}'.format(self.me.username))
 | 
						|
 | 
						|
    bot = Subbot('bot', 11111, 'a1b2c3d4').start(bot_token='TOKEN')
 | 
						|
    bot.run_until_disconnected()
 | 
						|
 | 
						|
 | 
						|
Key differences:
 | 
						|
 | 
						|
* Telethon method names are ``snake_case``.
 | 
						|
* dumbot does not offer friendly methods like ``update.reply``.
 | 
						|
* Telethon does not have an implicit ``on_update`` handler, so
 | 
						|
  we need to manually register one.
 | 
						|
 | 
						|
 | 
						|
.. _Telegram Bot API: https://core.telegram.org/bots/api
 | 
						|
.. _Introduction to Bots: https://core.telegram.org/bots
 | 
						|
.. _Bot FAQ: https://core.telegram.org/bots/faq
 | 
						|
.. _tdlib: https://core.telegram.org/tdlib
 | 
						|
.. _MTProto: https://core.telegram.org/mtproto
 | 
						|
.. _HTTP Bot API vs MTProto comparison: https://github.com/telegram-mtproto/botapi-comparison
 | 
						|
.. _requests: https://pypi.org/project/requests/
 | 
						|
.. _python-telegram-bot: https://python-telegram-bot.readthedocs.io
 | 
						|
.. _pyTelegramBotAPI: https://github.com/eternnoir/pyTelegramBotAPI
 | 
						|
.. _aiohttp: https://docs.aiohttp.org/en/stable
 | 
						|
.. _aiogram: https://aiogram.readthedocs.io
 | 
						|
.. _dumbot: https://github.com/Lonami/dumbot
 | 
						|
.. _echobot2.py: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot2.py
 |