File: botapi-vs-mtproto.rst

package info (click to toggle)
python-telethon 1.42.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,520 kB
  • sloc: python: 16,285; javascript: 200; makefile: 16; sh: 11
file content (336 lines) | stat: -rw-r--r-- 10,333 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
.. _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.

Configuration of your bot, such as its available commands and auto-completion,
is configured through `@BotFather <https://t.me/BotFather>`_.


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 wiki page `MTProto vs HTTP Bot API`_ 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 `echobot.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 & ~Filters.command, 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 fewer 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):
            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
.. _MTProto vs HTTP Bot API: https://github.com/LonamiWebs/Telethon/wiki/MTProto-vs-HTTP-Bot-API
.. _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
.. _echobot.py: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/echobot.py