How to add a module on telegram
Simla.com Documentation: Page not found
Sections
Sales129 articles
- Demo data in the system
- Orders
- Customers
- Tasks
- Warehouse
- Managers
- Finances
40 articles
- Mailings
- Segments
- Rules
53 articles
- Creating and editing an API key
- Working with the marketplace
- Delivery services
- Modules for integration with a site
- Telephony
- Modules for working with data books
- Recommendations
- Call tracking
- Analytical services
45 articles
- Analytics by orders
- Analytics by customers
- Analytics by products
- Analytics by managers
- Analytics on communications
- Finance analytics
94 articles
- Users
- Stores
- Data books
- Order statuses
- Product statuses
- Triggers
- Communication settings
- Loyalty
- System settings
39 articles
- Chat functionality
- Connecting messengers and chats
- Bots
python-telegram-bot · PyPI
We have made you a wrapper you can’t refuse
We have a vibrant community of developers helping each other in our Telegram group. Join us!
Stay tuned for library updates and new releases on our Telegram Channel.
Table of contents
Introduction
Telegram API support
Installing
Getting started
Learning by example
Logging
Documentation
Getting help
Contributing
License
Introduction
This library provides a pure Python interface for the Telegram Bot API. It’s compatible with Python versions 3.7+. PTB might also work on PyPy, though there have been a lot of issues before. Hence, PyPy is not officially supported.
In addition to the pure API implementation, this library features a number of high-level classes to make the development of bots easy and straightforward. These classes are contained in the telegram.ext submodule.
A pure API implementation without telegram.ext is available as the standalone package python-telegram-bot-raw. See here for details.
Note
Installing both python-telegram-bot and python-telegram-bot-raw in conjunction will result in undesired side-effects, so only install one of both.
Telegram API support
All types and methods of the Telegram Bot API 6.2 are supported.
Installing
You can install or upgrade python-telegram-bot with:
$ pip install python-telegram-bot --upgrade
Or you can install from source with:
$ git clone https://github.com/python-telegram-bot/python-telegram-bot --recursive $ cd python-telegram-bot $ python setup.py install
In case you have a previously cloned local repository already, you should initialize the added urllib3 submodule before installing with:
$ git submodule update --init --recursive
Optional Dependencies
PTB can be installed with optional dependencies:
pip install python-telegram-bot[passport] installs the cryptography library. Use this, if you want to use Telegram Passport related functionality.
pip install python-telegram-bot[ujson] installs the ujson library. It will then be used for JSON de- & encoding, which can bring speed up compared to the standard json library.
pip install python-telegram-bot[socks] installs the PySocks library. Use this, if you want to work behind a Socks5 server.
Getting started
Our Wiki contains a lot of resources to get you started with python-telegram-bot:
Introduction to the API
Tutorial: Your first Bot
Other references:
Telegram API documentation
python-telegram-bot documentation
Learning by example
We believe that the best way to learn this package is by example. Here are some examples for you to review. Even if it is not your approach for learning, please take a look at echobot.py, it is the de facto base for most of the bots out there. Best of all, the code for these examples are released to the public domain, so you can start by grabbing the code and building on top of it.
Visit this page to discover the official examples or look at the examples on the wiki to see other bots the community has built.
Logging
This library uses the logging module. To set up logging to standard output, put:
import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
at the beginning of your script.
You can also use logs in your application by calling logging.getLogger() and setting the log level you want:
logger = logging.getLogger() logger.setLevel(logging.INFO)
If you want DEBUG logs instead:
logger.setLevel(logging.DEBUG)
Documentation
python-telegram-bot’s documentation lives at readthedocs.io.
Getting help
You can get help in several ways:
We have a vibrant community of developers helping each other in our Telegram group. Join us!
Report bugs, request new features or ask questions by creating an issue or a discussion.
Our Wiki pages offer a growing amount of resources.
You can even ask for help on Stack Overflow using the python-telegram-bot tag.
Contributing
Contributions of all sizes are welcome. Please review our contribution guidelines to get started. You can also help by reporting bugs.
Donating
Occasionally we are asked if we accept donations to support the development. While we appreciate the thought, maintaining PTB is our hobby and we have almost no running costs for it. We therefore have nothing set up to accept donations. If you still want to donate, we kindly ask you to donate to another open source project/initiative of your choice instead.
License
You may copy, distribute and modify the software provided that modifications are described and licensed for free under LGPL-3. Derivatives works (including modifications or anything statically linked to the library) can only be redistributed under LGPL-3, but applications that use the library don’t have to be.
Integration module Telegram bot - FormDesigner Knowledge Base
To connect the integration module, you need to go to your personal account and select the "Modules" section in the required form:
You will see a list of all available modules. Click on the "+Add" icon in the Telegram bot item:
Module settings
You will see a pop-up window with the main settings of the Telegram bot integration module: nine0005
You need to enter in the "Chat ID" and "Message text" fields, respectively, the numerical value of the chat and in the message text, you can use all available macros (just like in email notifications) to substitute values from the form.
In addition to macros, the following html tags can be used in the message text:
bold, bold italic, italic inline URLinline fixed-width code
pre-formatted fixed-width code block
Chat ID is the numeric value of the chat to send notifications to. In order to find out this value, you need to connect our bot to Telegram. To do this, follow this link:
https://telegram.me/FormDesignerBot
You will be taken to this page:
How can I find out the Chat ID?
Click on the "Open in web" button and go to the Telegram page. If you are not authorized, then confirm the entrance to Telegram using your mobile phone. To find out the Chat ID, you need to add our @FormDesignerBot bot or, due to recent Telegram bans, add other bots: nine0005
- @userinfobot
- @ShowJsonBot
- @myidbot
!We recommend using our chat bot @FormDesignerBot (at the time of creating the instruction there were problems due to blocking)
After adding bots, write "/start" and you should receive a message with your Chat in response ID:
After receiving the ID, you can remove third-party bots, leaving only @FormDesignerBot. Now let's go back to our integration module and copy the received data: nine0005
We remind you that the "Message text" field must be filled in. Also, as in e-mail notifications, you can add the necessary macros to the text of the message. Don't forget to click the "Save" button. Now you will receive successfully completed applications in the Telegram messenger.
General Telegram channel
Our bot can also send requests to your general Telegram channel. This is very convenient, for example, you can add your managers to this channel and they will immediately see incoming applications. In order for our bot to send a message to the public channel, it must be added as a channel administrator. To do this, select your channel in Telegram (if it doesn’t exist, create it) and click on the "Administrators" item: nine0005
And click the "Add Administrator" icon:
Find our bot - @FormDesignerBot:
Then set up admin rights:
How can I find out the Chat ID of a channel?
!We recommend using our chat bot @FormDesignerBot (at the time of creating the instructions there were problems due to blocking and below you do not need to use a third-party bot)
Now add one more bot @get_id_bot to get the channel's Chat ID:
Also set up admin rights:
Next, you need to write "/my_id@get_id_bot" in the chat on the channel and you should receive a notification with the Chat ID value:
It is this Chat ID that must be specified in the settings of the Telegram module. Now all requests from the form will go to the general chat and all channel members will see them. Then remove the added bot from the administrators. nine0005
If you cannot find out the Chat ID in this way, then you can open the Web version of Telegram. Select your channel and copy the highlighted value in the browser line:
If you add "-100" before this value, you will get the required Chat ID.
It is recommended to use the mobile version of Telegram or Desktop version for PC to add administrators.
In the "Logic" tab, you can add logic rules to activate or deactivate the Telegram bot integration module. To do this, click on the "Add expression" button and select the rule under which the module will be activated or deactivated: nine0005
Creating a module for Telegram bot api in Python / Sudo Null IT News
Hello! I am a non-professional developer, programming is my hobby. And the "hobby" of this hobby is to take ready-made tools and create their analogues, just to understand an interesting topic (and also remake everything as you wish :)). This time, I decided to code an analog for such modules as aiogram or an asynchronous version of PyTelegramBotApi.
Disclaimer
There will be a lot of solutions in this article that will seem strange to you, there will be a lot of vulnerabilities, problems, etc. in my code. I am new to the topic and will not use my solution in serious projects. Therefore, I will be very happy if you give me some of your time and write about the main problems of my module in the comments. In general, for the sake of this I am writing an article. Thanks!)
pyTelegramBotApi problem
Before writing this article, I used the pyTelegramBotApi module for some time, during this time, I had to get into its source code several times and I noticed a detail that I did not like at all - this is the multiple duplication of code. For example, the very first process_updates function, which divides the updates received from the telegram into types and runs its own process_..._updates function for each of them, meets us like this:
new_messages = None new_edited_messages = None # There are 11 more of the same assignments chat_join_request = None for update in updates: logger. debug('Processing updates: {0}'.format(update)) if update.message: if new_messages is None: new_messages = [] new_messages.append(update.message) if update.edited_message: if new_edited_messages is None: new_edited_messages = [] new_edited_messages.append(update.edited_message) ... # There are 11 more of the same conditions if update.chat_join_request: if chat_join_request is None: chat_join_request = [] chat_join_request.append(update.chat_join_request) if new_messages: await self.process_new_messages(new_messages) if new_edited_messages: await self.process_new_edited_messages(new_edited_messages) ... # And here are 11 more of the same conditions if chat_join_request: await self.process_chat_join_request(chat_join_request)
In addition, the definition of each method that repeats the Telegram Bot Api methods looks like this:
async def send_message( self, chat_id: Union[int, str], text: str, parse_mode: Optional[str]=None, entities: Optional[List[types. MessageEntity]]=None, disable_web_page_preview: Optional[bool]=None, disable_notification: Optional[bool]=None, protect_content: Optional[bool]=None, reply_to_message_id: Optional[int]=None, allow_sending_without_reply: Optional[bool]=None, reply_markup: Optional[REPLY_MARKUP_TYPES]=None, timeout: Optional[int]=None) -> types.Message:
Thus, the module contains a complete copy of the API documentation, including all method arguments.
In my opinion it is:
-
It makes no sense.
-
Leads to situations where the API has been updated, but the module has not yet - and the module developer has to implement exactly the same logic in it that was added to the API. I personally encountered a situation where I had to add the module myself, since a new version of the api was released, and the developer had not had time to update it yet. nine0005
-
And, if I'm not mistaken, it violates the DRY principle: precisely because one logic change must be implemented in both the API code and the module code.
Idea
Therefore, I decided to make my own module, which I will try to eliminate all these shortcomings. This module should be "light" - that is, it should not contain any duplication of the API. And for example, if someone wants to use the "sendHolography" API method, the module should not interfere with this, since this is a duplication of the work of the API, which will still send an error:0005
{"ok":false,"error_code":404,"description":"Not Found"}
Or will not send if holographic monitors appear by this moment and the "sendHolography" method with them. And the module, unlike pyTelegramBotApi, will be automatically ready for such an update.
Let's start
I'm creating a Bot class, it should contain all Telegram Bot Api methods, but in order for the module not to depend on the actual set of methods, I'll define the __getattr__ method. It should return some objects, the call of which will execute the method, it will be a nested function. Also, I rename it and convert it to a method - so that everything is beautiful. And I add this method to the cache so as not to create it again next time. nine0005
from types import MethodType class bot: def __init__(self): self.cache = {} def __getattr__(self, attr: str): if attr in cache: return self.cache[attr] url = "/bot"+self._token+"/"+snake_case_to_camel_case(attr) async def function(bot, **kwargs): pass method = MethodType(function, self) self.cache[attr] = method return method
To make asynchronous get requests, you need to create an aiohttp.ClientSession object, but if you try to create it in Bot.__init__, you will get an error:
The object should be created within an async function sort of a crutch - I'll redefine the Bot.__new__ function as asynchronous, create a session in it. In this case, by calling __new__ when creating an object, the user will receive a coroutine, and then, after await, the object itself will be returned:0005def __init__(self, token: str): self. _http_exceptions = {} self._token = token self.cache = {} async def __new__(cls, *args, **kwargs): obj = super().__new__(cls) obj._session = aiohttp.ClientSession(url) obj.__init__(*args, **kwargs) return objawait Bot(token)You can see the _http_exceptions variable in the previous code block. Why is she needed? I can create an exception class for each http error code that telegram sends, but what if new methods are added to the telegram bot api that will send new error codes? Or maybe there will be a new version of http that will add new error codes? In this case, you will have to update the library! There is a better solution!)
class TelegramError(Exception): passclass Bot: ... def get_http_exception(self, number: int): if number in self._http_exceptions: return self._http_exceptions[number] else: HttpException = type(f"TelegramError{number}", (TelegramError,), {}) self. _http_exceptions[number] = HttpException return HttpExceptionThe first argument of the type class constructor is the name of the class, the second is a tuple of classes from which the created one should be inherited, and the third is a dictionary of class attributes. Thus, if an error is requested for the first time, its own class is created for it, inheriting from TelegramError and stored in the Bot._http_exceptions dictionary. nine0005
Now you can write the same nested function that will turn into different methods and send requests to the server.
async def function(bot, **kwargs): async with bot._session.get(url, params=kwargs) as response: response_data = await response.json() if response_data["ok"]: return response_data["result"] else: raise bot.get_http_exception(response_data["error_code"])( response_data["description"] )If I get an http error, I create the necessary exception and throw it. nine0005
Now we need to create a system that will constantly request updates from the server, and, if any, run the desired message handler. In PyTelegramBotApi, the choice of the desired handler is implemented using a filter system, for example:
@bot.message_handler(commands=["start", help]) def handler1: ... #for /start and /help commands @bot.message_handler(content_types=["photo"], chat_types=["private"]) def handler2: ... #for photos in private chats @bot.message_handler(func=lambda msg: msg.from_user.id in admins) def handler3: ... #for messages whose senders are in the list of admins. nine0023I'm not happy with this approach for the following reason: let's say I want one of the handlers to run only when a message is received, about which it is written in the database that it is an admin or owner. At the same time, the work of the handler itself should depend on whether the user is still an admin or owner. It turns out that I will need to make two queries to the database: one in the filter, and the other in the handler, and this is not efficient. Yes, you can split this handler into two: one for messages from admins, and the other for messages from owners. But then a part of the logic that is common for admins and owners will have to be moved into separate functions, which is not convenient. nine0005
Therefore, I chose another option. Let the first defined handler run first. In it, the developer can add some kind of condition - and on it throw an exception called NextHandler. In this case, the next handler is called. If the handler is executed without exception, the event is considered handled.
class NextHandler(Exception): def __init__(self): self.args = ("don't use this error outside of light_telegram_bot handler")class BotPolling: def __init__(self, bot, start_offset=0): self._handlers = [] self._bot = bot self._offset = start_offset async def start(self, timeout=60, **kwargs): try: while1: updates = await self._bot.get_updates( timeout=timeout, offset=self. _offset, **kwargs ) if updates: self._offset = updates[-1]["update_id"]+1 for update in updates: for handler in self._handlers: try: await handler(update) except NextHandler: pass else: break except Exception: raise LightTelegramBotPollingError() def handler(self, f): self._handlers.append(f)And here, for comparison, here are the same three handlers in my module:
@bot.handler() def handler1(message): if not test_commands(message.text, ["start", "help"]): raise NextHandler() @bot.handler() def handler2(message): if not ("photo" in message) and message.chat_type == "private" raise NextHandler() @bot.handler() def handler3(message): if not msg["from_user"]["id"] in admins: raise NextHandler()Yes, it turned out to be longer, but, on the other hand, it is much more universal.