From da5c801b4d0b12f0b60ba1506b5f690e5f491580 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Sun, 19 May 2019 12:40:52 +0200 Subject: [PATCH] Add new section for people coming from Bot API --- readthedocs/concepts/botapi-vs-mtproto.rst | 333 +++++++++++++++++++++ readthedocs/index.rst | 2 + 2 files changed, 335 insertions(+) create mode 100644 readthedocs/concepts/botapi-vs-mtproto.rst diff --git a/readthedocs/concepts/botapi-vs-mtproto.rst b/readthedocs/concepts/botapi-vs-mtproto.rst new file mode 100644 index 00000000..75353a4a --- /dev/null +++ b/readthedocs/concepts/botapi-vs-mtproto.rst @@ -0,0 +1,333 @@ +.. _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 diff --git a/readthedocs/index.rst b/readthedocs/index.rst index c042709f..728a4b68 100644 --- a/readthedocs/index.rst +++ b/readthedocs/index.rst @@ -21,6 +21,7 @@ Telethon's Documentation * Looking for the method reference? See :ref:`client-ref`. * Did you upgrade the library? Please read :ref:`changelog`. * Used Telethon before v1.0? See :ref:`compatibility-and-convenience`. +* Coming from Bot API or want to create new bots? See :ref:`botapi`. * Need the full API reference? https://lonamiwebs.github.io/Telethon/. @@ -71,6 +72,7 @@ You can also use the menu on the left to quickly skip over sections. concepts/sessions concepts/full-api concepts/errors + concepts/botapi-vs-mtproto concepts/asyncio .. toctree::