telepot reference ================= Telepot has two versions: - **Traditional version works on Python 2.7 and Python 3.** It uses `urllib3 `_ to make HTTP requests, and uses threads to achieve delegation by default. - **Async version works on Python 3.5 or above.** It is based on `asyncio `_, uses `aiohttp `_ to make asynchronous HTTP requests, and uses asyncio tasks to achieve delegation. This page focuses on traditional version. Async version is very similar, the most significant differences being: - Blocking methods (mostly network operations) become coroutines, and should be called with ``await``. - Delegation is achieved by tasks, instead of threads. Thread-safety ceases to be a concern. Traditional modules are under the package :mod:`telepot`, while async modules are under :mod:`telepot.aio`: +-------------------+-----------------------+ | Traditional | Async | +===================+=======================+ | telepot | telepot.aio | +-------------------+-----------------------+ | telepot.loop | telepot.aio.loop | +-------------------+-----------------------+ | telepot.delegate | telepot.aio.delegate | +-------------------+-----------------------+ | telepot.helper | telepot.aio.helper | +-------------------+-----------------------+ | telepot.routing | telepot.aio.routing | +-------------------+-----------------------+ | telepot.api | telepot.aio.api | +-------------------+-----------------------+ Some modules do not have async counterparts, e.g. :mod:`telepot.namedtuple` and :mod:`telepot.exception`, because they are shared. Try to combine this reading with the provided `examples `_ . One example is worth a thousand words. I hope they make things clear. Basic Bot --------- The ``Bot`` class is mostly a wrapper around `Telegram Bot API `_. Many methods are straight mappings to Bot API methods. Where appropriate, I only give links below. No point to duplicate all the details. .. autoclass:: telepot.Bot :members: Message Loop and Webhook ------------------------ There are two ways to obtain updates from Telegram Bot API: make calls to :meth:`.Bot.getUpdates` continuously, or use webhook. In the former case, it is troublesome to have to program that manually. So :class:`.MessageLoop` is here to ease your burden. In the latter case, although the programming overhead is mainly on the web server, a structured way to funnel web requests into telepot is desirable. The result is :class:`.Webhook` and :class:`.OrderedWebhook`. The idea is similar. You supply a message-handling function to the object constructor, then use :meth:`.run_as_thread` to get it going. A :class:`.MessageLoop` makes calls to :meth:`.getUpdates` continuously, and apply the message-handling function to every message received. A :class:`.Webhook` or :class:`.OrderedWebhook` would not do anything by itself; you have to :meth:`.feed` it the new update every time the web server receives one. In place of the message-handling function, you can supply one of the following: - a function that takes one argument (the message) - if ``None``, the bot's ``handle`` method is used - a routing table A *routing table* is a dictionary of ``{flavor: function}``, mapping messages to appropriate handler functions according to their flavors. It allows you to define functions specifically to handle one flavor of messages. It usually looks like this: ``{'chat': fn1, 'callback_query': fn2, 'inline_query': fn3, ...}``. Each handler function should take one argument (the message). .. autoclass:: telepot.loop.MessageLoop :members: :undoc-members: :inherited-members: In practice, you should always use :class:`.OrderedWebhook` rather than :class:`.Webhook`. Updates are individual HTTP requests, and there is no guarantee of their arrival order. :class:`.OrderedWebhook` puts them in order (according to ``update_id``) before applying the message-handling function. In contrast, :class:`.Webhook` applies the message-handling function in the order you feed them. Unless you want to implement your own ordering logic, :class:`.Webhook` should not be used. In async version, a task of :meth:`.run_forever` should be created instead of :meth:`.run_as_thread`. Refer to `webhook examples `_ for usage. .. autoclass:: telepot.loop.OrderedWebhook :members: :undoc-members: :inherited-members: .. autoclass:: telepot.loop.Webhook :members: :undoc-members: :inherited-members: Functions --------- .. autofunction:: telepot.flavor .. autofunction:: telepot.glance .. autofunction:: telepot.flance .. autofunction:: telepot.peel .. autofunction:: telepot.fleece .. autofunction:: telepot.is_event .. autofunction:: telepot.message_identifier .. autofunction:: telepot.origin_identifier DelegatorBot ------------ .. autoclass:: telepot.DelegatorBot A *seeder* is a function that: - takes one argument - a message - returns a *seed*. Depending on the nature of the seed, behavior is as follows: - if the seed is a hashable (e.g. number, string, tuple), it looks for a *delegate* associated with the seed. (Think of a dictionary of ``{seed: delegate}``) - if such a delegate exists and is alive, it is assumed that the message will be picked up by the delegate. Nothing more is done. - if no delegate exists or that delegate is no longer alive, a new delegate is obtained by calling the delegator function. The new delegate is associated with the seed. - **In essence, when the seed is a hashable, only one delegate is running for a given seed.** - if the seed is a non-hashable, (e.g. list), a new delegate is always obtained by calling the delegator function. No seed-delegate association occurs. - if the seed is ``None``, nothing is done. A *delegator* is a function that: - takes one argument - a (bot, message, seed) tuple. This is called a *seed tuple*. - returns a *delegate*, which can be one of the following: - an object that has methods ``start()`` and ``is_alive()``. Therefore, a ``threading.Thread`` object is a natural delegate. Once returned, the object's ``start()`` method is called. - a function. Once returned, it is wrapped in a ``Thread(target=function)`` and started. - a (function, args, kwargs) tuple. Once returned, it is wrapped in a ``Thread(target=function, args=args, kwargs=kwargs)`` and started. The above logic is implemented in the ``handle`` method. You only have to create a :class:`.MessageLoop` with no callback argument, the above logic will be executed for every message received. In the list of delegation patterns, all seeder functions are evaluated in order. One message may start multiple delegates. The module :mod:`telepot.delegate` has a bunch of seeder factories and delegator factories, which greatly ease the use of DelegatorBot. The module :mod:`telepot.helper` also has a number of ``*Handler`` classes which provide a connection-like interface to deal with individual chats or users. I have given an `answer `_ on Stack Overflow which elaborates on the inner workings of DelegatorBot in greater details. Interested readers are encouraged to read that. In the rest of discussions, *seed tuple* means a (bot, message, seed) tuple, referring to the single argument taken by delegator functions. ``telepot.delegate`` -------------------- .. automodule:: telepot.delegate :members: ``telepot.helper`` ------------------ Handlers ++++++++ .. autoclass:: telepot.helper.Monitor :show-inheritance: :members: .. autoclass:: telepot.helper.ChatHandler :show-inheritance: :members: .. autoclass:: telepot.helper.UserHandler :show-inheritance: :members: .. autoclass:: telepot.helper.InlineUserHandler :show-inheritance: :members: .. autoclass:: telepot.helper.CallbackQueryOriginHandler :show-inheritance: :members: .. autoclass:: telepot.helper.InvoiceHandler :show-inheritance: :members: Contexts ++++++++ .. autoclass:: telepot.helper.ListenerContext :members: :undoc-members: .. autoclass:: telepot.helper.ChatContext :show-inheritance: :members: :undoc-members: .. autoclass:: telepot.helper.UserContext :show-inheritance: :members: :undoc-members: .. autoclass:: telepot.helper.CallbackQueryOriginContext :show-inheritance: :members: :undoc-members: .. autoclass:: telepot.helper.InvoiceContext :show-inheritance: :members: :undoc-members: .. autoclass:: telepot.helper.Sender :members: .. autoclass:: telepot.helper.Administrator :members: .. autoclass:: telepot.helper.Editor :members: .. autoclass:: telepot.helper.Listener :members: Mixins ++++++ .. autoclass:: telepot.helper.Router :members: .. autoclass:: telepot.helper.DefaultRouterMixin :members: :undoc-members: .. autoclass:: telepot.helper.StandardEventScheduler :members: :undoc-members: .. autoclass:: telepot.helper.StandardEventMixin :members: :undoc-members: :exclude-members: StandardEventScheduler .. autoclass:: telepot.helper.IdleEventCoordinator :members: .. autoclass:: telepot.helper.IdleTerminateMixin :members: :undoc-members: :exclude-members: IdleEventCoordinator .. autoclass:: telepot.helper.CallbackQueryCoordinator :members: :undoc-members: .. autoclass:: telepot.helper.InterceptCallbackQueryMixin :members: :undoc-members: :exclude-members: CallbackQueryCoordinator .. autoclass:: telepot.helper.Answerer :members: .. autoclass:: telepot.helper.AnswererMixin :members: :undoc-members: :exclude-members: Answerer Utilities +++++++++ .. autoclass:: telepot.helper.SafeDict :members: .. autofunction:: telepot.helper.openable ``telepot.exception`` --------------------- .. automodule:: telepot.exception :members: :undoc-members: ``telepot.namedtuple`` ---------------------- Telepot's custom is to represent Bot API object as *dictionary*. On the other hand, the module :mod:`telepot.namedtuple` also provide namedtuple classes mirroring those objects. The reasons are twofold: 1. Under some situations, you may want an object with a complete set of fields, including those whose values are ``None``. A dictionary translated from Bot API's response would have those ``None`` fields absent. By converting such a dictionary to a namedtuple, all fields are guaranteed to be present, even if their values are ``None``. This usage is for **incoming** objects received from Telegram servers. 2. Namedtuple allows easier construction of objects like `ReplyKeyboardMarkup `_, `InlineKeyboardMarkup `_, and various `InlineQueryResult `_, etc. This usage is for **outgoing** objects sent to Telegram servers. Incoming objects include: - `User `_ - `Chat `_ - `Message `_ - `MessageEntity `_ - `PhotoSize `_ - `Audio `_ - `Document `_ - `Sticker `_ - `Video `_ - `Voice `_ - `VideoNote `_ - `Contact `_ - `Location `_ - `Venue `_ - `UserProfilePhotos `_ - `File `_ - `ChatPhoto `_ - `ChatMember `_ - `CallbackQuery `_ - `InlineQuery `_ - `ChosenInlineResult `_ - `Invoice `_ - `ShippingAddress `_ - `OrderInfo `_ - `ShippingQuery `_ - `PreCheckoutQuery `_ - `SuccessfulPayment `_ Outgoing objects include: - `ReplyKeyboardMarkup `_ - `KeyboardButton `_ - `ReplyKeyboardRemove `_ - `InlineKeyboardMarkup `_ - `InlineKeyboardButton `_ - `ForceReply `_ - Various types of `InlineQueryResult `_ - Various types of `InputMessageContent `_ - `LabeledPrice `_ - `ShippingOption `_ ``telepot.routing`` ------------------- .. automodule:: telepot.routing :members: ``telepot.text`` ---------------- .. automodule:: telepot.text :members: ``telepot.api`` ---------------- .. automodule:: telepot.api :members: