# Python TrueConf Bot SDK ## METADATA - **Version:** 1.5.4 - **Generated:** 2026-10-12T17:33:26+00:00 - **URL:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/ --- ## INDEX - [Python Library for TrueConf Chatbot Connector ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/index.md) - [Features ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/features.md) - [Learn](#learn) - [Getting Started ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/getting-started.md) - [Authentication ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/authentication.md) - [Handling Requests ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/parse-messages.md) - [Filters ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/filters.md) - [Middleware ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/middleware.md) - [FSM — Finite State Machine ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/fsm.md) - [Sending messages ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/send_message.md) - [Interactive Buttons ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/buttons.md) - [Chat activity indicator ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/typing_indicator.md) - [Shortcuts ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/shortcuts.md) - [Using enumerations ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/enums.md) - [Data Types ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/types.md) - [Working with Files ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/files.md) - [Restrictions ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/restrictions.md) - [Reference](#reference) - [Class Bot ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Bot.md) - [Class Router ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Router.md) - [Class Dispatcher ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Dispatcher.md) - [Enums](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Enums.md) - [Types ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Types.md) - [Formatting](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Formatting.md) - [Chat activity](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/chat_activity.md) - [Exceptions](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Exceptions.md) - [Responses ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Responses.md) - [List of Changes ⚓︎](https://trueconf.github.io/python-trueconf-bot/v1.5.4/release_notes.md) --- ## CONTENT # DOCUMENT: Features ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/features.md # Features⚓︎ ## Asyncio-based Asynchronous Architecture⚓︎ The entire system is built using async/await, ensuring high performance and non-blocking operations. ## Familiar aiogram-like Design⚓︎ Leverages familiar concepts: Router, decorators, shortcuts like message.answer, message.reply, filters, and even magic-filter (F.text, F.document, F.photo). ## Convenient Handling of Incoming Events⚓︎ All incoming JSON payloads are automatically transformed into Python classes (Message, AttachmentContent, UploadingProgress, etc.), making data handling simple and type-safe. ## Decorators for Routing⚓︎ The router enables elegant and structured handling of events: ``` from trueconf import Router, Message from trueconf.enums import MessageType from trueconf.filters import F router = Router() @router.message(F.text.startswith("/start")) async def on_start(msg: Message): await msg.answer("Hello! I'm TrueConf bot 👋") @router.message(F.document.mime_type == "application/pdf") async def on_pdf(msg: Message): await msg.reply("Thanks for the PDF!") ``` ## Two Connection Options⚓︎ - Using a pre-obtained JWT token: ``` bot = Bot(server="video.example.com", token="...") ``` - Or via login and password authentication: ``` bot = Bot.from_credentials(server, username, password) ``` ## Aliases and Shortcuts in aiogram Style⚓︎ Common methods are available for messages: ``` await msg.answer("Text to chat") await msg.reply("Reply to a message") await msg.copy_to(chat_id="other_chat") ``` ## Multi-Bot Support⚓︎ You can run multiple bots simultaneously and route events separately for each one. ## Asynchronous Transport — WebSocket⚓︎ All communication with the server is handled via WebSocket, which is faster and more efficient than traditional REST requests. ## Magic-filter, Just Like in aiogram⚓︎ Exactly the same as in aiogram: ``` @router.message(F.photo) async def on_photo(msg: Message): ... @router.message(F.document.mime_type.in_(["application/pdf", "application/msword"])) async def on_doc(msg: Message): ... ``` ## Files and Uploads⚓︎ Asynchronous file upload and download are supported. Files can be downloaded to a temporary directory or a specified path. ``` path = await bot.download_file_by_id(file_id) await msg.answer(f"File downloaded to {path}") ``` ## Full Set of Public API Methods⚓︎ The library implements all core TrueConf API methods: sending messages, uploading/downloading files, polls, conferences, participant management, and more. October 1, 2026 September 3, 2025 --- # DOCUMENT: List of Changes ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/release_notes.md # List of Changes⚓︎ ## 1.5.4⚓︎ Added: - The `Message.forwarded_message` property — the original of a forwarded message - The `max_size` parameter in `URLInputFile.read()` — aborts the download with `FileSizeTooLargeError` when the content exceeds the limit Fixed: - Parsing of forwarded messages (type `201`): `ForwardMessage` inherits from `Message` and gains all its parameters — `text`, `voice`, `document`, `reply_message`, `bind` and others; nested forwards are resolved recursively. A forwarded voice message no longer drops the whole update with `InvalidFieldValue` - `getChatHistory`: the `fromMessageId` parameter is no longer sent as `null` — it caused the `399 WRONG_PAYLOAD_FORMAT` server error - `URLInputFile`: the file size is now computed from the actually downloaded body. Sources that return a new file per request (e.g. camera snapshots) led to `400 Bad Request`: the size was taken from the headers of one response while the body of another was uploaded - `URLInputFile`: redirecting URLs and servers rejecting HEAD requests are handled correctly; an error response (e.g. 404) is no longer treated as the file with the error-page size Changed: - `URLInputFile.prepare()` reads only HTTP headers and does not download the body; `Content-Length` is treated as an estimate. The exact size becomes known after the download and is the size declared to the server - One `URLInputFile` object corresponds to one content: repeated sends and `clone()` reuse the downloaded bytes. Need a fresh file (e.g. a new camera frame) — create a new object - `read(max_size=...)` aborts the download when the limit is exceeded; the `bot.max_file_size` limit now applies to URL files as well - Metadata completeness (a non-empty name + size) is now guaranteed by the file classes themselves: `URLInputFile` resolves the name in `prepare()` (otherwise `FileUploadError`), `BufferedInputFile` and `FSInputFile` reject an empty `file_name` (`TypeError`/`ValueError`) - `Message.box` is now optional — a forwarded message carries no `box` ## 1.5.3⚓︎ Fixed: - Connect task cancellation in Python 3.10: an external cancellation (`task.cancel()`) now propagates to the caller - The `httpx2` dependency is back to `>=2.7.0` (previously `>=2.13.0`) - Tests are wired into GitHub Actions; CI updated: actions moved to Node 24, `setup-uv` pinned to v10.2.0, caching added ## 1.5.2⚓︎ Added: - Python 3.14 support declared Fixed: - The version compatibility table in README ## 1.5.1⚓︎ Added: - Version compatibility check: TrueConf Server 5.5.3–5.5.5 requires `python-trueconf-bot >=1.2.1,Fixed: - The version compatibility table in README ## 1.5.0⚓︎ 🚀 Major release! This is not only a set of new features, but also extensive work on stability. Tip Support for Python 3.10 ends on 31.10.2026, together with the end of its official support by the Python Software Foundation. Added: - Support for incoming voice messages with the `MessageType.VOICE_MESSAGE` (`205`) type - Support for inline buttons via `InlineKeyboardMarkup`/`InlineKeyboardButton` (actions: command, URL, message, copy). Requires TrueConf Server 5.5.6 and TrueConf client apps for Windows, macOS and Linux version 8.6.0, TrueConf for Android 3.3.0, TrueConf for iOS 4.2.0 - Callback queries for handling button presses: the `@router.callback_query()` handler, `callback_query.edit_message(...)` and `callback_query.answer(...)` shortcuts - Buttons with `wait_reply=True` and the `answerCommand` method temporarily raise `NotImplementedError`: the functionality is supported by TrueConf Server but awaits support from client applications. Once it becomes available, a new release will be published that removes this limitation - Chat object: the `chat` field with the `Chat` model in `Message` and `LastMessage` - Message replies: incoming reply messages now include `Message.reply_message` with the content of the original message being replied to - System messages: the `SystemMessage` model and the `@router.system_message()` handler - Reply with a quote via the `quote` parameter in `Message.reply()` and `Bot.send_message()`, as well as the `Message.quote` property - Chat activity indicator: the `Bot.send_chat_activity()` method, the `ChatActivity` enum and the `ChatActivitySender.typing(...)` context manager - In-memory file download size limit via the `max_in_memory_download_size` parameter - The `LineBreak` node in `trueconf.utils.formatting` (` ` for HTML, `\n` for Markdown) - The `message.location` and `message.contact` shortcuts for geolocation and contacts (vCard files and trueconf links) - OAuth2 authentication via `Bot.from_oauth()` for servers with login/password authentication disabled. Requires TrueConf Server 5.5.3+ - New exceptions: `WSConnectionError`, `InMemoryDownloadLimitExceededError`, `FileUploadError`, `OAuthMissingScopeError`, `PasswordAuthDisabledError` - Text descriptions for API error codes (399, 400–408) in `ApiError.message()`. Codes 400–408 relate to files and replace the single generic code 310 (“error while sending”) — now it is clear what exactly went wrong during the send - The `caption_message_id` field in `SendFileResponse` — the ID of the caption message sent with a file; allows changing the file caption via `edit_message(...)` - A custom `User-Agent` on all library requests in the format `python-trueconf-bot/ (Python/; /)`, e.g.: `python-trueconf-bot/1.5.0 (Python/3.12.4; Darwin/24.0.0)` Changed: - The `Underline` node in `trueconf.utils.formatting` now also renders in Markdown (`__text__`) — previously underline worked only in HTML markup - File download: the `file_path` parameter sets the exact output path, parent directories are created automatically - The `mimetype` parameter was renamed to `mime_type` - `ws_max_retries`/`ws_max_delay` behavior: once the attempts are exhausted, the connection ends with `WSConnectionError` - Bot shutdown now waits for running handlers and closes the WebSocket transport; a `timeout` parameter was added to `shutdown()` - The HTTP client was migrated from `httpx` to `httpx2` Fixed: - Parsing of system messages in chat history and API responses - File upload errors: the caller now receives `FileUploadError` with the original cause - Infinite WebSocket reconnection after the retry limit is exhausted - The WebSocket connection was not closed on bot shutdown — the session now properly closes the attached socket - Download URLs and tokens no longer appear in logs in full: the query string is stripped from URLs (`https://server/.../files/download?token=...` → `https://server/.../files/download`), and tokens in debug logs are truncated to the last 30 characters - Token acquisition in `Bot.from_credentials()` now respects the `https` and `web_port` parameters — previously the token was always requested via https:443, even if the server runs on http or a non-standard port Deprecated: - The `Message.chat_id` property — use `message.chat.chat_id` instead - The `dest_path` parameter — use `file_path` instead (will be removed in version 2.0) - The `mimetype` parameter — use `mime_type` instead ## 1.4.4⚓︎ Fixed: - Fixed a library (bot) crash occurring when the LastMessage contained a notification about a chat avatar change #15. ## 1.4.3⚓︎ Fixed: - Checking server version. Currently, the check is performed via the API first; if an error occurs, the check is based on the TrueConf service status. ## 1.4.2⚓︎ Fixed: - Bot crash when server version field is empty ## 1.4.1⚓︎ Added: - New parameter `timeout` in class `Bot` and `Bot.from_credentials()` method Fixed: - System events like `ChangedFileUploadLimits` don't have chat_id or author, which caused `DefaultKeyBuilder` to raise `RuntimeError`. Now `FSMMiddleware` checks for `chat_id/user_id` before building FSM context. System events pass through without FSM context. Refactor: - Improve network timeout logic for file download and upload: - Remove hardcoded `chunk_size` from `httpx.stream` to prevent false ReadTimeout on slow networks. - Configure `aiohttp.ClientTimeout` using `sock_read` instead of `total` to allow long file uploads without socket freezes. - Enforce strict `int | float` types for timeouts, removing redundant `None` checks - Update method docstrings to clearly reflect adaptive timeout behavior. ## 1.4.0⚓︎ Added: - FSM (Finite State Machine) — a finite state machine mechanism. It allows you to implement step-by-step dialogs, such as questionnaires, forms, and setup wizards. States are declared declaratively using `StatesGroup`/`State`, while data is stored in `FSMContext`. It supports nested groups, multiple storage strategies, and state-based filtering via `StateFilter`. Learn more: FSM. - Middleware — a layer for processing events before and after handlers. It allows you to log events, block them, check access, and modify data. It supports two types: outer middleware, which runs before filters, and inner middleware, which runs after filters. Learn more: Middleware. - The `skip_self_messages` parameter in `Bot()`. By default, it is set to `True`, so the bot automatically ignores messages sent by itself. It can be disabled with `skip_self_messages=False`. - Added `Message.reply_message`, containing the full message being replied to. - Added the `SystemMessage` model for system Envelopes in live updates and chat history, together with the `@router.system_message()` handler. Fixed: - The history-clearing notification now preserves `for_all` as the server-provided `bool` value. ## 1.3.0⚓︎ Added: - Added a health-check mechanism for tracking the bot connection state: - push model via the `Bot(on_health_check=func_callback)` callback, which is called when the connection status changes; - pull model via the `bot.health_check()` method, which returns the current bot state; - `connected`, `authorized`, and `disconnected` statuses. - Added `bot.me_id` support for storing the authorized bot identifier. - Added the `message.mention` shortcut, which returns `True` if the current bot is mentioned in the message or if `@all` is used. - Added the `trueconf.utils.formatting` module for convenient HTML/Markdown message construction with classes: `Text`, `Bold`, `Italic`, `Underline`, `Strikethrough`, `Link`, `Mention`, `AllMention`. - Added the `truststore` dependency for working with the system trusted certificate store. - Added the `SSLVerify` type for unified typing of the `verify_ssl` parameter: `bool | str | ssl.SSLContext`. - Added the `bot.me_chat` property as the new name for getting the `chat_id` of the "Favorites" chat. Changed: - Updated the `verify_ssl` behavior: - `verify_ssl=True` uses the system trusted certificate store through `truststore`; - `verify_ssl=False` disables certificate verification; - `verify_ssl="/path/to/ca.pem"` uses a custom CA bundle; - `verify_ssl=ssl.SSLContext(...)` uses the provided SSL context. - Updated the SSL logic for WebSocket connections: a single `self.ssl_context`, created via `build_ssl_context(...)`, is now used. - Updated bot initialization logging: logs now include human-readable information about the SSL context. Fixed: - Fixed failures caused by incomplete certificate chains. Certificate chains can now be verified successfully by using the system trusted certificate store through `truststore` or by passing a custom SSL context. Deprecated: - The asynchronous `bot.me` property, which returns the `chat_id` of the "Favorites" chat, is now deprecated. Use `await bot.me_chat` instead. Documentation: - Added Context7 AI Assistant: interactive support for code and documentation. - Added a new Sending messages documentation section covering: - getting `chat_id`; - sending text messages via `bot.send_message(...)`; - replying with `reply_message_id`; - forwarding messages via `bot.forward_message(...)`; - text formatting via `trueconf.utils.formatting`; - the 4096-character message length limit and using `safe_split_text(...)`. - Added health-check documentation covering: - push model via callback; - pull model via `bot.health_check()`; - an example of combined usage with an HTTP health endpoint. - Added and updated docstrings for the formatting module, `Message.mention`, `verify_ssl`, and the health-check API. - Added new sections: Shortcuts, Restrictions, Formatting, Exceptions. ## 1.2.3⚓︎ Added: - Added a 10-second server response timeout. If no response is received within the timeout, an `asyncio.TimeoutError` is raised: `Request to {self.__api_method__} timed out after {timeout}s` (#12). Fixed: - Fixed cases where Mashumaro failed to parse a response, which could cause the application to crash (#8, #11). ## 1.2.2⚓︎ Fixed: - Fixed a missing dependency: the `packaging` package, which is required to check the library version at bot startup. ## 1.2.1⚓︎ Added: - Added support for TrueConf Server 5.5.4. - Added the `receive_system_messages` flag to `Bot()` and `Bot.from_credentials()` to enable or disable receiving system messages. - Added the new `bot.get_chat_participant()` method, which replaces `bot.has_chat_participant()`. Fixed: - Fixed support for TrueConf Server 5.5.3+. Removed an unnecessary version check that prevented the code from running with library version 1.2.0. - Fixed documentation links to `llms.txt` and `llms-full.txt`. Changed: - When retrieving file information via `bot.get_file_info(file_id=...)`, the response now returns the `file_id` field instead of `info_hash`. Deprecated: - The `bot.has_chat_participant()` method has been deprecated. Use `bot.get_chat_participant()` instead. ## 1.2.0⚓︎ Added: - Added support for TrueConf Server 5.5.3, including: - chat title editing with `bot.edit_chat_title(...)`; - chat avatar editing with `bot.edit_chat_avatar(...)`; - chat history clearing with `bot.clear_chat_history(...)`; - retrieving file storage limits with `bot.get_file_info_upload_limits(...)`; - a new file transfer approach where the `file_name` parameter is now required for `FSInputFile(...)` and other file upload methods. - Added caching for file storage limit settings. These settings are now used for pre-upload validation, and the library raises an exception if a file does not meet the configured constraints. - Added `python-magic` and `filetype` libraries for more reliable file type detection based on magic numbers (byte signatures). - Added automatic file extension appending when a filename does not contain an extension. - Improved WebSocket connection stability with exponential backoff and a configurable retry strategy. You can control the maximum number of reconnection attempts with `ws_max_retries` and the maximum delay between attempts with `ws_max_delay` (#6). - Added TrueConf Server version validation. The library now raises a `RuntimeError` with upgrade instructions if an incompatible server version is detected. - Added the `safe_split_text` utility for safely splitting long messages exceeding 4096 characters into chunks of up to 4096 characters. This is especially useful for AI agents that generate long responses. - Added AI-friendly documentation builds: `llms.txt` and `llms-full.txt`. - Added and expanded logging. Fixed: - Fixed an issue with sending stickers in TrueConf Server 5.5.3+. - Fixed issue #7. - Fixed various minor bugs and made general improvements. Deprecated: - The `filename` and `mimetype` parameters are now deprecated. - Please migrate to the new `snake_case` parameter naming, as the old parameters will be removed in future versions. ## 1.1.10⚓︎ Fixed: - Fixed the missing `file_id` parameter in `SendFileResponse`. ## 1.1.9⚓︎ Added: - Added TrueConf Server version validation. The library now raises a `RuntimeError` with update instructions if an incompatible server version is detected. ## 1.1.8⚓︎ Fixed: - Added `verify_ssl` support for WSS connections. Previously, SSL verification was unconditionally bypassed when `https` was enabled; it is now correctly controlled by the configuration flag. ## 1.1.7⚓︎ Added: - Added `reply_photo`, `reply_document`, and `reply_sticker` shortcut methods to the `Message` class. - Added `reply_message_id` support to multiple methods and to the `SendFile` class. Fixed: - Fixed `quote_fields` being set to `False` in `aiohttp.FormData`. - Set the default value of `last_message` to `None` in `GetChatByIdResponse` (fixes #4). Deprecated: - `reply_message` is now deprecated. Use `reply_message_id` instead. ## 1.1.6⚓︎ Refactored: - Replaced local `verify_ssl` usage with `self.verify_ssl` in class methods. ## 1.1.5⚓︎ Fixed: - Prevented `run()` from hanging when the connect task fails. - Properly propagate `ApiErrorException` and other errors to the caller. ## 1.1.4⚓︎ Fixed: - Removed the `chat_id` field from `RemoveChatResponse` (#1). ## 1.1.3⚓︎ Fixed: - Fixed event propagation for multiple routers and subrouters. ## 1.1.2⚓︎ Added: - Bumped the development status. - Added `typing_extensions` to dependencies. - Added and updated the downloads badge. - Added imports for `Self` and `Unpack` from `typing_extensions`. Fixed: - Fixed `Message` shortcuts not working. ## 1.1.1⚓︎ Added: - New classes for working with files: `FSInputFile`, `BufferedInputFile`, `URLInputFile`. More details can be found in the documentation. - Support for displaying message history `display_history = True` when adding a user to a group chat or channel. - Support for request and event for: - role changes in a group chat or channel (request, notification); - creation of the “Favorites” chat (request, notification). - Ability to send files with a caption. - Shortcut `.save_to_favorites()` for quickly saving a message to the "Favorites" chat. - The asynchronous property `await bot.me`, which returns the `chat_id` of the "Saved Messages" chat. Fixed: - Stickers sent via `bot.send_sticker()` were displayed with a background due to an incorrect MIME type. - The method `.remove_participant_from_chat()` did not work when an incomplete TrueConf ID was specified. - Error unpacking the participant list due to an incorrect alias. - Sometimes, when obtaining a token using `.from_credentials()`, a `400 Bad Requests` error would occur when using a digit password. Modified: - The `bot.server_name` property has become asynchronous. Use it as `await bot.server_name`. ## 1.0.0⚓︎ 🎉 First Release! - Stable version of the python-trueconf-bot library. - Support for all major TrueConf ChatBot API methods. - Aliases and keyboard shortcuts in the aiogram style (message.answer, message.reply, etc.). - Asynchronous data transmission via the WebSocket protocol. - Working with files (sending and uploading). - Documentation: trueconf.github.io/python-trueconf-bot/ - PyPI: pypi.org/project/python-trueconf-bot/ October 12, 2026 November 12, 2025 --- # DOCUMENT: Python Library for TrueConf Chatbot Connector ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/index.md # Python Library for TrueConf Chatbot Connector⚓︎ Welcome to the documentation of python-trueconf-bot — a library that allows you to create and manage chatbots for the TrueConf platform using WebSocket and asyncio. This library is designed to simplify the development of chatbots by providing ready-made tools for connecting, processing incoming events, and sending responses. With it, you can create bots for automating tasks, integrating with external services, and enhancing communication within your organization. ## Key features⚓︎ - Asynchronous operation using asyncio - Support for WebSocket connections - Convenient routing of incoming messages - Built-in filters for processing different types of updates - Easy integration with external Python libraries ## Installation⚓︎ ### Requirements⚓︎ - Python 3.10+ - Installed dependencies: `websockets`, `httpx2`, `mashumaro`, `pillow`, `aiofiles`, `magic-filter` - It is recommended to use virtualenv or poetry for dependency isolation. ### Installation using pip⚓︎ ``` pip install python-trueconf-bot ``` ## Comparison with aiogram⚓︎ | Feature | aiogram (Telegram) | python-trueconf-bot (TrueConf) | | --- | --- | --- | | Asynchronous | asyncio | asyncio | | Routing decorators | `@router.message(...)` | `@router.message(...)` | | Message filtering | `F.text`, `F.photo`, `F.document` | `F.text`, `F.photo`, `F.document` | | Magic-filter | ✅ | ✅ | | Aliases (shortcuts) | `message.answer()`, `message.reply()` | `message.answer()`, `message.reply()` | | Bot initialization | `Bot(token="...")` | `Bot(server, token="...")` or `Bot.from_credentials(server, login, password)` | | JSON → Python | Pydantic models | Mashumaro dataclasses | | Transport | HTTPS + long polling / webhook | Asynchronous WebSocket | | Working with files | `bot.get_file(...)` + `bot.download_file(...)` | `message.photo.download()`, `message.document.download()`, `bot.download_file_by_id(...)` | ## LLM Files⚓︎ - llms.txt - llms-full.txt October 1, 2026 September 3, 2025 --- # DOCUMENT: Getting Started ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/getting-started.md # Getting Started⚓︎ Before getting started, we recommend creating and activating a virtual environment to isolate your project dependencies: ``` python -m venv .venv source .venv/bin/activate # Linux / macOS .venv\Scripts\activate # Windows PowerShell ``` ## Installing python-trueconf-bot⚓︎ To begin working with python-trueconf-bot, install the package from the global PyPI repository: ``` pip install python-trueconf-bot ``` Info Upon installation, dependencies will be automatically pulled in: `websockets`, `httpx2`, `mashumaro`, `pillow`, `aiofiles`, `magic-filter`. ## Creating a Basic Echo Bot⚓︎ First, import the required classes: ``` from trueconf import Bot, Dispatcher, Router, F from trueconf.types import Message ``` Next, create instances of `Router` and `Dispatcher` and connect them: ``` r = Router() dp = Dispatcher() # dp.include_router(r) ``` The bot supports three authentication methods: token, login and password, or OAuth2. Choose the method that best fits your setup. For details, see Authentication. ### Token-Based Authentication⚓︎ If you're using token-based connection, obtain the token as described in the official API documentation. It is recommended to store the token in an environment variable or `.env` file. Don’t forget to add `.env` to `.gitignore` if working with public repositories. ``` from os import getenv TOKEN = getenv("TOKEN") bot = Bot(server="video.example.com", token=TOKEN, dispatcher=dp) ``` Note The token is valid for one month from the moment it is created. However, an already authorized connection remains active until it is closed, even after the token has expired. In theory, such a connection can persist for years. ### Login/Password Authentication⚓︎ Use the `.from_credentials` method: ``` bot = Bot.from_credentials(username="echo_bot", password="123tr", server="10.110.2.240", dispatcher=dp) ``` Info Each time from_credentials() is called, the bot requests a new token from the server. The token lifespan is 1 month. ### Authentication with Login and Password Disabled⚓︎ If login and password authentication is disabled on the server for security reasons, authenticate the bot through an OAuth application with `.from_oauth`. In addition to the login and password, you need the application's `client_id`: ``` bot = Bot.from_oauth(username="elisa", password="123tr", client_id="client_id_of_app", server="10.110.2.240", dispatcher=dp) ``` Tip For authentication methods, requirements, parameters, and errors, see Authentication. ### Message Handler⚓︎ Now let’s create a simple handler for incoming messages. It will reply with the same text (a classic "echo bot"): ``` @r.message(F.text) async def echo(message: Message): await message.answer(message.text) ``` ### Running the Bot⚓︎ Run the bot inside an asynchronous `main()` function passed to `asyncio.run()`: ``` async def main(): await bot.run() import asyncio if __name__ == "__main__": asyncio.run(main()) ``` Why async/await? The python-trueconf-bot library is built on asyncio. This means that all network operations (connecting to the server, receiving and sending messages) are asynchronous and non-blocking. Therefore: - handlers are written as `async def`, - method calls use `await`, - the launch is managed via `asyncio.run(...)`. This approach allows handling multiple events and messages in parallel — without delays or blocking. ### Automatic Connection Recovery⚓︎ If the WebSocket connection to the server is interrupted, the bot will not stop immediately. Instead, it will automatically attempt to reconnect and continue receiving events. Reconnection uses an exponential backoff strategy: after each failed attempt, the delay increases but does not exceed the `ws_max_delay` value. This helps prevent excessive requests to the server during temporary network issues. By default, the following reconnection parameters are used: ``` bot = Bot( server="video.example.com", token=TOKEN, dispatcher=dp, ws_max_retries=5, ws_max_delay=60, ) ``` | Parameter | Type | Default | Description | | --- | --- | --- | --- | | `ws_max_retries` | `int` | `5` | Maximum number of connection attempts on network/IP errors before giving up | | `ws_max_delay` | `int` | `60` | Maximum delay between reconnection attempts (in seconds) | If your bot runs in an unstable network environment or the server may be temporarily unavailable, you can increase these values: ``` bot = Bot( server="video.example.com", token=TOKEN, dispatcher=dp, ws_max_retries=10, ws_max_delay=120, ) ``` Note In case of a normal WebSocket disconnection, the bot will attempt to reconnect using exponential backoff. If the server address is incorrect, the bot will not be able to establish a connection. In this case, the number of retry attempts is limited by `ws_max_retries`, after which a connection error will be raised. ## Health-check⚓︎ python-trueconf-bot supports two approaches for checking bot state: - push model — the bot calls a callback function when the connection state changes; - pull model — the application manually requests the current state via `bot.health_check()`. ### Push: callback on state changes⚓︎ The callback is passed via the `on_health_check` parameter when creating the bot. The function must be asynchronous and accept a dictionary with the current status: ``` async def on_health_check(status: dict): print("Bot status changed:", status) bot = Bot.from_credentials( server="video.example.com", username="echo_bot", password="123tr", dispatcher=dp, on_health_check=on_health_check, ) ``` The callback is triggered whenever the WebSocket connection or authorization state changes. For example, the bot may emit the following statuses: - `connected` — the WebSocket connection is established, but the bot is not authorized yet; - `authorized` — the bot has successfully authenticated; - `disconnected` — the connection has been lost. Example payload: ``` { "status": "authorized", "websocket_connected": true, "authorized": true, "user_id": "echo_bot@video.example.com", "server": "video.example.com", "port": 443, "protocol": "https", "timestamp": "2026-05-06T12:00:00+00:00", } ``` The push model is useful when you need to react immediately to state changes: write logs, notify monitoring systems, update application state, or alert administrators. ### Pull: manual health check⚓︎ The `bot.health_check()` method returns the current bot state at the moment it is called: ``` status = bot.health_check() print(status) ``` Example response: ``` { "status": "authorized", "websocket_connected": true, "authorized": true, "server": "video.example.com", "port": 443, "protocol": "https", "timestamp": "2026-05-06T12:00:00+00:00", } ``` The pull model is useful for HTTP health-check endpoints, such as FastAPI, Zabbix, Kubernetes probes, or other monitoring systems: ``` from fastapi import FastAPI app = FastAPI() @app.get("/health") def health(): return bot.health_check() ``` ### Combining push and pull⚓︎ In practice, it is often convenient to use both approaches together. The callback updates the latest known state, while the HTTP endpoint exposes it to monitoring systems: ``` from fastapi import FastAPI app = FastAPI() bot_status = {"status": "disconnected"} async def on_health_check(status: dict): bot_status.update(status) bot = Bot.from_credentials( server="video.example.com", username="echo_bot", password="123tr", dispatcher=dp, on_health_check=on_health_check, ) @app.get("/health") def health(): return bot_status ``` In this setup, the bot reports state changes through the callback, while external monitoring systems retrieve the current status through HTTP requests. October 1, 2026 September 3, 2025 --- # DOCUMENT: Authentication ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/authentication.md # Authentication⚓︎ The library supports three ways to authenticate a bot on TrueConf Server: | Method | API | When to use it | | --- | --- | --- | | Token | `Bot(server, token=...)` | You already have a token obtained manually or through the API | | Login and password | `Bot.from_credentials(...)` | Login and password authentication is enabled on the server | | OAuth2 | `Bot.from_oauth(...)` | Login and password authentication is disabled on the server | ## Token authentication⚓︎ Obtain a token as described in the official API documentation. We recommend storing the token in an environment variable or a `.env` file. If you use a public repository, remember to add `.env` to `.gitignore`. ``` from os import getenv TOKEN = getenv("TOKEN") bot = Bot(server="video.example.com", token=TOKEN, dispatcher=dp) ``` Note A token is valid for one month from the time it is created. However, an authenticated connection remains active until it is closed, even after the token expires. In theory, such a connection can remain active for years. ## Login and password authentication⚓︎ The `Bot.from_credentials()` method authenticates the bot with a login and password: ``` bot = Bot.from_credentials( username="echo_bot", password="123tr", server="video.example.com", dispatcher=dp, ) ``` Info Every call to from_credentials() requests a new token from the server. Each token is valid for one month. The main parameters after `password` are keyword-only: | Parameter | Type | Default | Description | | --- | --- | --- | --- | | `dispatcher` | `Dispatcher` | `None` | Dispatcher used to register handlers | | `receive_unread_messages` | `bool` | `False` | Whether to receive messages that arrived while the bot was offline | | `receive_system_messages` | `bool` | `False` | Whether to receive system messages | | `skip_self_messages` | `bool` | `True` | Whether to ignore messages sent by the bot itself | | `verify_ssl` | `bool | str | ssl.SSLContext` | `True` | SSL certificate verification settings | | `https` | `bool` | `True` | Whether to use HTTPS | | `web_port` | `int` | `None` | WebSocket port (`443` with HTTPS and `4309` without HTTPS by default) | | `ws_max_retries` | `int` | `5` | Maximum number of connection attempts after network errors | | `ws_max_delay` | `int` | `60` | Maximum delay between connection attempts, in seconds | | `timeout` | `float | int` | `10.0` | Server response timeout | | `on_health_check` | `Callable` | `None` | Callback invoked when the connection state changes | For the complete parameter list, see the `Bot.from_credentials()` reference. If login and password authentication is disabled on the server, the method raises `PasswordAuthDisabledError`. Use `Bot.from_oauth()` instead. ## OAuth2 authentication⚓︎ If login and password authentication is disabled on the server for security reasons, the bot cannot use `from_credentials()`. It does not support authentication through NTLM, Kerberos, other SSO protocols, or MFA. In this case, create an OAuth application on the server and authenticate the bot with `Bot.from_oauth()`. In addition to the login and password, you need the application's `client_id`: ``` bot = Bot.from_oauth( username="elisa", password="123tr", client_id="application_client_id", server="video.example.com", dispatcher=dp, ) ``` Requirements: - TrueConf Server 5.5.3 or later; - an OAuth application created on the server; - at least one scope configured for the application. The `version:read` scope is sufficient and does not expose sensitive information. A token cannot be obtained for an application without a scope. `Bot.from_oauth()` accepts the same parameters as `from_credentials()` and additionally requires `client_id`. See the `Bot.from_oauth()` reference. ### Authentication errors⚓︎ | Exception | When it occurs | What to do | | --- | --- | --- | | `PasswordAuthDisabledError` | The server rejects the token request with `403 auth_method_disabled` because login and password authentication is disabled | Use `Bot.from_oauth()` | | `OAuthMissingScopeError` | The server rejects the OAuth token request with `400 invalidScope` because the OAuth application has no configured scope | Add a scope, such as `version:read`, to the application settings on the server | Both exceptions inherit from `TrueConfChatBotError` and can be imported from `trueconf.exceptions`. For details, see the exceptions reference. October 1, 2026 October 1, 2026 --- # DOCUMENT: Handling Requests ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/parse-messages.md # Handling Requests⚓︎ ## Router⚓︎ Whenever a user interacts with the bot — for example, via a direct message, or when the bot is added to a group chat or channel — the bot receives an update from the server. To process these events, the `Router` is used. It defines which functions should be triggered upon receiving a specific type of update. This allows you to centrally manage the logic for handling various types of messages: UnnamedNamed ``` from trueconf import Router r = Router() ``` ``` from trueconf import Router r = Router(name="Router1") ``` To handle updates, the handler function is wrapped with a decorator. For example, to process the `SendMessage` event, use the `@.message()` decorator: ``` @r.message() async def on_message(message): ... ``` `@r.message()` receives user messages only. To receive system Envelopes, enable `receive_system_messages` when creating the bot and register a separate handler: ``` from trueconf import Bot, F from trueconf.enums import MessageType from trueconf.types import SystemMessage bot = Bot( server="video.example.net", token="JWT-token", receive_system_messages=True, ) @r.system_message(F.type == MessageType.CLEAR_CHAT_HISTORY) async def on_history_cleared(message: SystemMessage): print(message.content.for_all) ``` System Envelopes may be present in `get_chat_history()` results regardless of the `receive_system_messages` setting. ### Replied-to message⚓︎ When an incoming message is a reply, its `reply_message` field contains the directly referenced `Message` object: ``` @r.message() async def on_message(message): if message.reply_message is not None: print(message.reply_message.text) ``` The server expands only one level of the reply chain. If the referenced message is itself a reply, its `reply_message_id` is populated while its `reply_message` remains `None`. Load the next level explicitly when needed: ``` quoted = message.reply_message if quoted is not None and quoted.reply_message_id is not None: previous = await bot.get_message_by_id(quoted.reply_message_id) ``` ### Filter support⚓︎ Routers support filters based on the magic-filter library using the `F` object: ``` from trueconf import F ``` Filters allow you to handle only those events (incoming updates) that match specific conditions. For example: Text messageImageMessage from a specific user ``` from trueconf import Router, F r = Router() @r.message(F.text) async def on_message(message): ... ``` ``` from trueconf import Router, F r = Router() @r.message(F.photo) async def on_photo(message): ... ``` ``` from trueconf import Router, F r = Router() @r.message(F.from_user.id == "elisa") async def on_elisa(message): ... ``` Tip You can find more detailed examples of filter usage in the Filter section. ## Registering routers in the dispatcher⚓︎ All created routers must be registered with the main event handler — the `Dispatcher`. It is responsible for объединяет the handlers and manages routing for incoming updates: ``` from trueconf import Dispatcher dp = Dispatcher() dp.include_router(r) ``` As a rule, you may have many routers, but only one dispatcher: ``` from trueconf import Bot, Router, Dispatcher r1 = Router() r2 = Router() r3 = Router() r4 = Router() dp = Dispatcher() dp.include_router(r1) dp.include_router(r2) dp.include_router(r3) dp.include_router(r4) bot = Bot(token="JWT-token", dispatcher=dp) ``` ### Dynamic routers⚓︎ We have looked at an example of creating a simple router that is defined in code in advance: ``` from trueconf import Router, F r = Router() @r.message(F.from_user.id == "elisa") async def on_elisa(message): ... ``` But what if you need to handle an event whose condition is not known beforehand? This is where dynamic router registration (or dynamic routers) comes in. As you have already seen, registering a handler is done via a decorator (`@`). Note A decorator is a wrapper function that binds your code to a specific event. It “wraps” the handler function and registers it in the system so that when the event (trigger) occurs, the system knows exactly which code to run. To register a router dynamically, use a functional decorator call — i.e., apply it without the `@decorator` syntax sugar. ``` async def handle_message() ... @r.message(Command("start")) async def on_report(msg: Message): dynamic_r = Router() dp.include_router(dynamic_r) dynamic_r.message(F.from_user.id == msg.from_user.id)(handle_message) ``` Example You can find a detailed example using a dynamic router in our GitHub. ### Removing a router from the dispatcher⚓︎ Removing (deactivating) a router is typically needed when a dynamic router was created for a user and is no longer required. The dispatcher keeps a list of all registered routers in `dp.routers`. Accordingly, if you assigned a name like `Router(name="Cool")`, you can remove it as follows: ``` for router in dp.routers[:]: # (1)! if router.name == "Cool": dp.routers.remove(router) ``` - We iterate over a slice (a copy) of the list so the for loop does not break when an element is removed. ### Parallel and child routers⚓︎ Routers can also be: - independent roots, which receive the same event sequentially regardless of each other's result; - child routers, which form an ordered tree of fallback routes. Take a look at the diagram. When a new event arrives from the server, the dispatcher will process it as follows: - Send it for handling to Router 1. - Check the condition of the first handler, Handler 1. If it matches, proceed to Router 2. If it does not, check the next handler, Handler 2. - Regardless of whether any handlers in Router 1 matched, the dispatcher proceeds to execute Router 2. In Router 2, as shown, there are two child routers: Router 2.3 is a descendant of Router 2.2, and Router 2.2 is a descendant of Router 2. Here, the event will be processed as follows: - If nothing matches in Router 2, then move on to Router 2.2. - If nothing matches in Router 2.2, then move on to Router 2.3. As a result, Handler 2 from Router 2.3 will run only if no previous handler matched. If a parent has multiple child routers, they are checked in registration order. Once a child or one of its descendants handles the event, the remaining sibling branches are not checked. By default, children are not visited after their parent handles the event; `Router(allow_child_on_event=True)` enables that propagation. ## Handler priorities⚓︎ - Independent root routers run in the order they were added via `Dispatcher.include_router()`, and every root receives the event. - Child routers are checked in `Router.include_router()` order until the first tree handles the event. - Inside a single router, handlers are evaluated in the order they are declared. - Upon the first filter match, the handler is executed and no further handlers are checked (default behavior). This means that if you have multiple handlers with the same filter: ``` @r.message(F.text == "Hello") async def handler1(message): await message.answer("First") @r.message(F.text == "Hello") async def handler2(message): await message.answer("Second") ``` Then only `handler1` will be triggered, and `handler2` will be ignored. To trigger both handlers, use different filters or combine the logic inside a single handler function. Tip For better logic separation, it's recommended to create multiple routers (e.g., `commands_router`, `messages_router`, `admin_router`) and include them in the dispatcher in the desired order. This helps organize your code and simplifies bot maintenance. ## Code Organization Best Practices⚓︎ - Typically, routers are placed in separate modules (e.g., `handlers/messages.py`) and included in the main bot module via `include_router`. - This helps separate handlers by responsibility: messages, photos, commands, etc. - The dispatcher (`Dispatcher`) can be viewed as the central managing component that coordinates the logic for handling all incoming events. October 1, 2026 September 3, 2025 --- # DOCUMENT: Filters ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/filters.md # Filters⚓︎ Filters are necessary for routing incoming events (updates) to the correct handlers. The search for a handler always stops at the first match with a set of filters. By default, all handlers have an empty set of filters, so all updates will be passed to the first handler with an empty set of filters. In the current implementation, two main approaches for filtering text messages are available: - Command — a filter for processing commands in the format /command [arguments]. - MagicFilter is a universal declarative filter (from the magic-filter library) for event field validation. These two approaches are often used together: Command checks the command format and extracts arguments, while MagicFilter imposes additional conditions on arguments or other message fields. Tip Below you can find examples of using filters, but if that's not enough, check out examples in the repository. ## Command⚓︎ Command — a convenient filter for parsing and processing commands in message text. ``` Command(*commands: str | Pattern[str], prefix: str = "/", ignore_case: bool = False, magic: MagicFilter | None = None) ``` Capabilities - Accept one or more commands: `Command("start")`, `Command("info", "about")`. - Support regular expression patterns: `Command(re.compile(r"echo_\d+"))`. - Support different prefixes (default is `/`), for example `prefix="!/"` — then `!cmd` and `/cmd` will be valid. - Ignore case for string commands (`ignore_case=True`). - Accept optional `magic` — MagicFilter, which additionally validates the `CommandObject` (see below). The Command filter operates as follows: - Checks that the message is a `Message` and that it is of type `PLAIN_MESSAGE`. - Checks if the text begins with the specified prefix (default is `/`). - Splits the string into a command and arguments (if any). - Compares the command with the specified ones (including support for `re.Pattern`). - If `magic` is passed, `MagicFilter` is applied to the `CommandObject`. - If the `magic` filter is triggered, it returns a dictionary `{"command": command_obj}`. ### CommandObject⚓︎ If the filter is triggered, the handler can receive a CommandObject (passed as the `command` parameter): ``` @dataclass(frozen=True) class CommandObject: prefix: str command: str args: str | None regexp_match: Match[str] | None = None magic_result: Any | None = None ``` Fields - `prefix` — the prefix character (`/`, `!`, etc.). - `command` — the command name without the prefix. - `args` — the argument string (everything after the space). - `regexp_match` — the result of `re.Match` if the command was specified as a regular expression. - `magic_result` — optional data returned by `magic` (if applicable). ### Examples⚓︎ Basic handler: ``` @r.message(Command("ping")) async def handle_ping(message: Message): await bot.send_message(chat_id=message.chat_id, text="pong") ``` Multiple commands: ``` @r.message(Command("info", "about", "whoami")) async def handle_info(message: Message, command: CommandObject): await bot.send_message(chat_id=message.chat_id, text=f"Used /{command.command}") ``` Command with prefix: ``` @r.message(Command(re.compile(r"echo_\d+"))) async def handle_echo_numbered(message: Message, command: CommandObject): await bot.send_message(chat_id=message.chat_id, text=f"Echo: {command.command} {command.args or ''}") ``` ## MagicFilter⚓︎ MagicFilter is a declarative, chainable filter from the magic-filter package. It allows you to express checks on event fields using chains and operators. Instead of manually checking update fields within the handler, conditions can be set directly in the decorator. The filter works "lazily": when a handler is declared, only the chain of checks is stored, not the result. The actual evaluation happens only when a new event arrives, so filters can be easily combined and remain readable. This approach makes the code shorter and clearer, showing exactly which updates will be processed by a given handler. The idea behind MagicFilter is simple: describe an attribute chain and a condition, then apply it to an object. Imagine you have an object with nested fields. Instead of manually checking something like `if obj.foo.bar.baz == "spam": ...`, you can construct the filter declaratively: ``` F.foo.bar.baz == "spam" ``` The resulting filter is not an immediate check, but an object that "remembers" the condition. When processing an update, this filter is automatically applied to the object (the router handles the check under the hood). Technically, the `.resolve(obj)` method is used for this, but you don't need to call it manually — just define the condition in the decorator, and it will be executed during routing. ``` @r.message(F.text == "ping") async def ping_handler(message): await message.answer("pong") ``` Here, the filter `F.text == "ping"` will be automatically checked for each incoming message. If the condition matches, the handler will be triggered. ### Examples⚓︎ The MagicFilter object supports basic logical operations on object attributes. Existence Check: ``` F.photo # lambda message: message.photo ``` Equality: ``` F.text == "hello" # lambda message: message.text == "hello" F.from_user.id == 42 # lambda message: message.from_user.id == 42 F.text != "spam" # lambda message: message.text != "spam" ``` Set membership: ``` # lambda query: query.from_user.id in {42, 1000, 123123} F.from_user.id.in_({42, 1000, 123123}) # lambda query: query.data in {"foo", "bar", "baz"} F.data.in_({"foo", "bar", "baz"}) ``` Contains: ``` F.text.contains("foo") # lambda message: "foo" in message.text ``` Starts/ends with the string: ``` F.text.startswith("foo") # lambda message: message.text.startswith("foo") F.text.endswith("bar") # lambda message: message.text.endswith("bar") ``` Regular Expressions: ``` F.text.regexp(r"Hello, .+") # lambda message: re.match(r"Hello, .+", message.text) ``` Custom Function: ``` # lambda message: (lambda chat: chat.id == -42)(message.chat) F.chat.func(lambda chat: chat.id == -42) ``` Inversion of result: ``` ~F.text # not message.text ~F.text.startswith("spam") # not message.text.startswith("spam") ``` Combining conditions: ``` (F.from_user.id == 42) & (F.text == "admin") F.text.startswith("a") | F.text.endswith("b") (F.from_user.id.in_({42, 777, 911})) & (F.text.startswith("!") | F.text.startswith("/")) & F.text.contains("ban") ``` Attribute Modifiers (Strings): ``` F.text.lower() == "test" # message.text.lower() == "test" F.text.upper().in_({"FOO", "BAR"}) # message.text.upper() in {"FOO", "BAR"} F.text.len() == 5 # len(message.text) == 5 ``` ## Building Custom Filters⚓︎ You can build custom filters to fine-tune your event-handling logic. This allows you to move condition checks—such as verifying whether a user exists in the database or checking access permissions—into a separate, reusable component. Implementation requirements: - Class-based structure: A custom filter must be implemented as a class. This makes it possible to preserve state, such as filter settings, when the filter is initialized. - `__call__` method: The class must implement a `__call__` method. Without it, the class instance will not be considered callable, and the filter will not work. - Return value: The `__call__` method must return `True` if the event matches the filter conditions, or `False` if the event should be ignored by the handler. ``` from typing import Any class MyFilter: """ This filter checks whether a user belongs to the specified group via the server API. """ def __init__(self, target_group: str): # Store the required group when creating the instance self.target_group = target_group async def __call__(self, event: Any) -> bool: user = getattr(event, "from_user", None) if not user: return False user_id = user.id # Perform the check, for example via an API call user_info: dict = await server_api.get_user(user_id) groups = user_info.get("groups", []) # Make sure to return True or False return any(group.get("id") == self.target_group for group in groups) ``` Once the filter class is defined, you can use it in handler decorators exactly the same way as the built-in Command or F filters. When registering a handler, simply pass an instance of your class as an argument. ``` from aiogram import Router, Message # Import your filter class from my_filters import MyFilter router = Router() # Attach the filter in the same way as Command or F @router.message(MyFilter(target_group="0032")) async def my_handler(message: Message): await message.answer("Access granted: you belong to the required group!") ``` When a message is received, the bot will use the class instance, call its `__call__` method, and, if it returns `True`, execute the handler code. ## Combining Filters⚓︎ In python-trueconf-bot, you can combine multiple filters within a single handler. By default, when filters are separated by commas, they use AND logic—the handler will run only if all filters return `True`. Command and a custom filter You can restrict access to a specific command by using your own filter. The handler will run only if the message is the specified command and your filter returns `True`. ``` # Triggers if the /admin command is received # AND the user belongs to group "0032" @r.message(Command("admin"), InGroupFilter(target_group="0032")) async def admin_panel(message: Message): await message.answer("Welcome to the admin panel!") ``` MagicFilter (F) and a custom filter Combine message-content checks with your own access rules. For example, you can react to a specific word in the text only for users from certain groups: ``` # Triggers if the text contains "help" # AND the user belongs to the "support" group @r.message(F.text.contains("help"), InGroupFilter(target_group="0003")) async def support_handler(message: Message): await message.answer("The support team has been notified of your request.") ``` ### Combining Command Arguments and MagicFilter⚓︎ Combining Command and MagicFilter is a common and recommended practice: Command parses the command and creates a CommandObject, while `magic` allows you to impose additional conditions on `args` or other parts of the CommandObject. Filter the /echo command only if arguments are present: ``` @r.message(Command("echo", magic=F.args.is_not(None))) async def handle_echo(message: Message, command: CommandObject): await bot.send_message(chat_id=message.chat_id, text=command.args) ``` Additional argument length check: ``` @r.message(Command("upper", magic=F.args.len() > 3)) async def handle_upper(message: Message, command: CommandObject): await bot.send_message(chat_id=message.chat_id, text=(command.args or "").upper()) ``` Check with func — single word: ``` @r.message(Command("repeat", magic=F.args.func(lambda x: isinstance(x, str) and len(x.split()) == 1))) async def handle_repeat(message: Message, command: CommandObject): await bot.send_message(chat_id=message.chat_id, text=f"{command.args} {command.args}") ``` Combining regexp and magic: ``` @r.message(Command(re.compile(r"echo_\\d+"), magic=F.args)) async def handle_special_echo(message: Message, command: CommandObject): await bot.send_message(chat_id=message.chat_id, text=f"Special: {command.command} -> {command.args}") ``` October 1, 2026 September 3, 2025 --- # DOCUMENT: Middleware ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/middleware.md # Middleware⚓︎ Middleware is a layer that intercepts events before they reach a handler. Middleware can log, filter, modify data, or completely block events. ## Why middleware is needed⚓︎ - Logging — record every incoming event - Access control — block events from specific users - Data modification — add additional information to the event context - Anti-flood — limit request frequency ## Two types of middleware⚓︎ In python-trueconf-bot, there are two types of middleware that run at different stages of event processing: ### Outer middleware⚓︎ Runs before filters are checked. It allows you to block an event before it reaches any handler. ``` router.outer_middleware(my_middleware) ``` ### Inner middleware⚓︎ Runs after filters match, but before the handler itself is called. It is useful for checks that are needed only for specific handlers. ``` router.inner_middleware(my_middleware) ``` ## Execution order⚓︎ ``` Incoming event → Outer middleware (Dispatcher) → Outer middleware (Router) → Filter checks → Inner middleware (Router) → Handler ``` Outer middleware runs before filters. If an outer middleware does not call `await handler(event, data)`, the event will be completely blocked — neither filters nor handlers will run. ## Creating custom middleware⚓︎ Any middleware is a class with a `__call__` method that inherits from `BaseMiddleware`: ``` from trueconf.middleware import BaseMiddleware class MyMiddleware(BaseMiddleware): async def __call__(self, handler, event, data): # Code BEFORE the handler print(f"Event received: {event}") await handler(event, data) # ← pass control further down the chain # Code AFTER the handler print(f"Processing completed") ``` Important - If you do not call `await handler(event, data)`, the event will be blocked - Code before `await handler(...)` runs before the handler - Code after `await handler(...)` runs after the handler ### Example: logging all events⚓︎ ``` import logging from trueconf.middleware import BaseMiddleware logger = logging.getLogger("bot") class LoggingMiddleware(BaseMiddleware): async def __call__(self, handler, event, data): logger.info(f"Incoming event: {type(event).__name__}") await handler(event, data) logger.info(f"Event processed") router.outer_middleware(LoggingMiddleware()) ``` ### Example: access control⚓︎ ``` from trueconf.middleware import BaseMiddleware from trueconf.types import Message ALLOWED_USERS = {"admin_user", "moderator_user"} class AccessMiddleware(BaseMiddleware): async def __call__(self, handler, event, data): # Check only messages if not isinstance(event, Message): await handler(event, data) return if event.author.id not in ALLOWED_USERS: # Do not call handler — the event is blocked return await handler(event, data) router.outer_middleware(AccessMiddleware()) ``` ### Example: anti-flood⚓︎ ``` import time from trueconf.middleware import BaseMiddleware from trueconf.types import Message class AntiFloodMiddleware(BaseMiddleware): def __init__(self, limit: float = 1.0): self.limit = limit self.last_message: dict[str, float] = {} async def __call__(self, handler, event, data): if not isinstance(event, Message): await handler(event, data) return user_id = event.author.id now = time.monotonic() if user_id in self.last_message: elapsed = now - self.last_message[user_id] if elapsed before middleware from child routers. ### Middleware inheritance⚓︎ In a nested router structure, middleware is inherited from a parent router by child routers: ``` parent = Router() parent.outer_middleware(LoggingMiddleware()) child = Router() parent.include_router(child) ``` In this case, `child` inherits `LoggingMiddleware` from `parent`. Execution chain: ``` LoggingMiddleware (parent) → middleware (child) → filters → handler ``` Dispatcher is a special case `Dispatcher` inherits from `Router`, but its middleware is not inherited by child routers via `include_router()`. The dispatcher applies its middleware separately before passing the event to child routers. ## Differences between middleware and filters⚓︎ Middleware and filters solve different problems. Here are the key differences: | | Filters | Middleware | | --- | --- | --- | | Purpose | Routing — direct an event to the appropriate handler | Global processing — logging, blocking, data modification | | Scope | One specific handler | All events at once | | If it does not match | Router looks for the next handler | The event is fully blocked — no handler receives it | | Where it lives | In the handler decorator | Registered separately on Router/Dispatcher | ### Example: blocking with a filter vs blocking with middleware⚓︎ Filter — the event simply does not reach this handler, but it may reach another one: ``` # If the text is not "ping", this handler will not run, # but Router will check the next handlers @router.message(F.text == "ping") async def ping(msg: Message): await msg.answer("pong") # This handler will run for ALL other messages @router.message(F.text) async def echo(msg: Message): await msg.answer(msg.text) ``` Middleware — the event is blocked completely; no handler receives it: ``` class BanMiddleware(BaseMiddleware): async def __call__(self, handler, event, data): if isinstance(event, Message) and event.author.id == "spammer": return # ← do not call handler — the event dies here await handler(event, data) router.outer_middleware(BanMiddleware()) ``` ### When to use which⚓︎ Use filters when you need to: - Route the `/start` command to one handler and text messages to another - Check a specific message field, such as type, content, or author - Respond only to certain events Use middleware when you need to: - Block a user or event before filters are checked - Log all incoming events - Limit request frequency (anti-flood) - Add shared data to the context, such as user information from a database - Check access to all handlers at once October 1, 2026 June 11, 2026 --- # DOCUMENT: FSM — Finite State Machine ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/fsm.md # FSM — Finite State Machine⚓︎ ## What it is⚓︎ FSM (Finite State Machine) is a mechanism that allows a bot to “remember” which step of a conversation a user is currently on and respond to messages according to that step. Imagine a multi-step form: - The bot asks for a name → the user enters a name - The bot asks for an age → the user enters an age - The bot asks for a city → the user enters a city - The bot displays a summary Without FSM, the bot does not understand which answer it is expecting at the moment. If the user enters “25”, the bot cannot determine whether it is an age or something else. FSM solves this problem: the bot knows that at the `age` step, any message from the user should be treated as the age. ## Why you need it⚓︎ FSM is useful wherever you need a step-by-step dialog: - Questionnaires and forms — registration, surveys, data collection - Setup wizards — step-by-step parameter configuration - Support workflows — request → issue description → file attachment → confirmation - Section-based menus — navigation using commands or text ## Core concepts⚓︎ | Concept | What it is | Example | | --- | --- | --- | | State | A single specific state (step) | `name`, `age`, `confirm` | | StatesGroup | A group of related states | `Form` with the `name`, `age`, and `confirm` states | | FSMContext | An object for reading and writing state and data | `await state.get_state()`, `await state.set_state(...)` | | StateFilter | A filter that allows a handler to run only in the required state | `@router.message(StateFilter(Form.name))` | | Storage | State storage (in memory) | `MemoryStorage()` | ## Quick start⚓︎ ### Step 1. Imports⚓︎ ``` from trueconf import Bot, Dispatcher, Router, F from trueconf.types import Message from trueconf.filters import Command from trueconf.fsm import FSMContext, State, StatesGroup, StateFilter from trueconf.fsm.storage.memory import MemoryStorage ``` ### Step 2. Creating storage and a dispatcher⚓︎ ``` storage = MemoryStorage() dp = Dispatcher(storage=storage) router = Router() dp.include_router(router) ``` Info `MemoryStorage` stores states in RAM. After the bot restarts, all states are reset. This is enough for development and testing. For production, you can implement your own persistent storage. ### Step 3. Declaring states⚓︎ Create a class that inherits from `StatesGroup` and declare states in it as attributes: ``` from trueconf.fsm import State, StatesGroup class Form(StatesGroup): name = State() # "Form:name" age = State() # "Form:age" city = State() # "Form:city" ``` Each state automatically receives a string identifier in the `GroupName:StateName` format. You do not define it manually — it is generated from the class name and the attribute name. ### Step 4. Handlers⚓︎ ``` @router.message(Command("start")) async def cmd_start(msg: Message, state: FSMContext): await state.set_state(Form.name) await msg.answer("What is your name?") @router.message(Form.name) async def process_name(msg: Message, state: FSMContext): await state.update_data(name=msg.text) await state.set_state(Form.age) await msg.answer("How old are you?") @router.message(Form.age) async def process_age(msg: Message, state: FSMContext): await state.update_data(age=msg.text) data = await state.get_data() await state.clear() await msg.answer(f"Nice to meet you, {data['name']}!\nYou are {data['age']} years old.") @router.message(Command("cancel")) async def cmd_cancel(msg: Message, state: FSMContext): await state.clear() await msg.answer("Cancelled.") ``` ### Step 5. Running the bot⚓︎ ``` bot = Bot.from_credentials( server="your-server", username="your-bot", password="your-password", dispatcher=dp, ) async def main(): await bot.run() import asyncio if __name__ == "__main__": asyncio.run(main()) ``` Tip Note that `state: FSMContext` is passed to the handler automatically as a parameter. You do not need to create it manually — the library injects the required object for you. ## Declaring states⚓︎ Rules - The class must inherit from `StatesGroup`. - Each state is a class attribute created with `State()`. - State names are generated automatically from the group name and the attribute name. - Do not use the same `State()` object in different groups — each `State` is bound to one group. ``` from trueconf.fsm import State, StatesGroup class OrderForm(StatesGroup): product = State() # "OrderForm:product" quantity = State() # "OrderForm:quantity" address = State() # "OrderForm:address" confirm = State() # "OrderForm:confirm" ``` ### Multiple groups⚓︎ You can create multiple state groups for different bot scenarios: - for questionnaires; - for support requests; - for placing an order in a warehouse system or 1C. This prevents states from different dialogs from being mixed together and keeps the code easier to understand and extend. ``` from trueconf.fsm import State, StatesGroup class FeedbackForm(StatesGroup): rating = State() comment = State() class SupportTicket(StatesGroup): topic = State() description = State() priority = State() ``` ### Nested groups⚓︎ Groups can be nested inside one another. This is useful for complex multi-step forms where one scenario contains separate logical blocks. For example, during registration, you can move the address into a separate nested group so that the `city`, `street`, and `zip_code` states are associated specifically with the address and are not mixed with the main form steps. ``` from trueconf.fsm import State, StatesGroup class Registration(StatesGroup): name = State() # "Registration:name" age = State() # "Registration:age" class Address(StatesGroup): # nested group city = State() # "Registration.Address:city" street = State() # "Registration.Address:street" zip_code = State() # "Registration.Address:zip_code" confirm = State() # "Registration:confirm" ``` Tip Nested state identifiers are generated using a dot: `Registration.Address:city`. ## Working with states⚓︎ When working with a form, it is important to check which state the user is currently in. The examples below show how to work with the state machine: Set stateGet stateClear state ``` await state.set_state(Form.name) ``` All subsequent messages from this user will be handled by handlers bound to `Form.name`. ``` current = await state.get_state() ``` `"Form:name"` or `None` if there is no active state. ``` await state.clear() ``` Clears the current state and all saved data. After calling `clear()`, the user is considered to have “no state” — handlers with `StateFilter` will no longer match them. Difference between clear and set_state(None) - `await state.clear()` clears the state and deletes all data - `await state.set_state(None)` clears the state, but keeps the data Use `clear()` when the dialog is fully completed and the data is no longer needed. ## Storing and reading data⚓︎ In addition to the state — that is, the step the user is currently on — FSM allows you to store arbitrary data. For example, a name, age, selected menu item, or any other values the user entered during the dialog. Save dataGet all dataGet one valueUpdate all data ``` await state.update_data(name="Ivan", age=25) ``` `update_data()` adds new data to the data that has already been saved. If a key already exists, its value will be updated. You can also pass data as a dictionary: ``` await state.update_data({"name": "Ivan", "age": 25}) ``` Or combine both approaches: ``` await state.update_data({"name": "Ivan"}, age=25) ``` Note `update_data()` merges new data with the existing data. To replace all data completely, use `set_data()`. ``` data = await state.get_data() ``` The method returns a dictionary with all saved data: ``` {"name": "Ivan", "age": 25} ``` ``` name = await state.get_value("name") # "Ivan" ``` You can specify a default value that will be returned if the key does not exist: ``` name = await state.get_value("name", "Not specified") ``` We also recommend retrieving a value this way when you only need one field and do not want to load the entire dictionary. ``` await state.set_data({"name": "Peter"}) ``` Completely replaces all saved data with a new dictionary. Previous data will be deleted. ## Filtering by state⚓︎ To make a handler run only at a specific step of the dialog, use `StateFilter`. It compares the user's current state with the specified state and lets the event pass only if they match. ``` from trueconf.fsm import StateFilter @router.message(StateFilter(Form.name)) async def process_name(msg: Message, state: FSMContext): ... ``` For convenience, we made it possible to pass a `State` object directly to the decorator. The library automatically treats it as a `StateFilter`, so the following options are equivalent: ``` @router.message(StateFilter(Form.name)) async def process_name(msg: Message, state: FSMContext): ... @router.message(Form.name) async def process_name(msg: Message, state: FSMContext): ... ``` If the same handler should work in several states at once, pass them separated by commas. The handler will be called if the current state matches at least one of them: ``` @router.message(Form.name, Form.age) async def process_name_or_age(msg: Message, state: FSMContext): ... ``` For users without an active dialog, use `StateFilter(None)`. This handler will run only if the state has not been set yet or has already been cleared: ``` from trueconf.fsm import StateFilter @router.message(StateFilter(None)) async def no_active_state(msg: Message, state: FSMContext): await msg.answer("You do not have an active dialog. Enter /start.") ``` If you need to handle a message regardless of the current state, use `any_state`: ``` from trueconf.fsm import any_state @router.message(any_state) async def catch_all(msg: Message, state: FSMContext): await msg.answer("I do not understand. Enter /cancel to cancel.") ``` ### Commands inside states⚓︎ You can combine `StateFilter` with `Command` — the handler will run only if the user is in the required state AND has sent the specified command: ``` # /skip works ONLY in the Form.name state @router.message(Form.name, Command("skip")) async def skip_name(msg: Message, state: FSMContext): await state.update_data(name="Anonymous") await state.set_state(Form.age) await msg.answer("Name skipped. How old are you?") ``` You can also use multiple commands in the same state: ``` @router.message(Form.confirm, Command("yes")) async def confirm_yes(msg: Message, state: FSMContext): data = await state.get_data() await state.clear() await msg.answer(f"Done, {data['name']}!") @router.message(Form.confirm, Command("no")) async def confirm_no(msg: Message, state: FSMContext): await state.clear() await msg.answer("Cancelled.") ``` Handler order matters! Router checks handlers in registration order and stops at the first match. If you have a handler with `Command("cancel")` and a handler with `Form.name`, register commands first, otherwise `/cancel` will be handled by the state handler and will not work as cancellation: ``` # Correct: @router.message(Command("cancel")) async def cmd_cancel(msg: Message, state: FSMContext): await state.clear() await msg.answer("Cancelled.") @router.message(Form.name) async def process_name(msg: Message, state: FSMContext): ... ``` ## Input validation⚓︎ If the user enters invalid data, do not call `set_state()`. The user will remain in the current state and will be able to try again: ``` @router.message(Form.age) async def process_age(msg: Message, state: FSMContext): if not msg.text.isdigit(): await msg.answer("Please enter a number. How old are you?") return # ← stay in Form.age await state.update_data(age=int(msg.text)) await state.set_state(Form.city) await msg.answer("Which city do you live in?") ``` ## FSM strategies⚓︎ By default, the state is stored separately for each user in each chat. This works for most bots. However, in some cases, you may need different behavior. ### FSMStrategy⚓︎ ``` from trueconf.fsm import FSMStrategy dp = Dispatcher(storage=MemoryStorage(), strategy=FSMStrategy.CHAT) ``` | Strategy | Behavior | When to use | | --- | --- | --- | | `USER_IN_CHAT` | Each user in each chat has a separate state | Default. Private messages, questionnaires | | `CHAT` | The entire chat has one state shared by all users | Polls, collaborative games | | `GLOBAL_USER` | A user has one state across all chats | Global user settings | ## Creating custom storage⚓︎ `MemoryStorage` is suitable for development, but data is lost after a restart. For production, you can implement your own storage. Tip If you need to store data in a storage backend so it survives bot restarts, implement the abstract `BaseStorage` class: ``` from trueconf.fsm.storage.base import BaseStorage from trueconf.fsm.key_builder import StorageKey class MyCustomStorage(BaseStorage): async def get_state(self, key: StorageKey) -> str | None: ... async def set_state(self, key: StorageKey, state: str | None) -> None: ... async def get_data(self, key: StorageKey) -> dict: ... async def set_data(self, key: StorageKey, data: dict) -> None: ... async def update_data(self, key: StorageKey, updates: dict) -> dict: ... async def clear(self, key: StorageKey) -> None: ... async def close(self) -> None: ... ``` Connect it just as easily: ``` dp = Dispatcher(storage=MyCustomStorage()) ``` All user code (`state.set_state()`, `state.get_data()`, and so on) works without changes — only the storage implementation changes. October 1, 2026 June 11, 2026 --- # DOCUMENT: Sending messages ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/send_message.md # Sending messages⚓︎ To send a message, the bot must know the `chat_id` of the target chat: a personal chat, group chat, or channel. ## How to get `chat_id`?⚓︎ ### Personal chats (P2P)⚓︎ To get the `chat_id` of a personal chat, use `bot.create_personal_chat(user_id)`. If a personal chat with the user does not exist yet, the server will create it. If the chat already exists, the server will return the existing `chat_id`. ``` chat = await bot.create_personal_chat(user_id="john_doe@video.example.com") await bot.send_message( chat_id=chat.chat_id, text="Hello!", ) ``` ### Group chats and channels⚓︎ Be careful with group chats and channels. Methods that create group chats and channels always create a new chat: ``` chat = await bot.create_group_chat(title="Support") channel = await bot.create_channel(title="News") ``` If you call such a method again with the same title, another chat or channel with the same `title` will be created. Therefore, after creating a group chat or channel, it is better to save its `chat_id` in a database, configuration file, or another persistent storage. What if the chat already exists? How do I get its `chat_id`? ### Finding an existing chat⚓︎ You can get the list of available chats with `bot.get_chats()`: ``` response = await bot.get_chats(count=10, page=1) ``` The method returns `GetChatsResponse` with the `list` parameter containing the list of chats. You can find the required chat, for example by its title, and get its `chat_id`: Using a generatorUsing a loop ``` response = await bot.get_chats(count=100, page=1) chat = next( (chat for chat in response.list if chat.title == "Support"), None, ) if chat is not None: print(chat.chat_id) ``` ``` response = await bot.get_chats(count=100, page=1) chat = None for item in response.list: if item.title == "Support": chat = item break if chat is not None: print(chat.chat_id) ``` After you find the required `chat_id`, it is also recommended to save it so that you do not have to search for the chat again on every application start. ### Getting `chat_id` from an incoming message⚓︎ Another simple way is to send a message to the target chat and handle it with the bot. In the handler, you can print `message.chat_id`: ``` from trueconf import Router from trueconf.types import Message router = Router() @router.message() async def print_chat_id(message: Message): print(message.chat_id) ``` This approach is convenient for group chats and channels: add the bot to the required chat, send a message, and check the `chat_id` in the console. ## Text messages⚓︎ To send a text message, use `bot.send_message(...)`: ``` await bot.send_message( chat_id="chat_id", text="Hello!", ) ``` If you send a message from an incoming message handler, you can use `Message` shortcut methods, such as `message.answer(...)` or `message.reply(...)`. They automatically use `message.chat_id`, so you do not need to pass it manually. For details, see the Shortcuts section. ### Replying to a message⚓︎ If you need to reply to a specific message, pass the source message identifier in the `reply_message_id` parameter: ``` await bot.send_message( chat_id="chat_id", text="This is a reply", reply_message_id="message_id", ) ``` This approach allows you to send regular messages and replies through a single API. ### Forwarding messages⚓︎ To forward an existing message, use `bot.forward_message(...)`: ``` await bot.forward_message( chat_id="target_chat_id", message_id="source_message_id", ) ``` Where: - `chat_id` is the identifier of the chat where the message should be forwarded; - `message_id` is the identifier of the message to forward. ### Text formatting⚓︎ Messages can be sent as plain text, HTML, or Markdown by passing `parse_mode`: ``` from trueconf.enums import ParseMode await bot.send_message( chat_id="chat_id", text="Important", parse_mode=ParseMode.HTML, ) ``` For convenient formatted text construction, the library provides the `trueconf.utils.formatting` module. It lets you build a message from classes instead of writing HTML or Markdown manually: ``` from trueconf.enums import ParseMode from trueconf.utils.formatting import ( Bold, Italic, LineBreak, Link, Mention, Text, ) content = Text( Bold("Important"), " message for ", Mention("John Doe", user_id="john_doe@video.example.com"), LineBreak(), Link("Open website", url="https://trueconf.com"), ) await bot.send_message( chat_id="chat_id", text=content.as_html(), parse_mode=ParseMode.HTML, ) ``` The module supports: - `Bold(...)` - `Italic(...)` - `Underline(...)` - `Strikethrough(...)` - `Link(...)` - `Mention(...)` - `AllMention()` - `LineBreak()` - `Text(...)` ### Message length limits⚓︎ TrueConf Server limits text messages to `4096` characters. If a message exceeds this limit, use the `safe_split_text(...)` helper function. It safely splits long text while preserving HTML/Markdown markup: ``` from trueconf.utils import safe_split_text chunks = safe_split_text(long_text) for chunk in chunks: await bot.send_message( chat_id="chat_id", text=chunk, parse_mode=ParseMode.HTML, ) ``` For more information about limits, see the Restrictions section. Shortcut methods In message handlers, it is often more convenient to use `message.answer(...)`, `message.reply(...)`, and other shortcut methods instead of calling `bot.send_message(...)` directly. For details, see the Shortcuts section. Interactive buttons You can attach inline keyboards to messages and handle button clicks through `CallbackQuery`. For details, see Interactive Buttons. Sending files This section covers text messages. To send documents, images, videos, voice messages, and other attachments, see the Working with files section. October 1, 2026 May 6, 2026 --- # DOCUMENT: Interactive Buttons ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/buttons.md # Interactive Buttons⚓︎ Inline buttons appear below a message and let users interact with a bot without typing: they can choose a command, open a link, send prepared text, or copy data. We will start with one button, then build a menu and handle button clicks. Requirements - TrueConf Server 5.5.6 or later; - TrueConf for Windows, macOS, and Linux 8.6.0 or later; - TrueConf for Android 3.3.0 or later; - TrueConf for iOS 4.2.0 or later. Caution Buttons can only be attached to plain text messages, and only chatbots can send messages with buttons. For a complete description of the button format at the WebSocket API level, see the TrueConf Server API documentation. ## Your First Button⚓︎ Create a button with `InlineKeyboardButton` and a keyboard with `InlineKeyboardMarkup`: ``` from trueconf import InlineKeyboardButton, InlineKeyboardMarkup keyboard = InlineKeyboardMarkup( buttons=[ [InlineKeyboardButton(text="Help", command="menu:help")], ] ) ``` Here, `text` is the button label and `command` is the command the bot receives when the button is clicked. The `buttons` parameter contains a list of rows. This means that even a single button requires two nested lists: the outer list defines the keyboard, and the inner list defines its first row. Pass the keyboard to the `buttons` parameter when sending a message: ``` await bot.send_message( chat_id="chat_id", text="Choose an action:", buttons=keyboard, ) ``` You can also pass a keyboard to `message.answer(...)` and `message.reply(...)`. Tip If several handlers use the same keyboard, create it once at module level and pass it to the methods that need it. ## Button Actions⚓︎ The previous example used a `command` button, which sends a command to the bot. The library supports four actions, and each button must specify exactly one of them: | Parameter | What happens when the button is clicked | | --- | --- | | `command` | The bot receives a `CallbackQuery` event; no message is posted to the chat | | `url` | Opens a link using the `http`, `https`, `mailto`, or `trueconf` scheme | | `message` | Sends the prepared message on behalf of the user | | `copy_data` | Copies the specified data to the clipboard | You can arrange buttons in multiple rows: ``` from trueconf import ButtonStyle, InlineKeyboardButton, InlineKeyboardMarkup keyboard = InlineKeyboardMarkup( buttons=[ [ InlineKeyboardButton( text="Help", command="menu:help", style=ButtonStyle.PRIMARY, ), InlineKeyboardButton( text="Open website", url="https://trueconf.com", ), ], [ InlineKeyboardButton( text="Prepare a question", message="Tell me more", draft=True, ), InlineKeyboardButton( text="Copy code", copy_data="code-42", ), ], ] ) ``` In this example: - `Help` sends the `menu:help` command to the bot; - `Open website` opens a link; - `Prepare a question` places text in the input field because `draft=True`; - `Copy code` copies the `code-42` string. If `draft=True` is omitted from a `message` button, the prepared text is sent to the chat immediately on behalf of the user. Tip The `text` parameter is required for every action except `url`. If a URL button has no label, the client displays the URL itself. Caution Only a `command` button sends an event to the bot. The client application handles `url`, `message`, and `copy_data` buttons, so clicking them does not create a `CallbackQuery`. ## Additional Parameters⚓︎ When the basic action is not enough, use additional parameters to customize the button's behavior and appearance: | Parameter | Available for | Purpose | | --- | --- | --- | | `style` | All buttons | Sets `ButtonStyle.DEFAULT`, `ButtonStyle.PRIMARY`, `ButtonStyle.DANGER`, or `ButtonStyle.SUCCESS` | | `button_id` | All buttons | Sets the button identifier; for a `command` button, it is included in the click event | | `draft` | `message` only | Places text in the input field instead of sending it immediately | | `custom_data` | `command` only | Sends additional data to the bot together with the command | | `to` | `command` only | Directs the command to another bot | For example, `custom_data` can carry the identifier of a selected object separately from the command: ``` button = InlineKeyboardButton( text="Add to cart", command="cart:add", custom_data="product-42", button_id="add-product", ) ``` Warning The `wait_reply=True` parameter and the `CallbackQuery.answer()` method cannot be used yet because TrueConf client applications do not currently support this scenario. The library therefore raises `NotImplementedError` when they are used. ## Handling a Command⚓︎ After the user clicks a `command` button, the bot receives a `CallbackQuery` object. Register a `@router.callback_query()` handler and add a filter for the command value: ``` from trueconf import CallbackQuery, F, Router router = Router() @router.callback_query(F.command == "menu:help") async def show_help(callback: CallbackQuery): await callback.edit_message(text="Help", buttons=help_keyboard) ``` The `F.command == "menu:help"` filter ensures that the handler responds only to the intended button. For a group of related commands, use a common prefix and an `F.command.startswith(...)` filter: ``` @router.callback_query(F.command.startswith("menu:")) async def handle_menu(callback: CallbackQuery): ... ``` The click data is available through the properties of the `CallbackQuery` object: - `callback.command` — the command of the clicked button; - `callback.custom_data` — the data from `custom_data`; - `callback.message` — the message containing the button; - `callback.chat` — the chat in which the button was clicked; - `callback.command_source.button_id` — the `button_id` value, if specified. ## Updating a Menu After a Click⚓︎ Buttons are often used for navigation: the user opens a section, and the bot changes the message text and displays a new set of actions. From a callback handler, use `callback.edit_message(...)`: ``` @router.callback_query(F.command == "menu:catalog") async def show_catalog(callback: CallbackQuery): await callback.edit_message( text="Choose a category:", buttons=catalog_keyboard, ) ``` You can update the text and keyboard independently: ``` # Update only the text and keep the current buttons await callback.edit_message(text="New text") # Update only the buttons and keep the current text await callback.edit_message(buttons=new_keyboard) # Update the text and buttons together await callback.edit_message( text="New text", buttons=new_keyboard, ) # Remove the buttons and keep the current text await callback.edit_message(buttons=None) ``` If the `buttons` parameter is omitted, the current buttons are preserved. To remove them, explicitly pass `buttons=None`. To edit a message outside a `CallbackQuery` handler, use `bot.edit_message(...)`. In this case, you must provide the message text: ``` await bot.edit_message( message_id="message_id", text="Updated text", buttons=new_keyboard, ) ``` ## Getting a Message Keyboard⚓︎ The keyboard of a received text message is available through `TextContent.buttons`: ``` message = await bot.get_message_by_id(message_id) if message.content.buttons is not None: keyboard = message.content.buttons ``` ## Restrictions⚓︎ Observe the following restrictions when creating a keyboard: - no more than 8 rows and 8 buttons per row; - no more than 64 buttons in a keyboard; - `text` must contain 1 to 32 characters when a label is provided; - `command` must contain 1 to 255 ASCII characters; - `custom_data` must contain 1 to 4096 ASCII characters; - `copy_data` must contain 1 to 4095 Unicode characters; - `url` must contain 8 to 8095 ASCII characters; - HTML and Markdown in button labels are not processed, and line breaks are replaced with spaces. ## Complete Example⚓︎ Ready-to-use bots More ready-to-use button scenarios are available in the examples on GitHub. This bot sends a menu in response to the `/menu` command and then handles the `Say hello` button: ``` import asyncio from trueconf import ( Bot, CallbackQuery, Dispatcher, F, InlineKeyboardButton, InlineKeyboardMarkup, Message, Router, ) from trueconf.filters import Command router = Router() dispatcher = Dispatcher() MAIN_MENU = InlineKeyboardMarkup( buttons=[ [ InlineKeyboardButton(text="Say hello", command="menu:hello"), InlineKeyboardButton(text="Open website", url="https://trueconf.com"), ], [InlineKeyboardButton(text="Copy", copy_data="trueconf")], ] ) @router.message(Command("menu")) async def show_menu(message: Message): await message.answer("Choose an action:", buttons=MAIN_MENU) @router.callback_query(F.command == "menu:hello") async def say_hello(callback: CallbackQuery): await callback.edit_message(text="Hello!", buttons=MAIN_MENU) async def main(): dispatcher.include_router(router) bot = Bot.from_credentials( username="echo_bot", password="123tr", server="video.example.com", dispatcher=dispatcher, ) await bot.run() if __name__ == "__main__": asyncio.run(main()) ``` October 1, 2026 October 1, 2026 --- # DOCUMENT: Chat activity indicator ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/typing_indicator.md # Chat activity indicator⚓︎ While the bot processes a request, you can show its status in the chat: for example, that it is typing a message. ## One-shot activity⚓︎ Use `bot.send_chat_activity(...)` to send a single activity event: ``` from trueconf.enums import ChatActivity await bot.send_chat_activity( chat_id="chat_id", activity_type=ChatActivity.TYPING, ) ``` Available activity types are listed in the `ChatActivity` enum: - `ChatActivity.TYPING` — the bot is typing; - `ChatActivity.CHOOSING_STICKER` — the bot is choosing a sticker; - `ChatActivity.UPLOADING_FILE` — the bot is uploading a file. The indicator expires The server shows the indicator only for a short time. For long operations, re-send the activity periodically — use `ChatActivitySender` described below. ## Keeping the indicator visible⚓︎ `ChatActivitySender` is an async context manager that periodically re-sends the activity in the background while the operation runs: ``` from trueconf.utils.chat_activity import ChatActivitySender async with ChatActivitySender.typing(bot=bot, chat_id=chat_id): result = await generate_text_answer() ``` The sender re-sends the activity at the cadence returned by the server: each response carries `retryAfter` in milliseconds, and the sender waits that long before the next send. `ChatActivitySender` also accepts the generic `activity` argument, so you can use any value from the `ChatActivity` enum: ``` from trueconf.enums import ChatActivity async with ChatActivitySender(bot=bot, chat_id=chat_id, activity=ChatActivity.UPLOADING_FILE): await upload_large_file() ``` October 1, 2026 October 1, 2026 --- # DOCUMENT: Shortcuts ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/shortcuts.md # Shortcuts⚓︎ ## Working with the Message Object⚓︎ When handling an incoming message, a `Message` object is typically passed to the handler function: ``` from trueconf import Router from trueconf.types import Message r = Router() @r.message() async def on_message(message: Message): await message.answer("Message received") ``` The `Message` object is injected into the handler automatically and contains the context of the current event: information about the sender, chat, message type, content, message ID, and other parameters. In addition, the message object provides access to the bot instance that is processing the current event: ``` @r.message() async def on_message(message: Message): result = await message.bot.get_something() ``` This is useful when the bot instance is defined in another module or declared later in the code, making it unavailable as a direct variable (`bot`) inside the handler. In such cases, you can access the current bot instance via the message object: `message.bot`. ## Message Shortcuts⚓︎ The `Message` class provides shortcuts — helper methods that allow you to perform common actions without explicitly passing `chat_id`, `message_id`, and other parameters. These values are automatically taken from the current message. Note Currently, shortcuts are implemented only for the `Message` type. Support for other event types may be added in future releases. For example, instead of calling the bot method directly: ``` @r.message() async def on_message(message: Message): await message.bot.send_message(chat_id=message.chat_id, text="Hello!") ``` you can use a shortcut: ``` @r.message() async def on_message(message: Message): await message.answer("Hello!") ``` Shortcuts are especially useful in handlers where actions are tied to the current message or chat. They make the code more concise and reduce repetition. For example, `message.answer(...)` automatically uses the chat where the message was received, while `message.reply(...)` also links the response to the original message. Tip You can find the full list of available shortcuts in the Message class reference. ## Contacts⚓︎ `Message.contact` returns the contact of the current message as a `Contact` object, or `None` if the message is not a contact. The result is cached on the message, so a vCard file is downloaded from the server only once: ``` contact = await message.contact ``` Two contact formats are recognized: - vCard attachment — a `.vcf` file (`mimeType: text/vcard`). The file is downloaded from the server and parsed: the structured `N` field gives the first/last name, `TEL` gives the phone number, and the raw vCard text is available as `Contact.vcard`. - TrueConf contact link — a text message whose entire content is exactly one `[Name](trueconf:login&do=profile)` link. `Contact.user_id` holds the login and `Contact.first_name` holds the display name fetched from the server (falling back to the link text if the user no longer exists). ``` @r.message() async def on_message(message: Message): contact = await message.contact if contact is not None: await message.answer(f"{contact.first_name}: {contact.phone_number}") ``` The display name is never split into first/last name: the server-side name convention (surname-first, given-first, full name) varies per installation, so `Contact.last_name` stays `None` for TrueConf contacts. ## Geolocation⚓︎ `Message.location` returns a `Location` object for a geolocation message, or `None` for other message types: ``` @r.message() async def on_message(message: Message): if message.location is not None: print(location.latitude, location.longitude, location.title) ``` ## Quote⚓︎ `Message.quote` returns the quoted part of a reply, while `Message.text` contains the message text without the quote block. You can pass the quoted fragment to the `quote` parameter of `message.reply(...)` or `bot.send_message(...)`: ``` @r.message() async def on_message(message: Message): if message.quote is not None: await message.reply("Thank you for the quote!", quote=message.quote) ``` ## Voice Messages⚓︎ `Message.voice` returns a `Voice` object for a voice message, or `None` for other message types. It provides the same file shortcuts as other attachments: `download()`, `url`, and `preview_url`: ``` @r.message() async def on_message(message: Message): if message.voice is not None: await voice.download(file_path="voice.ogg") ``` October 1, 2026 May 5, 2026 --- # DOCUMENT: Using enumerations ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/enums.md # Using enumerations⚓︎ In the python-trueconf-bot library, many method parameters and object fields are defined through enums (enumerations). This is done for developer convenience and to avoid errors caused by using "magic strings" or numeric codes. You can import all enums at once: ``` from trueconf.enums import * ``` Or import only the ones you need: ``` from trueconf.enums import ParseMode, FileReadyState ``` ### Usage examples⚓︎ #### Text formatting⚓︎ ``` from trueconf.enums import ParseMode await message.answer("Hello, *world*!", parse_mode=ParseMode.MARKDOWN) ``` Instead of manually typing the string `"Markdown"`, you use `ParseMode.MARKDOWN`. #### Working with files⚓︎ ``` from trueconf.enums import FileReadyState info = await bot.get_file_info(file_id="abc123") if info.ready_state == FileReadyState.READY: await bot.download_file_by_id(info.file_id, file_path=f"./downloads/{info.name}") elif info.ready_state == FileReadyState.NOT_AVAILABLE: print("File is not available") ``` #### Chat types⚓︎ ``` from trueconf.enums import ChatType if chat.chat_type == ChatType.GROUP: await message.answer("This is a group chat") ``` Thus, `enums` help you write cleaner and safer code. October 1, 2026 September 3, 2025 --- # DOCUMENT: Data Types ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/types.md # Data Types⚓︎ When developing applications, it is especially important that the IDE provides hints about available methods and class parameters. However, the router (Router) passes different data types to handlers, and the IDE cannot always correctly determine their type. Therefore, it needs a hint about which specific object is being passed. In python-trueconf-bot, this is handled by the `trueconf.types` package, which describes all incoming server events and requests (notifications). For responses to client requests, a separate module is provided — `trueconf.types.responses`. Thus: - when working with events, use types from `trueconf.types`; - when working with client request results, use types from `trueconf.types.responses`. This ensures: - IDE autocompletion (hints for attributes and methods); - static type checking with mypy or similar tools; - more convenient code and documentation navigation. ## Example Usage⚓︎ ### Participant Added to a Chat⚓︎ Suppose you want to handle an event about adding a new participant to a chat (1): - According to the API, this request has `"method": "addChatParticipant"`. ``` from trueconf import Router r = Router() @r.added_chat_participant() async def on_added_user(event): ... ``` To enable the IDE to provide hints about the available attributes of the `event` object, you need to specify the correct data type: ``` from trueconf import Router from trueconf.types import AddedChatParticipant r = Router() @r.added_chat_participant() async def on_added_user(event: AddedChatParticipant): who_add = event.added_by ``` In this example: - `AddedChatParticipant` describes the structure of the incoming event, - you get convenient IDE autocompletion, - with static type checking tools (e.g., mypy), the correctness of field access is automatically verified. ### “Raw” Event⚓︎ When using the `@.event` decorator, you gain access to all fields of the event object, including those that are usually hidden when converting JSON into a class: ``` { "method": "name", "type": 1, "id": 11, "payload": {} } ``` In this case, it is better to use `trueconf.types.Update`, which describes the structure of the full update received from the server. ``` from trueconf import Router from trueconf.types import Update from trueconf.enums import IncomingUpdateMethod r = Router() @r.event() async def raw_event(event: Update): if event.method == IncomingUpdateMethod.MESSAGE: pass # Alternatively, without importing enum if event.method == "SendMessage": pass ``` October 1, 2026 September 3, 2025 --- # DOCUMENT: Working with Files ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/files.md # Working with Files⚓︎ TrueConf Chatbot Connector does not impose any restrictions on uploading files to the server. However, starting from version TrueConf Server 5.5.2 and above, the administrator can set limits on the maximum file size and allowable formats (extensions). The python-trueconf-bot library offers convenient tools for file handling, both for sending and uploading. To send a file, use one of the InputFile subclasses, depending on the data source. Three built-in classes are available for file transfer: - FSInputFile — uploading a file from the local file system - BufferedInputFile — loading from a byte buffer - URLInputFile — uploading a file from a remote URL All classes are located in the trueconf.types module. You can use these classes in methods: - bot.send_document(...) - bot.send_photo(...) - bot.send_sticker(...) ## How to send a file?⚓︎ ### 🗂️ FSInputFile⚓︎ It is used for uploading files from the local file system. It is recommended to use this when you have a file path. ``` from trueconf.types import FSInputFile await bot.send_document( chat_id="a1b2c3d4", file=FSInputFile("docs/report.pdf"), caption="📄 Annual report for **2025**", parse_mode=ParseMode.MARKDOWN, ) await bot.send_sticker(chat_id="a1b2c3d4", file=FSInputFile("stickers/cat.webp")) ``` ### 🧠 BufferedInputFile⚓︎ Used when the file is already in memory (for example, received from an API, loaded into RAM, or from a database). ``` from trueconf.types import BufferedInputFile image_bytes = open("image.jpg", "rb").read() preview_bytes = open("preview.jpg", "rb").read() await bot.send_photo( chat_id="a1b2c3d4", file=BufferedInputFile(file=image_bytes, filename="image.jpg"), preview=BufferedInputFile(file=preview_bytes, filename="preview.jpg"), caption="This is my photo", ) ``` The convenient method `from_file()` is also available: ``` file = BufferedInputFile.from_file("archive.zip") await bot.send_document(chat_id="...", file=file) ``` ### 🌐 URLInputFile⚓︎ If the file is available online, you can provide a link, and the bot will download it automatically. ``` from trueconf.types import URLInputFile file = URLInputFile( url="https://example.com/image.png", filename="image.png", # optional — it will be determined automatically ) ``` How the size is determined. `await file.prepare()` reads only the HTTP headers (type, name, `Content-Length`) without downloading the body — it is cheap. For dynamic sources (e.g. a camera that returns a new snapshot per request) `Content-Length` is only an estimate: the exact size becomes known after the download, and it is the size declared to the server, so it always matches the uploaded content. - One `URLInputFile` object = one content: repeated sends and `clone()` reuse the downloaded bytes instead of downloading again. Need a fresh snapshot — create a new object. - `await file.read(max_size=...)` aborts the download when the content exceeds the limit (when sending, the `bot.max_file_size` limit is applied automatically). ### Recommendations⚓︎ - MIME type: determined automatically. If the python-magic package is installed, the MIME type will be calculated based on the file's content (bytes), which is significantly more accurate than determining it by extension. Install it with dependencies as follows: ``` pip install python-trueconf-bot[python-magic] ``` - clone(): each file type supports the `.clone()` method, which creates a new copy of the object with a different `id(object)`. ## How to download a file?⚓︎ To easily download incoming media files, such as images (`message.photo`) or documents (`message.document`), the library provides the shortcut method `.download()`. This is syntactic sugar over the `bot.download_file_by_id(...)` method, simplifying the handling of attachments. It is recommended to use `.download()` because it: - automatically retrieves file_id from the object; - uses the current bot instance; - minimizes the amount of code. ``` @router.message(F.document) async def handle_doc(msg: Message): await msg.document.download(file_path="document.pdf") ``` Notes The `file_path` can be either relative or absolute. Parent directories are created automatically. The method `download_file_by_id(...)` is also available for more flexible control: ``` await bot.download_file_by_id(file_id=msg.document.file_id, file_path="document.pdf") ``` The deprecated `dest_path` parameter is treated as a directory and appends the server file name. Use `file_path` for an exact output path. ## MIME Type Detection with python-magic⚓︎ A file’s MIME type can be detected automatically. The library supports two approaches: - By file extension — works without additional dependencies, but may be inaccurate. - By file content (bytes) — significantly more accurate, but requires `python-magic`. ### How It Works⚓︎ The `python-magic` package does not determine MIME types on its own. It is a Python wrapper around the native libmagic library written in C, which is what actually identifies a file type based on its contents. That is why `python-magic` may not work out of the box on some systems: the Python package is installed via `pip`, but the system library `libmagic` must be installed separately. If `libmagic` is missing, importing `magic` may fail with an error such as: - `ImportError: failed to find libmagic. Check your installation` ### Installation⚓︎ Install the system dependencies: - macOS (Homebrew): ``` brew install libmagic ``` - Linux (Debian/Ubuntu): ``` sudo apt install libmagic1 ``` - Windows: ``` pip install python-magic-bin ``` We also recommend reviewing the repository: https://github.com/ahupp/python-magic. ### Notes⚓︎ - When `python-magic` is available, the MIME type is detected from the file bytes, which is usually more accurate than detecting it by filename or extension. October 12, 2026 November 12, 2025 --- # DOCUMENT: Restrictions ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/learn/restrictions.md # Restrictions⚓︎ The library performs pre-validation of certain TrueConf Server limits and raises exceptions before sending a request if a value exceeds the allowed threshold. #### Chat Title⚓︎ The maximum chat title length is `255` characters. If a longer title is provided, a `GroupTitleTooLongError` or `ChannelTitleTooLongError` will be raised. #### Message Length⚓︎ The maximum length of a text message is `4096` visible characters. If this limit is exceeded, a `TextMessageTooLongError` will be raised. If you need to send a long message, for example an LLM-generated response, you can split it into multiple parts using `safe_split_text`: ``` from trueconf.utils import safe_split_text for chunk in safe_split_text(long_text): await bot.send_message( chat_id=chat_id, text=chunk, ) ``` The `safe_split_text(text)` function returns a list of chunks that can be sent sequentially. #### File Restrictions⚓︎ Limits on file size and allowed extensions are configured by the TrueConf Server administrator. The bot retrieves these parameters from the server and updates them when the settings change: ``` bot.max_file_size: int | None bot.file_extension_filter_mode: str | None bot.file_extensions_list: set | None ``` When sending a file, the library checks its size and extension. If the file exceeds the allowed size, a `FileSizeTooLargeError` will be raised. If the file extension is not allowed by server settings, an `InvalidFileExtensionError` will be raised. Note File restrictions depend on the configuration of the specific TrueConf Server. If the administrator changes the maximum file size or the list of allowed extensions, the bot will automatically receive updated values on the next limits update event. #### Inline Buttons⚓︎ The library validates inline keyboard restrictions when an `InlineKeyboardMarkup` object is created: - no more than `8` rows; - no more than `8` buttons per row; - no more than `64` buttons in total; - button text must contain `1` to `32` characters; - a button command can contain up to `255` ASCII characters; - `custom_data` can contain up to `4096` ASCII characters and is available only for `command` buttons. If a limit is exceeded, the library raises `ValueError`. For details, see Interactive Buttons. October 1, 2026 May 5, 2026 --- # DOCUMENT: Class Bot ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Bot.md # Class `Bot`⚓︎ Here is the reference information for the `Bot` class, including all its parameters, attributes, and methods. You can import the `Bot` class directly from the `trueconf` package: ``` from trueconf import Bot ``` ## `` trueconf.Bot ⚓︎ ``` Bot( server, token, *, dispatcher=None, receive_unread_messages=False, receive_system_messages=False, skip_self_messages=True, verify_ssl=True, web_port=None, https=True, ws_max_retries=5, ws_max_delay=60, debug=False, on_health_check=None, timeout=10.0, max_in_memory_download_size=100 * 1024 * 1024, ) ``` Initializes a TrueConf chatbot instance with WebSocket connection and configuration options. ### Source trueconf.com/docs/chatbot-connector/en/connect-and-auth/#auth Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `server` | `str` | Address of the TrueConf server. | required | | `token` | `str` | Bot authorization token. | required | | `*` | | All following arguments must be passed by name (keyword-only). | required | | `dispatcher` | `` trueconf.Dispatcher (`trueconf.dispatcher.dispatcher.Dispatcher`)' href=../Dispatcher/#trueconf.Dispatcher>Dispatcher | None | Dispatcher instance for registering handlers. | `None` | | `receive_unread_messages` | `bool` | Whether to receive unread messages on connection. Defaults to False. | `False` | | `receive_system_messages` | `bool` | Whether to receive system messages, such as user additions to the chat or chat title changes. Defaults to False. | `False` | | `skip_self_messages` | `bool` | If True, the bot will ignore messages sent by itself. This prevents echo loops when multiple bot sessions are running. Defaults to True. | `True` | | `verify_ssl` | `bool | str | SSLContext` | SSL verification mode. If True, verifies the server certificate using the system trust store when available. If False, disables certificate verification. If a string is provided, it must be a path to a CA bundle file. A custom ssl.SSLContext can also be passed. Defaults to True. | `True` | | `web_port` | `int` | WebSocket connection port. Defaults to 443. | `None` | | `https` | `bool` | Whether to use HTTPS protocol. Defaults to True. | `True` | | `ws_max_retries` | `int` | Max connection attempts on network/IP errors before giving up. Defaults to 5. | `5` | | `ws_max_delay` | `int` | Maximum delay between reconnection attempts (in seconds). Defaults to 60. | `60` | | `debug` | `bool` | Enables debug mode. Defaults to False. | `False` | | `on_health_check` | `HealthCheckCallback | None` | Async callback called when the bot connection health changes. The callback receives a dictionary with the current status, WebSocket state, authorization state, server, port, protocol, timestamp, and optional error details. Defaults to None. | `None` | | `timeout` | `float | int` | The maximum time in seconds to wait for network activity. Instead of limiting the total upload duration, it protects against socket freezes during data transmission and waiting for the server's response. Defaults to 10.0. | `10.0` | | `max_in_memory_download_size` | `int` | Maximum file size in bytes that can be returned in memory. Defaults to 100 MiB. This limit does not apply when `dest_path` is provided. | `100 * 1024 * 1024` | ### Note Alternatively, you can authorize using a username and password via the `from_credentials()` class method. ### `` authorized_event `instance-attribute` ⚓︎ ``` authorized_event = asyncio.Event() ``` ### `` connected_event `instance-attribute` ⚓︎ ``` connected_event = asyncio.Event() ``` ### `` debug `instance-attribute` ⚓︎ ``` debug = debug ``` ### `` dp `instance-attribute` ⚓︎ ``` dp = dispatcher or trueconf.Dispatcher (trueconf.dispatcher.dispatcher.Dispatcher)' href=../Dispatcher/#trueconf.Dispatcher>Dispatcher() ``` ### `` file_extension_filter_mode `instance-attribute` ⚓︎ ``` file_extension_filter_mode = None ``` ### `` file_extensions_list `instance-attribute` ⚓︎ ``` file_extensions_list = None ``` ### `` https `instance-attribute` ⚓︎ ``` https = https ``` ### `` max_file_size `instance-attribute` ⚓︎ ``` max_file_size = None ``` ### `` max_in_memory_download_size `instance-attribute` ⚓︎ ``` max_in_memory_download_size = max_in_memory_download_size ``` ### `` me_id `property` ⚓︎ ``` me_id ``` ### `` port `instance-attribute` ⚓︎ ``` port = 443 if self.https else 4309 ``` ### `` receive_system_messages `instance-attribute` ⚓︎ ``` receive_system_messages = receive_system_messages ``` ### `` receive_unread_messages `instance-attribute` ⚓︎ ``` receive_unread_messages = receive_unread_messages ``` ### `` server `instance-attribute` ⚓︎ ``` server = server ``` ### `` ssl_context `instance-attribute` ⚓︎ ``` ssl_context = _build_ssl_context(verify_ssl) ``` ### `` stopped_event `instance-attribute` ⚓︎ ``` stopped_event = asyncio.Event() ``` ### `` timeout `instance-attribute` ⚓︎ ``` timeout = timeout ``` ### `` token `property` ⚓︎ ``` token ``` Returns the bot's authorization token. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | The access token used for authentication. | ### `` add_participant_to_chat `async` ⚓︎ ``` add_participant_to_chat( chat_id, user_id, display_history=False ) ``` Adds a participant to the specified chat. Optionally allows showing chat history to the newly added participant. The `display_history` parameter is supported only in TrueConf Server version 5.5.2 and above. ### Source trueconf.com/docs/chatbot-connector/en/chats/#addChatParticipant Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to add the participant to. | required | | `user_id` | `str` | Identifier of the user to be added. If no domain is specified, the server domain will be used. | required | | `display_history` | `bool` | Whether to show previous chat history to the participant. Requires TrueConf Server 5.5.2+. Defaults to False. | `False` | Returns: | Name | Type | Description | | --- | --- | --- | | `AddChatParticipantResponse` | `` AddChatParticipantResponse (`trueconf.types.responses.add_chat_participant_response.AddChatParticipantResponse`)' href=../Responses/#trueconf.types.responses.AddChatParticipantResponse>AddChatParticipantResponse | Object containing the result of the participant addition. | ### Example ``` await bot.add_participant_to_chat( chat_id="chat123", user_id="user456", display_history=True ) ``` ### `` answer_command `async` ⚓︎ ``` answer_command( command_id, answer_type, text, status=None, visibility=None, level=None, ) ``` Answer an incoming command created by a button with `wait_reply=True`. ### `` change_participant_role `async` ⚓︎ ``` change_participant_role(chat_id, user_id, role) ``` Requires TrueConf Server 5.5.2+. Changes the role of a participant in the specified group chat. This method requires that the bot has moderator (admin) or owner rights in the chat. ### Supported roles in group chat - "owner" — group chat owner - "admin" — appointed moderator of the group chat - "user" — regular participant of a group chat ### It is recommended to use the enumeration class for safer role assignment ``` from trueconf.enums import ChatParticipantRole ``` For a full list of roles in conference, channel, or Favorites chats, see the documentation: ### Role descriptions trueconf.com/docs/chatbot-connector/en/roles-and-users-rules/#which-roles-has-apis ### Role permissions matrix trueconf.com/docs/chatbot-connector/en/roles-and-users-rules/#roles-rules-group-chats ### Source trueconf.com/docs/chatbot-connector/en/chats/#changeParticipantRole Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat where the role should be changed. | required | | `user_id` | `str` | Identifier of the participant whose role is being updated. | required | | `role` | `str |` ChatParticipantRole (`trueconf.enums.chat_participant_role.ChatParticipantRole`)' href=../Enums/#trueconf.enums.ChatParticipantRole>ChatParticipantRole | New role to assign. Must be one of the supported roles listed above. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `ChangeParticipantRoleResponse` | `` ChangeParticipantRoleResponse (`trueconf.types.responses.change_participant_role_response.ChangeParticipantRoleResponse`)' href=../Responses/#trueconf.types.responses.ChangeParticipantRoleResponse>ChangeParticipantRoleResponse | Object containing the result of the role change operation. | ### Example ``` from trueconf.enums import ChatParticipantRole as role await bot.change_participant_role( chat_id="chat123", user_id="user456", role=role.ADMIN ) ``` ### `` check_version `async` ⚓︎ ``` check_version() ``` ### `` clear_chat_history `async` ⚓︎ ``` clear_chat_history(chat_id, for_all=False) ``` ``` **Requires TrueConf Server 5.5.3+** ``` Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to clear the history for. | required | | `for_all` | `bool` | If True, the history will be cleared for all participants. If False, it will only be cleared for the current user. Defaults to False. | `False` | Returns: | Name | Type | Description | | --- | --- | --- | | `ClearChatHistoryResponse` | `ClearChatHistoryResponse` | Object containing the result of the history clearing. | ### `` create_channel `async` ⚓︎ ``` create_channel(title) ``` Creates a new channel with the specified title. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createChannel Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `title` | `str` | Title of the new channel. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `CreateChannelResponse` | `` CreateChannelResponse (`trueconf.types.responses.create_channel_response.CreateChannelResponse`)' href=../Responses/#trueconf.types.responses.CreateChannelResponse>CreateChannelResponse | Object containing the result of the channel creation. | ### `` create_favorites_chat `async` ⚓︎ ``` create_favorites_chat() ``` Requires TrueConf Server 5.5.2+ Creates a "Favorites" chat for the current user. This type of chat is a personal space accessible only to its owner. It can be used to store notes, upload files, or test bot features in a private context. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createFavoritesChat Returns: | Name | Type | Description | | --- | --- | --- | | `CreateFavoritesChatResponse` | `CreateFavoritesChatResponse` | An object containing information about the newly created chat. | ### `` create_group_chat `async` ⚓︎ ``` create_group_chat(title) ``` Creates a new group chat with the specified title. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createGroupChat Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `title` | `str` | Title of the new group chat. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `CreateGroupChatResponse` | `` CreateGroupChatResponse (`trueconf.types.responses.create_group_chat_response.CreateGroupChatResponse`)' href=../Responses/#trueconf.types.responses.CreateGroupChatResponse>CreateGroupChatResponse | Object containing the result of the group chat creation. | ### `` create_personal_chat `async` ⚓︎ ``` create_personal_chat(user_id) ``` Creates a personal (P2P) chat with a user by their identifier. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createP2PChat Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `user_id` | `str` | Identifier of the user. Can be with or without a domain. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `CreateP2PChatResponse` | `` CreateP2PChatResponse (`trueconf.types.responses.create_p2p_chat_response.CreateP2PChatResponse`)' href=../Responses/#trueconf.types.responses.CreateP2PChatResponse>CreateP2PChatResponse | Object containing the result of the personal chat creation. | ### Note Creating a personal chat (peer-to-peer) with a server user. If the bot has never messaged this user before, a new chat will be created. If the bot has previously sent messages to this user, the existing chat will be returned. ### `` delete_chat `async` ⚓︎ ``` delete_chat(chat_id) ``` Deletes a chat by its identifier. ### Source trueconf.com/docs/chatbot-connector/en/chats/#removeChat Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to be deleted. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `RemoveChatResponse` | `` RemoveChatResponse (`trueconf.types.responses.remove_chat_response.RemoveChatResponse`)' href=../Responses/#trueconf.types.responses.RemoveChatResponse>RemoveChatResponse | Object containing the result of the chat deletion. | ### `` download_file_by_id `async` ⚓︎ ``` download_file_by_id( file_id, dest_path=None, *, file_path=None ) ``` Downloads a file by its ID, waiting for the upload to complete if necessary. If `file_path` is provided, the file is saved to that exact path. The deprecated `dest_path` is treated as a directory and the server file name is appended to it. If neither is provided, the file content is returned as bytes. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file_id` | `str` | Unique identifier of the file on the server. | required | | `dest_path` | `str | Path` | Deprecated destination directory. Use `file_path` to specify the exact output file. | `None` | | `file_path` | `str | Path` | Exact path where the file should be saved. | `None` | Returns: | Type | Description | | --- | --- | | `bytes | Path | None` | bytes | Path | None: File content (bytes), path to file (Path), or None if failed. | Raises: | Type | Description | | --- | --- | | `` InMemoryDownloadLimitExceededError (`trueconf.exceptions.InMemoryDownloadLimitExceededError`)' href=../Exceptions/#trueconf.exceptions.InMemoryDownloadLimitExceededError>InMemoryDownloadLimitExceededError | If an in-memory download exceeds `max_in_memory_download_size`. | ### `` edit_chat_avatar `async` ⚓︎ ``` edit_chat_avatar(chat_id, file) ``` Updates the avatar of the specified chat. Use this method to set a new chat avatar for a group chat and channel. ### Notes Requires TrueConf Server 5.5.3 or later. The bot must have sufficient permissions in the chat (e.g., owner or admin/moderator). The file must be provided as an instance of one of the `InputFile` subclasses: `FSInputFile`, `BufferedInputFile`, or `URLInputFile`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#editChatAvatar Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat whose avatar should be updated. | required | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=../Types/#trueconf.types.InputFile>InputFile | Image file to be uploaded as the new chat avatar. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `EditChatAvatarResponse` | `EditChatAvatarResponse` | Object containing the result of the avatar update. | ### Example ``` await bot.edit_chat_avatar( chat_id="a1s2d3f4f5g6", file=FSInputFile("avatar.png") ) ``` ### `` edit_chat_title `async` ⚓︎ ``` edit_chat_title(chat_id, title) ``` Updates the display title of the specified chat. Use this method to set a new visible name for a chat (e.g., a group chat or channel). ### Notes Requires TrueConf Server 5.5.3 or later. The bot must have sufficient permissions in the chat (e.g., owner or admin/moderator). ### Source trueconf.com/docs/chatbot-connector/en/chats/#editChatTitle Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat whose title should be updated. | required | | `title` | `str` | New title for the chat. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `EditChatTitleResponse` | `` EditChatTitleResponse (`trueconf.types.responses.edit_chat_title_response.EditChatTitleResponse`)' href=../Responses/#trueconf.types.responses.EditChatTitleResponse>EditChatTitleResponse | Object containing the result of the title update. | ### Example ``` await bot.edit_chat_title(chat_id="a1s2d3f4f5g6", title="Project Alpha – Team") ``` ### `` edit_message `async` ⚓︎ ``` edit_message( message_id, text, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT, *, buttons=None ) ``` Edits a previously sent message. The server treats `editMessage` as a full content overwrite (PUT): the new `content` replaces the old one completely. Pass `buttons` together with `text` to update the inline buttons; omit it (leave `None`) to remove the buttons from the message. ### Source trueconf.com/docs/chatbot-connector/en/messages/#editMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `message_id` | `str` | Identifier of the message to be edited. | required | | `text` | `str` | New text content for the message. | required | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode. Defaults to plain text. | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | | `buttons` | `` trueconf.types.InlineKeyboardMarkup `dataclass` (`trueconf.types.keyboard.InlineKeyboardMarkup`)' href=../Types/#trueconf.types.InlineKeyboardMarkup>InlineKeyboardMarkup | None | New inline keyboard. `None` (default) removes the buttons. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `EditMessageResponse` | `` EditMessageResponse (`trueconf.types.responses.edit_message_response.EditMessageResponse`)' href=../Responses/#trueconf.types.responses.EditMessageResponse>EditMessageResponse | Object containing the result of the message update. | ### `` edit_survey `async` ⚓︎ ``` edit_survey( message_id, title, survey_campaign_id, survey_type= NON_ANONYMOUS class-attribute instance-attribute (trueconf.enums.survey_type.SurveyType.NON_ANONYMOUS)' href=../Enums/#trueconf.enums.SurveyType.NON_ANONYMOUS>NON_ANONYMOUS, ) ``` Edits a previously sent survey. ### Source trueconf.com/docs/chatbot-connector/en/surveys/#editSurvey Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `message_id` | `str` | Identifier of the message containing the survey to edit. | required | | `title` | `str` | New title of the survey. | required | | `survey_campaign_id` | `str` | Identifier of the survey campaign. | required | | `survey_type` | `` SurveyType (`trueconf.enums.survey_type.SurveyType`)' href=../Enums/#trueconf.enums.SurveyType>SurveyType | Type of the survey (anonymous or non-anonymous). Defaults to non-anonymous. | `` NON_ANONYMOUS `class-attribute` `instance-attribute` (`trueconf.enums.survey_type.SurveyType.NON_ANONYMOUS`)' href=../Enums/#trueconf.enums.SurveyType.NON_ANONYMOUS>NON_ANONYMOUS | Returns: | Name | Type | Description | | --- | --- | --- | | `EditSurveyResponse` | `` EditSurveyResponse (`trueconf.types.responses.edit_survey_response.EditSurveyResponse`)' href=../Responses/#trueconf.types.responses.EditSurveyResponse>EditSurveyResponse | Object containing the result of the survey update. | ### `` forward_message `async` ⚓︎ ``` forward_message(chat_id, message_id) ``` Forwards a message to the specified chat. ### Source trueconf.com/docs/chatbot-connector/en/messages/#forwardMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to forward the message to. | required | | `message_id` | `str` | Identifier of the message to be forwarded. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `ForwardMessageResponse` | `` ForwardMessageResponse (`trueconf.types.responses.forward_message_response.ForwardMessageResponse`)' href=../Responses/#trueconf.types.responses.ForwardMessageResponse>ForwardMessageResponse | Object containing the result of the message forwarding. | ### `` from_credentials `classmethod` ⚓︎ ``` from_credentials( server, username, password, *, dispatcher=None, receive_unread_messages=False, receive_system_messages=False, skip_self_messages=True, verify_ssl=True, web_port=None, https=True, ws_max_retries=5, ws_max_delay=60, debug=False, on_health_check=None, timeout=10.0, max_in_memory_download_size=100 * 1024 * 1024, ) ``` Creates a bot instance using username and password authentication. ### Source trueconf.com/docs/chatbot-connector/en/connect-and-auth/#connect-and-auth Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `server` | `str` | Address of the TrueConf server. | required | | `username` | `str` | Username for authentication. | required | | `password` | `str` | Password for authentication. | required | | `*` | | All following arguments must be passed by name (keyword-only). | required | | `dispatcher` | `` trueconf.Dispatcher (`trueconf.dispatcher.dispatcher.Dispatcher`)' href=../Dispatcher/#trueconf.Dispatcher>Dispatcher | None | Dispatcher instance for registering handlers. | `None` | | `receive_unread_messages` | `bool` | Whether to receive unread messages on connection. Defaults to False. | `False` | | `receive_system_messages` | `bool` | Whether to receive system messages, such as user additions to the chat or chat title changes. Defaults to False. | `False` | | `skip_self_messages` | `bool` | If True, the bot will ignore messages sent by itself. Defaults to True. | `True` | | `verify_ssl` | `bool | str | SSLContext` | SSL verification mode. Defaults to True. | `True` | | `web_port` | `int` | WebSocket connection port. Defaults to 443. | `None` | | `https` | `bool` | Whether to use HTTPS protocol. Defaults to True. | `True` | | `ws_max_retries` | `int` | Max connection attempts on network/IP errors before giving up. Defaults to 5. | `5` | | `ws_max_delay` | `int` | Maximum delay between reconnection attempts (in seconds). Defaults to 60. | `60` | | `debug` | `bool` | Enables debug mode. Defaults to False. | `False` | | `on_health_check` | `HealthCheckCallback | None` | Async callback called when the bot connection health changes. Defaults to None. | `None` | | `timeout` | `float | int` | The maximum time in seconds to wait for network activity. Instead of limiting the total upload duration, it protects against socket freezes during data transmission and waiting for the server's response. Defaults to 10.0. | `10.0` | | `max_in_memory_download_size` | `int` | Maximum file size in bytes that can be returned in memory. Defaults to 100 MiB. This limit does not apply when `dest_path` is provided. | `100 * 1024 * 1024` | Returns: | Name | Type | Description | | --- | --- | --- | | `Bot` | `Self` | An authorized bot instance. | Raises: | Type | Description | | --- | --- | | `RuntimeError` | If the token could not be obtained. | ### `` from_oauth `classmethod` ⚓︎ ``` from_oauth( server, username, password, client_id, *, dispatcher=None, receive_unread_messages=False, receive_system_messages=False, skip_self_messages=True, verify_ssl=True, web_port=None, https=True, ws_max_retries=5, ws_max_delay=60, debug=False, on_health_check=None, timeout=10.0, max_in_memory_download_size=100 * 1024 * 1024, ) ``` Creates a bot instance using TrueConf Server OAuth2 authentication. Requires an OAuth application created on the TrueConf server. The method exchanges the user credentials and the application's client_id for the bot JWT token via the TrueConf Server OAuth2 API. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `server` | `str` | Address of the TrueConf server. | required | | `username` | `str` | Username for authentication. | required | | `password` | `str` | Password for authentication. | required | | `client_id` | `str` | Client ID of the OAuth application created on the server. | required | | `*` | | All remaining keyword arguments are identical to `from_credentials()`. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `Bot` | `Self` | An authorized bot instance. | Raises: | Type | Description | | --- | --- | | `RuntimeError` | If the token could not be obtained. | ### `` get_chat_by_id `async` ⚓︎ ``` get_chat_by_id(chat_id) ``` Retrieves information about a chat by its identifier. ### Source trueconf.com/docs/chatbot-connector/en/chats/#getChatById Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `GetChatByIDResponse` | `` GetChatByIdResponse (`trueconf.types.responses.get_chat_by_id_response.GetChatByIdResponse`)' href=../Responses/#trueconf.types.responses.GetChatByIdResponse>GetChatByIdResponse | Object containing information about the chat. | ### `` get_chat_history `async` ⚓︎ ``` get_chat_history(chat_id, count, from_message_id=None) ``` Retrieves the message history of the specified chat. ### Source trueconf.com/docs/chatbot-connector/en/messages/#getChatHistory Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat. | required | | `count` | `int` | Number of messages to retrieve. | required | | `from_message_id` | `str | None` | Identifier of the message to start retrieving history from. If not specified, the history will be loaded from the most recent message. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `GetChatHistoryResponse` | `` GetChatHistoryResponse (`trueconf.types.responses.get_chat_history_response.GetChatHistoryResponse`)' href=../Responses/#trueconf.types.responses.GetChatHistoryResponse>GetChatHistoryResponse | Object containing the result of the chat history request. | Raises: | Type | Description | | --- | --- | | `ValueError` | If the count number is less than 1. | ### `` get_chat_participant `async` ⚓︎ ``` get_chat_participant(chat_id, user_id) ``` Retrieves information about a chat participant. ### Source trueconf.com/docs/chatbot-connector/en/chats/#getChatParticipant Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat. | required | | `user_id` | `str` | Identifier of the user. Can be with or without a domain. | required | Returns: | Type | Description | | --- | --- | | `GetChatParticipantResponse |` ApiError (`trueconf.types.responses.ApiError`)' href=../Responses/#trueconf.types.responses.ApiError>ApiError | GetChatParticipantResponse | ApiError: Object containing information about the requested | | `GetChatParticipantResponse |` ApiError (`trueconf.types.responses.ApiError`)' href=../Responses/#trueconf.types.responses.ApiError>ApiError | participant, or an API error if the user is not a participant of the chat. | ### `` get_chat_participants `async` ⚓︎ ``` get_chat_participants(chat_id, page_size, page_number) ``` Retrieves a paginated list of chat participants. ### Source trueconf.com/docs/chatbot-connector/en/chats/#getChatParticipants Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat. | required | | `page_size` | `int` | Number of participants per page. | required | | `page_number` | `int` | Page number. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `GetChatParticipantsResponse` | `` GetChatParticipantsResponse (`trueconf.types.responses.get_chat_participants_response.GetChatParticipantsResponse`)' href=../Responses/#trueconf.types.responses.GetChatParticipantsResponse>GetChatParticipantsResponse | Object containing the result of the participant list request. | ### `` get_chats `async` ⚓︎ ``` get_chats(count=10, page=1) ``` Retrieves a paginated list of chats available to the bot. ### Source trueconf.com/docs/chatbot-connector/en/chats/#getChats Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `count` | `int` | Number of chats per page. Defaults to 10. | `10` | | `page` | `int` | Page number. Must be greater than 0. Defaults to 1. | `1` | Returns: | Name | Type | Description | | --- | --- | --- | | `GetChatsResponse` | `` GetChatsResponse (`trueconf.types.responses.get_chats_response.GetChatsResponse`)' href=../Responses/#trueconf.types.responses.GetChatsResponse>GetChatsResponse | Object containing the result of the chat list request. | Raises: | Type | Description | | --- | --- | | `ValueError` | If the page number is less than 1. | ### `` get_file_info `async` ⚓︎ ``` get_file_info(file_id) ``` Retrieves information about a file by its identifier. ### Source trueconf.com/docs/chatbot-connector/en/files/#getFileInfo Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file_id` | `str` | Identifier of the file. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `GetFileInfoResponse` | `` GetFileInfoResponse (`trueconf.types.responses.get_file_info_response.GetFileInfoResponse`)' href=../Responses/#trueconf.types.responses.GetFileInfoResponse>GetFileInfoResponse | Object containing information about the file. | ### `` get_file_info_upload_limits `async` ⚓︎ ``` get_file_info_upload_limits() ``` Returns the current file upload limits configured on the TrueConf Server. Useful for validating outgoing files in advance (e.g., checking maximum file size and allowed types/extensions). ### Notes Requires TrueConf Server 5.5.3 or later. ### Source trueconf.com/docs/chatbot-connector/en/files/#getFileUploadLimits Returns: | Name | Type | Description | | --- | --- | --- | | `GetFileUploadLimitsResponse` | `` GetFileUploadLimitsResponse (`trueconf.types.responses.GetFileUploadLimitsResponse`)' href=../Responses/#trueconf.types.responses.GetFileUploadLimitsResponse>GetFileUploadLimitsResponse | Object describing upload constraints | | | `` GetFileUploadLimitsResponse (`trueconf.types.responses.GetFileUploadLimitsResponse`)' href=../Responses/#trueconf.types.responses.GetFileUploadLimitsResponse>GetFileUploadLimitsResponse | (e.g., maximum file size, allowed types/extensions). | ### Example ``` limits = await bot.get_file_info_upload_limits() # Use `limits` fields to validate a file before uploading ``` ### `` get_message_by_id `async` ⚓︎ ``` get_message_by_id(message_id) ``` Retrieves a message by its identifier. ### Source trueconf.com/docs/chatbot-connector/en/messages/#getMessageById Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `message_id` | `str` | Identifier of the message to retrieve. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `GetMessageByIdResponse` | `` GetMessageByIdResponse (`trueconf.types.responses.get_message_by_id_response.GetMessageByIdResponse`)' href=../Responses/#trueconf.types.responses.GetMessageByIdResponse>GetMessageByIdResponse | Object containing the retrieved message data. | ### `` get_user_display_name `async` ⚓︎ ``` get_user_display_name(user_id) ``` Retrieves the display name of a user by their TrueConf ID. ### Source trueconf.com/docs/chatbot-connector/en/contacts/#getUserDisplayName Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `user_id` | `str` | User's TrueConf ID. Can be specified with or without a domain. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `GetUserDisplayNameResponse` | `` GetUserDisplayNameResponse (`trueconf.types.responses.get_user_display_name_response.GetUserDisplayNameResponse`)' href=../Responses/#trueconf.types.responses.GetUserDisplayNameResponse>GetUserDisplayNameResponse | Object containing the user's display name. | ### `` has_chat_participant `async` ⚓︎ ``` has_chat_participant(chat_id, user_id) ``` Checks whether the specified user is a participant in the chat. ### Source trueconf.com/docs/chatbot-connector/en/chats/#hasChatParticipant Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat. | required | | `user_id` | `str` | Identifier of the user. Can be with or without a domain. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `HasChatParticipantResponse` | `` HasChatParticipantResponse (`trueconf.types.responses.has_chat_participant_response.HasChatParticipantResponse`)' href=../Responses/#trueconf.types.responses.HasChatParticipantResponse>HasChatParticipantResponse | Object containing the result of the check. | ### `` health_check ⚓︎ ``` health_check() ``` Returns the current bot health status. This method can be used by external monitoring systems, HTTP health endpoints, or application code that needs to check the current WebSocket and authorization state without waiting for a callback event. Returns: | Type | Description | | --- | --- | | `Dict[str, Any]` | Dict[str, Any]: Dictionary containing the current status, WebSocket state, authorization state, server, port, protocol, and UTC timestamp. | ### `` me `async` ⚓︎ ``` me() ``` Returns the identifier of the bot's personal (Favorites) chat. If the chat does not exist yet, it will be created automatically. The result is cached to prevent redundant API calls. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Chat ID of the bot's personal Favorites chat. | ### `` me_chat `async` ⚓︎ ``` me_chat() ``` Returns the identifier of the bot's personal (Favorites) chat. If the chat does not exist yet, it will be created automatically. The result is cached to prevent redundant API calls. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Chat ID of the bot's personal Favorites chat. | ### `` remove_message `async` ⚓︎ ``` remove_message(message_id, for_all=False) ``` Removes a message by its identifier. ### Source trueconf.com/docs/chatbot-connector/en/messages/#removeMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `message_id` | `str` | Identifier of the message to be removed. | required | | `for_all` | `bool` | If True, the message will be removed for all participants. Default to False (the message is removed only for the bot). | `False` | Returns: | Name | Type | Description | | --- | --- | --- | | `RemoveMessageResponse` | `` RemoveMessageResponse (`trueconf.types.responses.remove_message_response.RemoveMessageResponse`)' href=../Responses/#trueconf.types.responses.RemoveMessageResponse>RemoveMessageResponse | Object containing the result of the message deletion. | ### `` remove_participant_from_chat `async` ⚓︎ ``` remove_participant_from_chat( chat_id, user_id, clear_history=False ) ``` Removes a participant from the specified chat. ### Source trueconf.com/docs/chatbot-connector/en/chats/#removeChatParticipant Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to remove the participant from. | required | | `user_id` | `str` | Identifier of the user to be removed. | required | | `clear_history` | `bool` | If True, the chat history will be cleared for the removed participant. Defaults to False. | `False` | Returns: | Name | Type | Description | | --- | --- | --- | | `RemoveChatParticipantResponse` | `` RemoveChatParticipantResponse (`trueconf.types.responses.remove_chat_participant_response.RemoveChatParticipantResponse`)' href=../Responses/#trueconf.types.responses.RemoveChatParticipantResponse>RemoveChatParticipantResponse | Object containing the result of the participant removal. | ### `` reply_message `async` ⚓︎ ``` reply_message(chat_id, message_id, text, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT) ``` Sends a reply to an existing message in the chat. ### Source trueconf.com/docs/chatbot-connector/en/messages/#replyMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat where the reply will be sent. | required | | `message_id` | `str` | Identifier of the message to reply to. | required | | `text` | `str` | Text content of the reply. | required | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode. Defaults to plain text. | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | Returns: | Name | Type | Description | | --- | --- | --- | | `SendMessageResponse` | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | Object containing the result of the message delivery. | ### `` run `async` ⚓︎ ``` run(handle_signals=True) ``` Runs the bot and waits until it stops. Supports handling termination signals (SIGINT, SIGTERM). Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `handle_signals` | `bool` | Whether to handle termination signals. Defaults to True. | `True` | Returns: | Type | Description | | --- | --- | | `None` | None | ### `` send_chat_activity `async` ⚓︎ ``` send_chat_activity(chat_id, activity_type) ``` Sends a chat activity indicator (for example, typing) to the specified chat. The indicator expires after a short time, so for long operations use `ChatActivitySender` to keep it visible. ### Source trueconf.com/docs/chatbot-connector/en/messages/#sendChatActivity Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to send the activity to. | required | | `activity_type` | `` ChatActivity (`trueconf.enums.chat_activity.ChatActivity`)' href=../Enums/#trueconf.enums.ChatActivity>ChatActivity | str | Type of activity to display. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `SendChatActivityResponse` | `` SendChatActivityResponse (`trueconf.types.responses.send_chat_activity_response.SendChatActivityResponse`)' href=../Responses/#trueconf.types.responses.SendChatActivityResponse>SendChatActivityResponse | Object containing the result of the request. | ### `` send_document `async` ⚓︎ ``` send_document( chat_id, file, caption=None, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT, reply_message_id=None, ) ``` Sends a document or any arbitrary file to the specified chat. This method supports all file types, including images. However, images sent via this method will be transferred in original, uncompressed form. If you want to send a compressed image with preview support, use `send_photo()` instead. The file must be provided as an instance of one of the `InputFile` subclasses: `FSInputFile`, `BufferedInputFile`, or `URLInputFile`. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | The identifier of the chat to which the document will be sent. | required | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=../Types/#trueconf.types.InputFile>InputFile | The file to be uploaded. Must be a subclass of `InputFile`. | required | | `caption` | `str | None` | Optional caption text to be sent with the file. | `None` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode (e.g., Markdown, HTML, or plain text). | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | | `reply_message_id` | `str` | Optional identifier of the message to which this message is a reply. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | An object containing the result of the file upload. If the file was sent with a caption, `caption_message_id` contains the ID of the caption message. | ### Example ``` await bot.send_document( chat_id="a1s2d3f4f5g6", file=FSInputFile("report.pdf"), caption="📄 Annual report **for 2025**", parse_mode=ParseMode.MARKDOWN ) ``` ### `` send_message `async` ⚓︎ ``` send_message( chat_id, text, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT, reply_message_id=None, *, buttons=None, quote=None, ) ``` Sends a message to the specified chat. ### Source trueconf.com/docs/chatbot-connector/en/messages/#sendMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to send the message to. | required | | `text` | `str` | Text content of the message. | required | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode. Defaults to plain text. | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | | `reply_message_id` | `str` | Optional identifier of the message to which this message is a reply. | `None` | | `quote` | `str` | Part of the replied message to highlight in the reply preview. Requires `reply_message_id`. The quote body follows the message `parse_mode`: HTML and plain text are wrapped into an HTML quote block (plain text is escaped, parse mode becomes HTML), while Markdown uses a `>quote` blockquote. Note: the substring is not validated against the replied message here, only in `Message.reply()`. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `SendMessageResponse` | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | Object containing the result of the message delivery. | ### `` send_photo `async` ⚓︎ ``` send_photo( chat_id, file, preview, caption=None, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT, reply_message_id=None, ) ``` Sends a photo to the specified chat, with optional caption and preview support. This method is recommended when sending compressed images with preview support. If you want to send uncompressed images or arbitrary files, use `send_document()` instead. The file must be provided as an instance of one of the `InputFile` subclasses: `FSInputFile`, `BufferedInputFile`, or `URLInputFile`. Supported image formats include: `.jpg`, `.jpeg`, `.png`, `.webp`, `.bmp`, `.gif`, `.tiff` ### Source trueconf.com/docs/chatbot-connector/en/files/#file-transfer Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to which the photo will be sent. | required | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=../Types/#trueconf.types.InputFile>InputFile | The photo file to upload. Must be a subclass of `InputFile`. | required | | `preview` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=../Types/#trueconf.types.InputFile>InputFile | None | Optional preview image. Must also be an `InputFile` if provided. | required | | `caption` | `str | None` | Optional caption to be sent along with the image. | `None` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Formatting mode for the caption (e.g., Markdown, HTML, plain text). | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | | `reply_message_id` | `str` | Optional identifier of the message to which this message is a reply. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | An object containing the result of the file upload. If the photo was sent with a caption, `caption_message_id` contains the ID of the caption message. | ### Example ``` await bot.send_photo( chat_id="a1s2d3f4f5g6", file=FSInputFile("image.jpg"), preview=FSInputFile("image_preview.webp"), caption="Here's our **team** photo 📸", parse_mode=ParseMode.MARKDOWN ) ``` ### `` send_sticker `async` ⚓︎ ``` send_sticker(chat_id, file, reply_message_id=None) ``` Sends a sticker in WebP format to the specified chat. The file must have a MIME type of `'image/webp'`, otherwise a `TypeError` will be raised. The file must be an instance of one of the `InputFile` subclasses: `FSInputFile`, `BufferedInputFile`, or `URLInputFile`. A preview is automatically generated from the source file, as required for sticker uploads in TrueConf. ### Source trueconf.com/docs/chatbot-connector/en/files/#file-transfer Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to which the sticker will be sent. | required | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=../Types/#trueconf.types.InputFile>InputFile | The sticker file in WebP format. Must be a subclass of `InputFile`. | required | | `reply_message_id` | `str` | Optional identifier of the message to which this message is a reply. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | An object containing the result of the file upload. | Raises: | Type | Description | | --- | --- | | `TypeError` | If the file's MIME type is not `'image/webp'`. | ### Example ``` await bot.send_sticker(chat_id="user123", file=FSInputFile("sticker.webp")) ``` ### `` send_survey `async` ⚓︎ ``` send_survey( chat_id, title, survey_campaign_id, reply_message_id=None, survey_type= NON_ANONYMOUS class-attribute instance-attribute (trueconf.enums.survey_type.SurveyType.NON_ANONYMOUS)' href=../Enums/#trueconf.enums.SurveyType.NON_ANONYMOUS>NON_ANONYMOUS, ) ``` Sends a survey to the specified chat. ### Source trueconf.com/docs/chatbot-connector/en/surveys/#sendSurvey Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the chat to send the survey to. | required | | `title` | `str` | Title of the survey displayed in the chat. | required | | `survey_campaign_id` | `str` | Identifier of the survey campaign. | required | | `reply_message_id` | `str` | Optional identifier of the message to which this message is a reply. | `None` | | `survey_type` | `` SurveyType (`trueconf.enums.survey_type.SurveyType`)' href=../Enums/#trueconf.enums.SurveyType>SurveyType | Type of the survey (anonymous or non-anonymous). Defaults to non-anonymous. | `` NON_ANONYMOUS `class-attribute` `instance-attribute` (`trueconf.enums.survey_type.SurveyType.NON_ANONYMOUS`)' href=../Enums/#trueconf.enums.SurveyType.NON_ANONYMOUS>NON_ANONYMOUS | Returns: | Name | Type | Description | | --- | --- | --- | | `SendSurveyResponse` | `` SendSurveyResponse (`trueconf.types.responses.send_survey_response.SendSurveyResponse`)' href=../Responses/#trueconf.types.responses.SendSurveyResponse>SendSurveyResponse | Object containing the result of the survey submission. | ### `` server_name `async` ⚓︎ ``` server_name() ``` Returns the domain name of the TrueConf server. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Domain name of the connected server. | ### `` server_version `async` ⚓︎ ``` server_version() ``` Returns the server version of the TrueConf server. Returns: | Type | Description | | --- | --- | | `str | None` | str | None: Version of the connected server, or None if unavailable. | ### `` shutdown `async` ⚓︎ ``` shutdown(timeout=None) ``` Gracefully shuts down the bot after active update handlers have finished. This method: - Stops accepting new updates; - Waits for active update handlers to finish; - Cancels the connection task if it is still active; - Closes the WebSocket session or `self.session` if they are open; - Clears the connection and authorization events; - Sets the `stopped_event` flag. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `timeout` | `float | None` | Maximum time in seconds to wait for active update handlers to finish. If the timeout is reached, the remaining handlers are left running and shutdown continues. Defaults to None, which waits indefinitely. | `None` | Returns: | Type | Description | | --- | --- | | `None` | None | ### `` start `async` ⚓︎ ``` start() ``` Starts the bot by connecting to the server and listening for incoming events. ### Note This method is safe to call multiple times — subsequent calls are ignored if the connection is already active. Returns: | Type | Description | | --- | --- | | `None` | None | ### `` subscribe_file_progress `async` ⚓︎ ``` subscribe_file_progress(file_id) ``` Subscribes to file transfer progress updates. ### Source trueconf.com/docs/chatbot-connector/en/files/#subscribeFileProgress Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file_id` | `str` | Identifier of the file. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `SubscribeFileProgressResponse` | `` SubscribeFileProgressResponse (`trueconf.types.responses.subscribe_file_progress_response.SubscribeFileProgressResponse`)' href=../Responses/#trueconf.types.responses.SubscribeFileProgressResponse>SubscribeFileProgressResponse | Object containing the result of the subscription. | ### Note If the file is in the UPLOADING status, you can subscribe to the upload process to be notified when the file becomes available. ### `` unsubscribe_file_progress `async` ⚓︎ ``` unsubscribe_file_progress(file_id) ``` Unsubscribes from receiving file upload progress events. ### Source trueconf.com/docs/chatbot-connector/en/files/#unsubscribeFileProgress Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file_id` | `str` | Identifier of the file. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `UnsubscribeFileProgressResponse` | `` UnsubscribeFileProgressResponse (`trueconf.types.responses.unsubscribe_file_progress_response.UnsubscribeFileProgressResponse`)' href=../Responses/#trueconf.types.responses.UnsubscribeFileProgressResponse>UnsubscribeFileProgressResponse | Object containing the result of the unsubscription. | ### Note If necessary, you can unsubscribe from file upload events that were previously subscribed to using the `subscribe_file_progress()` method. June 30, 2026 September 3, 2025 --- # DOCUMENT: Class Router ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Router.md # Class `Router`⚓︎ Here is the reference information for the `Router` class, including all its parameters, attributes, and methods. You can import the `Router` class directly from the `trueconf` package: ``` from trueconf import Router ``` ## `` trueconf.Router ⚓︎ ``` Router(name=None, allow_child_on_event=False, _parent=None) ``` Event router for handling incoming events in a structured and extensible way. A `Router` allows you to register event handlers with specific filters, such as message types, chat events, or custom logic. You can also include nested routers using `include_router()` to build modular and reusable event structures. Handlers can be registered for: - Messages (`@.message(...)`) - System messages (`@.system_message(...)`) - Chat creation events (`@.created_personal_chat()`, `@.created_group_chat()`, `@.created_channel()`) - Participant events (`@.added_chat_participant()`, `@.removed_chat_participant()`) - Message lifecycle events (`@.edited_message()`, `@.removed_message()`) - File upload events (`@.uploading_progress()`) - Removed chats (`@.removed_chat()`) Example: ``` router = Router() @router.message(F.text == "hello") async def handle_hello(msg: Message): await msg.answer("Hi there!") ``` If you have multiple routers, use `.include_router()` to add them to a parent router. ### `` allow_child_on_event `instance-attribute` ⚓︎ ``` allow_child_on_event = allow_child_on_event ``` ### `` name `instance-attribute` ⚓︎ ``` name = name or hex(id(self)) ``` ### `` added_chat_participant ⚓︎ ``` added_chat_participant(*filters) ``` Register a handler when a participant is added to a chat. ### `` callback_query ⚓︎ ``` callback_query(*filters) ``` Register a handler for incoming `CallbackQuery` events. ### `` changed_file_upload_limits ⚓︎ ``` changed_file_upload_limits(*filters) ``` Requires TrueConf Server 5.5.3+ Registers a handler for file upload limits change events. This handler is triggered when the server's file upload restrictions are updated. The event is represented by the `ChangedFileUploadLimits` type and may include: - `max_size` — the maximum allowed file size in bytes (`1 MB = 1000 bytes`). If the size limit is disabled, the value is `None`. - `extensions` — file extension restrictions. If extension filtering is disabled, the value is `None`. If `extensions` is provided, it contains: - `mode` — restriction mode: - `block` — blocked extensions (blacklist) - `allow` — allowed extensions (whitelist) - `list` — list of file extensions. ### Source trueconf.com/docs/chatbot-connector/en/files/#newFileUploadLimits Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*filters` | `FilterLike` | Optional filters to apply to the event. Multiple filters can be specified. | `()` | Returns: | Name | Type | Description | | --- | --- | --- | | `Callable` | | A decorator function for registering the handler. | ### Example ``` from trueconf.types import ChangedFileUploadLimits @router.changed_file_upload_limits() async def on_limits_changed(event: ChangedFileUploadLimits): print(f"Max file size: {event.max_size}") if event.extensions: print(f"Mode: {event.extensions.mode}") print(f"Extensions: {event.extensions.list}") ``` ### `` changed_participant_role ⚓︎ ``` changed_participant_role(*filters) ``` Requires TrueConf Server 5.5.2+ Registers a handler for participant role change events in chats. This handler is triggered when a user's role is changed in a personal chat, group chat, channel, or conference chat. Used with the `ChangedParticipantRole` event type. ### Source trueconf.com/docs/chatbot-connector/en/chats/#changedParticipantRole Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*filters` | `FilterLike` | Optional filters to apply to the event. Multiple filters can be specified. | `()` | Returns: | Name | Type | Description | | --- | --- | --- | | `Callable` | | A decorator function for registering the handler. | ### Example ``` from trueconf.enums import ChatParticipantRole as role from trueconf.types import ChangedParticipantRole @router.changed_participant_role() async def on_role_changed(event: ChangedParticipantRole): if event.role == role.admin: print(f"{event.user_id} has been promoted to admin in chat {event.chat_id}") ``` ### `` cleared_chat_history ⚓︎ ``` cleared_chat_history(*filters) ``` Requires TrueConf Server 5.5.3+ Registers a handler for chat history clearing events. This handler is triggered when the message history of a chat is cleared. Used with the `ClearedChatHistory` event type. ### Source trueconf.com/docs/chatbot-connector/en/chats/#clearedHistory Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*filters` | `FilterLike` | Optional filters to apply to the event. Multiple filters can be specified. | `()` | Returns: | Name | Type | Description | | --- | --- | --- | | `Callable` | | A decorator function for registering the handler. | ### Example ``` from trueconf.types import ClearedChatHistory @router.cleared_chat_history() async def on_history_cleared(event: ClearedChatHistory): print(f"History was cleared in chat {event.chat_id}. For all: {event.for_all}") ``` ### `` created_channel ⚓︎ ``` created_channel(*filters) ``` Register a handler for channel creation events. ### `` created_favorites_chat ⚓︎ ``` created_favorites_chat(*filters) ``` Requires TrueConf Server 5.5.2+. Register a handler for favorites chat creation events. ### `` created_group_chat ⚓︎ ``` created_group_chat(*filters) ``` Register a handler for group chat creation events. ### `` created_personal_chat ⚓︎ ``` created_personal_chat(*filters) ``` Register a handler for personal chat creation events. ### `` edited_chat_avatar ⚓︎ ``` edited_chat_avatar(*filters) ``` Requires TrueConf Server 5.5.3+ Registers a handler for chat avatar edit events. This handler is triggered when a chat avatar is changed. Used with the `EditedChatAvatar` event type. ### Source trueconf.com/docs/chatbot-connector/en/chats/#editedChatAvatar Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*filters` | `FilterLike` | Optional filters to apply to the event. Multiple filters can be specified. | `()` | Returns: | Name | Type | Description | | --- | --- | --- | | `Callable` | | A decorator function for registering the handler. | ### Example ``` from trueconf.types import EditedChatAvatar @router.edited_chat_avatar() async def on_avatar_changed(event: EditedChatAvatar): print(f"Avatar was updated in chat {event.chat_id}") print(f"New avatar: {event.avatar_url}") ``` ### `` edited_chat_title ⚓︎ ``` edited_chat_title(*filters) ``` Requires TrueConf Server 5.5.3+ Registers a handler for chat title edit events. This handler is triggered when a chat title is changed. Used with the `EditedChatTitle` event type. ### Source trueconf.com/docs/chatbot-connector/en/chats/#editedChatTitle Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*filters` | `FilterLike` | Optional filters to apply to the event. Multiple filters can be specified. | `()` | Returns: | Name | Type | Description | | --- | --- | --- | | `Callable` | | A decorator function for registering the handler. | ### Example ``` from trueconf.types import EditedChatTitle @router.edited_chat_title() async def on_title_changed(event: EditedChatTitle): print(f"Chat {event.chat_id} has a new title: {event.title}") ``` ### `` edited_message ⚓︎ ``` edited_message(*filters) ``` Register a handler for message edit events. ### `` event ⚓︎ ``` event(method=None, *filters) ``` Register a raw handler for incoming updates, filtered by method name. Handlers receive the full raw envelope as `trueconf.types.Update` (`method`, `type`, `id`, `payload`). Typed decorators (`@r.callback_query()`, `@r.message()`, ...) receive typed objects. Examples: ``` >>> @r.event() # ловит все сырые апдейты >>> async def raw_all(event: Update): ... ``` ``` >>> @r.event("command") # только нажатия кнопок >>> async def raw_command(event: Update): ... ``` ### `` include_router ⚓︎ ``` include_router(router) ``` Include a child router for hierarchical event routing. ### `` inner_middleware ⚓︎ ``` inner_middleware(middleware) ``` Register inner middleware (runs after filter match, before handler). ### `` message ⚓︎ ``` message(*filters) ``` Register a handler for incoming `Message` events. ### `` outer_middleware ⚓︎ ``` outer_middleware(middleware) ``` Register outer middleware (runs before filter/handler matching). ### `` removed_chat ⚓︎ ``` removed_chat(*filters) ``` Register a handler when a chat is removed. ### `` removed_chat_participant ⚓︎ ``` removed_chat_participant(*filters) ``` Register a handler when a participant is removed from a chat. ### `` removed_message ⚓︎ ``` removed_message(*filters) ``` Register a handler for message deletion events. ### `` system_message ⚓︎ ``` system_message(*filters) ``` Register a handler for incoming `SystemMessage` events. ### `` uploading_progress ⚓︎ ``` uploading_progress(*filters) ``` Register a handler for file uploading progress events. June 30, 2026 September 3, 2025 --- # DOCUMENT: Class Dispatcher ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Dispatcher.md # Class `Dispatcher`⚓︎ Here is the reference information for the `Dispatcher` class, including all its parameters, attributes, and methods. You can import the `Dispatcher` class directly from the `trueconf` package: ``` from trueconf import Dispatcher ``` ## `` trueconf.Dispatcher ⚓︎ ``` Dispatcher( *, storage=None, fsm_manager=None, key_builder=None, strategy=None, ) ``` Central dispatcher for routing incoming events. The dispatcher receives incoming events, applies its outer middleware chain, and then passes each event to every included root router in registration order. Root routers are independent; handling an event in one root does not prevent another root from receiving it. Each root owns an ordered tree of child routers. Within one tree, traversal stops at the first router that handles the event. A router created with `allow_child_on_event=True` also propagates handled events to its children. `Dispatcher` inherits from `Router`, so it supports the same handler, middleware, and subrouter registration APIs. ### Example ``` dispatcher = Dispatcher() dispatcher.include_router(router) ``` ### FSM example ``` from trueconf.fsm.storage.memory import MemoryStorage storage = MemoryStorage() dp = Dispatcher(storage=storage) ``` Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `storage` | `BaseStorage | None` | Storage backend used to create an FSM manager. Cannot be used together with `fsm_manager`. | `None` | | `fsm_manager` | `FSMManager | None` | Existing FSM manager instance. Cannot be used together with `storage`. | `None` | | `key_builder` | `KeyBuilder | None` | Key builder used when creating an FSM manager from `storage`. Ignored when `fsm_manager` is passed. | `None` | | `strategy` | `FSMStrategy | None` | FSM strategy used when creating an FSM manager from `storage`. Ignored when `fsm_manager` is passed. | `None` | Attributes: | Name | Type | Description | | --- | --- | --- | | `routers` | `List[` trueconf.Router (`trueconf.dispatcher.router.Router`)' href=../Router/#trueconf.Router>Router] | Root routers included in the dispatcher. | | `fsm` | `FSMManager | None` | FSM manager configured for the dispatcher, or `None` if FSM support has not been enabled. | ### `` include_router ⚓︎ ``` include_router(router) ``` Include a root router in the dispatcher. The dispatcher's own middleware is applied in `_feed_update` before the event reaches child routers. Therefore we do NOT set `_parent` — child routers should not inherit the dispatcher's middleware through the ancestor chain. June 30, 2026 September 3, 2025 --- # DOCUMENT: Enums **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Enums.md # Enums You can import all enums at once: ``` from trueconf.enums import * ``` ## `` trueconf.enums ⚓︎ ### `` ALLOWED_BUTTON_URL_SCHEMES `module-attribute` ⚓︎ ``` ALLOWED_BUTTON_URL_SCHEMES = ( "http", "https", "mailto", "trueconf", ) ``` ### `` ButtonStyle ⚓︎ #### `` DANGER `class-attribute` `instance-attribute` ⚓︎ ``` DANGER = 'danger' ``` #### `` DEFAULT `class-attribute` `instance-attribute` ⚓︎ ``` DEFAULT = 'default' ``` #### `` PRIMARY `class-attribute` `instance-attribute` ⚓︎ ``` PRIMARY = 'primary' ``` #### `` SUCCESS `class-attribute` `instance-attribute` ⚓︎ ``` SUCCESS = 'success' ``` ### `` ButtonType ⚓︎ #### `` COMMAND `class-attribute` `instance-attribute` ⚓︎ ``` COMMAND = 'command' ``` #### `` COPY `class-attribute` `instance-attribute` ⚓︎ ``` COPY = 'copy' ``` #### `` MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` MESSAGE = 'message' ``` #### `` SHARE `class-attribute` `instance-attribute` ⚓︎ ``` SHARE = 'share' ``` #### `` URL `class-attribute` `instance-attribute` ⚓︎ ``` URL = 'url' ``` ### `` ChatActivity ⚓︎ This object represents a type of activity that the bot can show in a chat. ### Source trueconf.com/docs/chatbot-connector/en/messages/#sendChatActivity #### `` CHOOSING_STICKER `class-attribute` `instance-attribute` ⚓︎ ``` CHOOSING_STICKER = 'choosing_sticker' ``` #### `` TYPING `class-attribute` `instance-attribute` ⚓︎ ``` TYPING = 'typing' ``` #### `` UPLOADING_FILE `class-attribute` `instance-attribute` ⚓︎ ``` UPLOADING_FILE = 'uploading_file' ``` ### `` ChatParticipantRole ⚓︎ This object represents a possible participant role in a chat. ### Source trueconf.com/docs/chatbot-connector/en/objects/#chatparticipantroleenum #### `` ADMIN `class-attribute` `instance-attribute` ⚓︎ ``` ADMIN = 'admin' ``` #### `` CONF_MODERATOR `class-attribute` `instance-attribute` ⚓︎ ``` CONF_MODERATOR = 'conf_moderator' ``` #### `` CONF_OWNER `class-attribute` `instance-attribute` ⚓︎ ``` CONF_OWNER = 'conf_owner' ``` #### `` FAVORITES_OWNER `class-attribute` `instance-attribute` ⚓︎ ``` FAVORITES_OWNER = 'favorites_owner' ``` #### `` OWNER `class-attribute` `instance-attribute` ⚓︎ ``` OWNER = 'owner' ``` #### `` USER `class-attribute` `instance-attribute` ⚓︎ ``` USER = 'user' ``` #### `` WRITER `class-attribute` `instance-attribute` ⚓︎ ``` WRITER = 'writer' ``` ### `` ChatType ⚓︎ The enumeration contains possible chat types. ### Source trueconf.com/docs/chatbot-connector/en/objects/#chattypeenum #### `` CHANNEL `class-attribute` `instance-attribute` ⚓︎ ``` CHANNEL = 6 ``` #### `` FAVORITES `class-attribute` `instance-attribute` ⚓︎ ``` FAVORITES = 5 ``` #### `` GROUP `class-attribute` `instance-attribute` ⚓︎ ``` GROUP = 2 ``` #### `` P2P `class-attribute` `instance-attribute` ⚓︎ ``` P2P = 1 ``` #### `` SYSTEM `class-attribute` `instance-attribute` ⚓︎ ``` SYSTEM = 3 ``` #### `` UNDEF `class-attribute` `instance-attribute` ⚓︎ ``` UNDEF = 0 ``` ### `` CommandAnswerType ⚓︎ #### `` CANCEL `class-attribute` `instance-attribute` ⚓︎ ``` CANCEL = 'cancel' ``` #### `` COMPLETE `class-attribute` `instance-attribute` ⚓︎ ``` COMPLETE = 'complete' ``` #### `` MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` MESSAGE = 'message' ``` #### `` TIMEOUT `class-attribute` `instance-attribute` ⚓︎ ``` TIMEOUT = 'timeout' ``` ### `` CommandMessageLevel ⚓︎ #### `` CRITICAL `class-attribute` `instance-attribute` ⚓︎ ``` CRITICAL = 'critical' ``` #### `` ERROR `class-attribute` `instance-attribute` ⚓︎ ``` ERROR = 'error' ``` #### `` INFO `class-attribute` `instance-attribute` ⚓︎ ``` INFO = 'info' ``` #### `` WARNING `class-attribute` `instance-attribute` ⚓︎ ``` WARNING = 'warning' ``` ### `` CommandMessageStatus ⚓︎ #### `` CANCELED `class-attribute` `instance-attribute` ⚓︎ ``` CANCELED = 'canceled' ``` #### `` FAILED `class-attribute` `instance-attribute` ⚓︎ ``` FAILED = 'failed' ``` #### `` OK `class-attribute` `instance-attribute` ⚓︎ ``` OK = 'ok' ``` #### `` PENDING `class-attribute` `instance-attribute` ⚓︎ ``` PENDING = 'pending' ``` #### `` RUNNING `class-attribute` `instance-attribute` ⚓︎ ``` RUNNING = 'running' ``` #### `` TIMEOUT `class-attribute` `instance-attribute` ⚓︎ ``` TIMEOUT = 'timeout' ``` #### `` UNKNOWN `class-attribute` `instance-attribute` ⚓︎ ``` UNKNOWN = 'unknown' ``` ### `` CommandMessageVisibility ⚓︎ #### `` ALERT `class-attribute` `instance-attribute` ⚓︎ ``` ALERT = 'alert' ``` #### `` DEFAULT `class-attribute` `instance-attribute` ⚓︎ ``` DEFAULT = 'default' ``` #### `` STICKY `class-attribute` `instance-attribute` ⚓︎ ``` STICKY = 'sticky' ``` #### `` TOAST `class-attribute` `instance-attribute` ⚓︎ ``` TOAST = 'toast' ``` ### `` EnvelopeAuthorType ⚓︎ The enumeration contains possible author types. ### Source trueconf.com/docs/chatbot-connector/en/objects/#envelopeauthortypeenum #### `` SYSTEM `class-attribute` `instance-attribute` ⚓︎ ``` SYSTEM = 0 ``` #### `` USER `class-attribute` `instance-attribute` ⚓︎ ``` USER = 1 ``` ### `` FileReadyState ⚓︎ This enumeration is used to indicate the status of a file on the server. ### Source trueconf.com/docs/chatbot-connector/en/objects/#filereadystateenum #### `` NOT_AVAILABLE `class-attribute` `instance-attribute` ⚓︎ ``` NOT_AVAILABLE = 0 ``` #### `` READY `class-attribute` `instance-attribute` ⚓︎ ``` READY = 2 ``` #### `` UPLOADING `class-attribute` `instance-attribute` ⚓︎ ``` UPLOADING = 1 ``` ### `` IncomingUpdateMethod ⚓︎ #### `` ADDED_CHAT_PARTICIPANT `class-attribute` `instance-attribute` ⚓︎ ``` ADDED_CHAT_PARTICIPANT = 'addChatParticipant' ``` #### `` CHANGED_FILE_UPLOAD_LIMITS `class-attribute` `instance-attribute` ⚓︎ ``` CHANGED_FILE_UPLOAD_LIMITS = 'getFileUploadLimits' ``` #### `` CHANGED_PARTICIPANT_ROLE `class-attribute` `instance-attribute` ⚓︎ ``` CHANGED_PARTICIPANT_ROLE = 'changeParticipantRole' ``` #### `` CLEARED_CHAT_HISTORY `class-attribute` `instance-attribute` ⚓︎ ``` CLEARED_CHAT_HISTORY = 'clearHistory' ``` #### `` COMMAND `class-attribute` `instance-attribute` ⚓︎ ``` COMMAND = 'command' ``` #### `` CREATED_CHANNEL `class-attribute` `instance-attribute` ⚓︎ ``` CREATED_CHANNEL = 'createChannel' ``` #### `` CREATED_FAVORITES_CHAT `class-attribute` `instance-attribute` ⚓︎ ``` CREATED_FAVORITES_CHAT = 'createFavoritesChat' ``` #### `` CREATED_GROUP_CHAT `class-attribute` `instance-attribute` ⚓︎ ``` CREATED_GROUP_CHAT = 'createGroupChat' ``` #### `` CREATED_PERSONAL_CHAT `class-attribute` `instance-attribute` ⚓︎ ``` CREATED_PERSONAL_CHAT = 'createP2PChat' ``` #### `` EDITED_CHAT_AVATAR `class-attribute` `instance-attribute` ⚓︎ ``` EDITED_CHAT_AVATAR = 'editChatAvatar' ``` #### `` EDITED_CHAT_TITLE `class-attribute` `instance-attribute` ⚓︎ ``` EDITED_CHAT_TITLE = 'editChatTitle' ``` #### `` EDITED_MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` EDITED_MESSAGE = 'editMessage' ``` #### `` MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` MESSAGE = 'sendMessage' ``` #### `` REMOVED_CHAT `class-attribute` `instance-attribute` ⚓︎ ``` REMOVED_CHAT = 'removeChat' ``` #### `` REMOVED_CHAT_PARTICIPANT `class-attribute` `instance-attribute` ⚓︎ ``` REMOVED_CHAT_PARTICIPANT = 'removeChatParticipant' ``` #### `` REMOVED_MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` REMOVED_MESSAGE = 'removeMessage' ``` #### `` UPLOADING_PROGRESS `class-attribute` `instance-attribute` ⚓︎ ``` UPLOADING_PROGRESS = 'uploadFileProgress' ``` ### `` MessageType ⚓︎ The enumeration contains the message type. ### Source trueconf.com/docs/chatbot-connector/en/objects/#envelopetypeenum #### `` ADD_PARTICIPANT `class-attribute` `instance-attribute` ⚓︎ ``` ADD_PARTICIPANT = 1 ``` #### `` ATTACHMENT `class-attribute` `instance-attribute` ⚓︎ ``` ATTACHMENT = 202 ``` #### `` CLEAR_CHAT_HISTORY `class-attribute` `instance-attribute` ⚓︎ ``` CLEAR_CHAT_HISTORY = 23 ``` #### `` EDIT_CHAT_AVATAR `class-attribute` `instance-attribute` ⚓︎ ``` EDIT_CHAT_AVATAR = 22 ``` #### `` EDIT_CHAT_TITLE `class-attribute` `instance-attribute` ⚓︎ ``` EDIT_CHAT_TITLE = 21 ``` #### `` FORWARDED_MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` FORWARDED_MESSAGE = 201 ``` #### `` LOCATION `class-attribute` `instance-attribute` ⚓︎ ``` LOCATION = 203 ``` #### `` PARTICIPANT_ROLE `class-attribute` `instance-attribute` ⚓︎ ``` PARTICIPANT_ROLE = 110 ``` #### `` PLAIN_MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` PLAIN_MESSAGE = 200 ``` #### `` REMOVE_PARTICIPANT `class-attribute` `instance-attribute` ⚓︎ ``` REMOVE_PARTICIPANT = 2 ``` #### `` SURVEY `class-attribute` `instance-attribute` ⚓︎ ``` SURVEY = 204 ``` #### `` VOICE_MESSAGE `class-attribute` `instance-attribute` ⚓︎ ``` VOICE_MESSAGE = 205 ``` ### `` OAuthError ⚓︎ Error codes, according to the OAuth 2.0 specification, are presented as ASCII strings from the list specified in the specification. ### Source trueconf.com/docs/chatbot-connector/en/objects/#oauth-error #### `` INVALID_CLIENT `class-attribute` `instance-attribute` ⚓︎ ``` INVALID_CLIENT = 'invalid_client' ``` #### `` INVALID_GRANT `class-attribute` `instance-attribute` ⚓︎ ``` INVALID_GRANT = 'invalid_grant' ``` #### `` INVALID_REQUEST `class-attribute` `instance-attribute` ⚓︎ ``` INVALID_REQUEST = 'invalid_request' ``` #### `` UNSUPORTED_GRANT_TYPE `class-attribute` `instance-attribute` ⚓︎ ``` UNSUPORTED_GRANT_TYPE = 'unsupported_grant_type' ``` ### `` ParseMode ⚓︎ Formatting options ### Source trueconf.com/docs/chatbot-connector/en/messages/#message-formatting #### `` HTML `class-attribute` `instance-attribute` ⚓︎ ``` HTML = 'html' ``` #### `` MARKDOWN `class-attribute` `instance-attribute` ⚓︎ ``` MARKDOWN = 'markdown' ``` #### `` TEXT `class-attribute` `instance-attribute` ⚓︎ ``` TEXT = 'text' ``` ### `` SurveyType ⚓︎ #### `` ANONYMOUS `class-attribute` `instance-attribute` ⚓︎ ``` ANONYMOUS = '{{Anonymous survey}}' ``` #### `` NON_ANONYMOUS `class-attribute` `instance-attribute` ⚓︎ ``` NON_ANONYMOUS = '{{Survey}}' ``` ### `` UpdateType ⚓︎ There are three types of messages. Only REQUEST and RESPONSE are applicable. ### Source trueconf.com/docs/chatbot-connector/en/objects/#message-type #### `` REQUEST `class-attribute` `instance-attribute` ⚓︎ ``` REQUEST = 1 ``` #### `` RESERVED `class-attribute` `instance-attribute` ⚓︎ ``` RESERVED = 0 ``` #### `` RESPONSE `class-attribute` `instance-attribute` ⚓︎ ``` RESPONSE = 2 ``` June 30, 2026 September 3, 2025 --- # DOCUMENT: Types ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Types.md # Types⚓︎ You can import all types at once: ``` from trueconf.types import * ``` ## `` trueconf.types.AddedChatParticipant `dataclass` ⚓︎ ``` AddedChatParticipant(timestamp, chat_id, user_id, added_by) ``` Event type: a new participant was added to a chat. This object is received in the handler when a user is added to a personal chat, group chat, channel, or conference chat. ### Notes This class is used as the event type in handler functions decorated with `@.added_chat_participant()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#addedChatParticipant Attributes: | Name | Type | Description | | --- | --- | --- | | `` timestamp `instance-attribute` (`trueconf.types.AddedChatParticipant.timestamp`)' href=#trueconf.types.AddedChatParticipant.timestamp>timestamp | `int` | Unix timestamp (milliseconds) of when the event occurred. | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.AddedChatParticipant.chat_id`)' href=#trueconf.types.AddedChatParticipant.chat_id>chat_id | `str` | Unique identifier of the chat where the participant was added. | | `` user_id `class-attribute` `instance-attribute` (`trueconf.types.AddedChatParticipant.user_id`)' href=#trueconf.types.AddedChatParticipant.user_id>user_id | `str` | TrueConf ID of the participant who was added. | | `` added_by `class-attribute` `instance-attribute` (`trueconf.types.AddedChatParticipant.added_by`)' href=#trueconf.types.AddedChatParticipant.added_by>added_by | `EnvelopeAuthor` | Information about the user who added the participant. | Examples: ``` from trueconf.types import AddedChatParticipant @.added_chat_participant() async def on_added(event: AddedChatParticipant): print(event.user_id) ``` ### `` added_by `class-attribute` `instance-attribute` ⚓︎ ``` added_by = field(metadata={'alias': 'addedBy'}) ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` timestamp `instance-attribute` ⚓︎ ``` timestamp ``` ### `` user_id `class-attribute` `instance-attribute` ⚓︎ ``` user_id = field(metadata={'alias': 'userId'}) ``` ## `` trueconf.types.ChangedParticipantRole `dataclass` ⚓︎ ``` ChangedParticipantRole(timestamp, role, chat_id, user_id) ``` Event type: a participant's role was changed in a chat. This object is received in the handler when a participant's role is changed in a personal chat, group chat, channel, or conference chat. ### Notes This class is used as the event type in handler functions decorated with `@.changed_chat_participant_role()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#changedParticipantRole Attributes: | Name | Type | Description | | --- | --- | --- | | `` timestamp `instance-attribute` (`trueconf.types.ChangedParticipantRole.timestamp`)' href=#trueconf.types.ChangedParticipantRole.timestamp>timestamp | `int` | Unix timestamp (in milliseconds) when the role change occurred. | | `` role `instance-attribute` (`trueconf.types.ChangedParticipantRole.role`)' href=#trueconf.types.ChangedParticipantRole.role>role | `str` | New role assigned to the participant. | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.ChangedParticipantRole.chat_id`)' href=#trueconf.types.ChangedParticipantRole.chat_id>chat_id | `str` | Identifier of the chat where the role change occurred. | | `` user_id `class-attribute` `instance-attribute` (`trueconf.types.ChangedParticipantRole.user_id`)' href=#trueconf.types.ChangedParticipantRole.user_id>user_id | `str` | TrueConf ID of the participant whose role was changed. | ### Example ``` from trueconf.types import ChangedParticipantRole @router.changed_chat_participant_role() async def on_role_changed(event: ChangedParticipantRole): print(f"User {event.user_id} now has role {event.role} in chat {event.chat_id}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` role `instance-attribute` ⚓︎ ``` role ``` ### `` timestamp `instance-attribute` ⚓︎ ``` timestamp ``` ### `` user_id `class-attribute` `instance-attribute` ⚓︎ ``` user_id = field(metadata={'alias': 'userId'}) ``` ## `` trueconf.types.CreatedChannel `dataclass` ⚓︎ ``` CreatedChannel( chat_id, title, chat_type, last_message, unread_messages ) ``` Event type: a new channel chat was created. This object is received in the handler when a channel is created in TrueConf. ### Notes This class is used as the event type in handler functions decorated with `@.created_channel()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createdChannel Attributes: | Name | Type | Description | | --- | --- | --- | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.CreatedChannel.chat_id`)' href=#trueconf.types.CreatedChannel.chat_id>chat_id | `str` | Unique identifier of the created channel. | | `` title `instance-attribute` (`trueconf.types.CreatedChannel.title`)' href=#trueconf.types.CreatedChannel.title>title | `str` | Title of the channel. | | `` chat_type `class-attribute` `instance-attribute` (`trueconf.types.CreatedChannel.chat_type`)' href=#trueconf.types.CreatedChannel.chat_type>chat_type | `` ChatType (`trueconf.enums.chat_type.ChatType`)' href=../Enums/#trueconf.enums.ChatType>ChatType | Type of the chat (should be `channel`). | | `` last_message `class-attribute` `instance-attribute` (`trueconf.types.CreatedChannel.last_message`)' href=#trueconf.types.CreatedChannel.last_message>last_message | `LastMessage | None` | The last message in the channel, if available. | | `` unread_messages `class-attribute` `instance-attribute` (`trueconf.types.CreatedChannel.unread_messages`)' href=#trueconf.types.CreatedChannel.unread_messages>unread_messages | `int` | Number of unread messages in the channel. | Examples: ``` from trueconf.types import CreatedChannel @.created_channel() async def on_created(event: CreatedChannel): print(f"Channel {event.title} created with id {event.chat_id}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` chat_type `class-attribute` `instance-attribute` ⚓︎ ``` chat_type = field(metadata={'alias': 'chatType'}) ``` ### `` last_message `class-attribute` `instance-attribute` ⚓︎ ``` last_message = field(metadata={'alias': 'lastMessage'}) ``` ### `` title `instance-attribute` ⚓︎ ``` title ``` ### `` unread_messages `class-attribute` `instance-attribute` ⚓︎ ``` unread_messages = field( metadata={"alias": "unreadMessages"} ) ``` ## `` trueconf.types.CreatedGroupChat `dataclass` ⚓︎ ``` CreatedGroupChat( chat_id, title, chat_type, last_message, unread_messages ) ``` Event type: a new group chat was created. This object is received in the handler when a group chat is created in TrueConf. ### Notes This class is used as the event type in handler functions decorated with `@.created_group_chat()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createdGroupChat Attributes: | Name | Type | Description | | --- | --- | --- | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.CreatedGroupChat.chat_id`)' href=#trueconf.types.CreatedGroupChat.chat_id>chat_id | `str` | Unique identifier of the group chat. | | `` title `instance-attribute` (`trueconf.types.CreatedGroupChat.title`)' href=#trueconf.types.CreatedGroupChat.title>title | `str` | Title of the group chat. | | `` chat_type `class-attribute` `instance-attribute` (`trueconf.types.CreatedGroupChat.chat_type`)' href=#trueconf.types.CreatedGroupChat.chat_type>chat_type | `` ChatType (`trueconf.enums.chat_type.ChatType`)' href=../Enums/#trueconf.enums.ChatType>ChatType | Type of the chat (should be `group`). | | `` last_message `class-attribute` `instance-attribute` (`trueconf.types.CreatedGroupChat.last_message`)' href=#trueconf.types.CreatedGroupChat.last_message>last_message | `LastMessage | None` | The last message in the chat, if available. | | `` unread_messages `class-attribute` `instance-attribute` (`trueconf.types.CreatedGroupChat.unread_messages`)' href=#trueconf.types.CreatedGroupChat.unread_messages>unread_messages | `int` | Number of unread messages in the group chat. | Examples: ``` from trueconf.types import CreatedGroupChat @.created_group_chat() async def on_created(event: CreatedGroupChat): print(f"Group chat {event.title} created with id {event.chat_id}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` chat_type `class-attribute` `instance-attribute` ⚓︎ ``` chat_type = field(metadata={'alias': 'chatType'}) ``` ### `` last_message `class-attribute` `instance-attribute` ⚓︎ ``` last_message = field(metadata={'alias': 'lastMessage'}) ``` ### `` title `instance-attribute` ⚓︎ ``` title ``` ### `` unread_messages `class-attribute` `instance-attribute` ⚓︎ ``` unread_messages = field( metadata={"alias": "unreadMessages"} ) ``` ## `` trueconf.types.CreatedPersonalChat `dataclass` ⚓︎ ``` CreatedPersonalChat( chat_id, title, chat_type, last_message, unread_messages ) ``` Event type: a new personal chat was created. This object is received in the handler when a personal chat is created in TrueConf. ### Notes This class is used as the event type in handler functions decorated with `@.created_personal_chat()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#createdP2PChat Attributes: | Name | Type | Description | | --- | --- | --- | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.CreatedPersonalChat.chat_id`)' href=#trueconf.types.CreatedPersonalChat.chat_id>chat_id | `str` | Unique identifier of the personal chat. | | `` title `instance-attribute` (`trueconf.types.CreatedPersonalChat.title`)' href=#trueconf.types.CreatedPersonalChat.title>title | `str` | Title of the chat (usually the participant’s name). | | `` chat_type `class-attribute` `instance-attribute` (`trueconf.types.CreatedPersonalChat.chat_type`)' href=#trueconf.types.CreatedPersonalChat.chat_type>chat_type | `` ChatType (`trueconf.enums.chat_type.ChatType`)' href=../Enums/#trueconf.enums.ChatType>ChatType | Type of the chat (should be `p2p`). | | `` last_message `class-attribute` `instance-attribute` (`trueconf.types.CreatedPersonalChat.last_message`)' href=#trueconf.types.CreatedPersonalChat.last_message>last_message | `LastMessage | None` | The last message in the chat, if available. | | `` unread_messages `class-attribute` `instance-attribute` (`trueconf.types.CreatedPersonalChat.unread_messages`)' href=#trueconf.types.CreatedPersonalChat.unread_messages>unread_messages | `int` | Number of unread messages in the personal chat. | Examples: ``` from trueconf.types import CreatedPersonalChat @.created_personal_chat() async def on_created(event: CreatedPersonalChat): print(f"Personal chat created with id {event.chat_id}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` chat_type `class-attribute` `instance-attribute` ⚓︎ ``` chat_type = field(metadata={'alias': 'chatType'}) ``` ### `` last_message `class-attribute` `instance-attribute` ⚓︎ ``` last_message = field(metadata={'alias': 'lastMessage'}) ``` ### `` title `instance-attribute` ⚓︎ ``` title ``` ### `` unread_messages `class-attribute` `instance-attribute` ⚓︎ ``` unread_messages = field( metadata={"alias": "unreadMessages"} ) ``` ## `` trueconf.types.EditedMessage `dataclass` ⚓︎ ``` EditedMessage(timestamp, content, chat_id) ``` Event type: a message was edited. This object is received in the handler when a previously sent message is edited in a chat. ### Notes This class is used as the event type in handler functions decorated with `@.edited_message()`. ### Source trueconf.com/docs/chatbot-connector/en/messages/#editMessage Attributes: | Name | Type | Description | | --- | --- | --- | | `` timestamp `instance-attribute` (`trueconf.types.EditedMessage.timestamp`)' href=#trueconf.types.EditedMessage.timestamp>timestamp | `int` | Unix timestamp (milliseconds) of when the edit occurred. | | `` content `instance-attribute` (`trueconf.types.EditedMessage.content`)' href=#trueconf.types.EditedMessage.content>content | `TextContent` | The updated content of the edited message. | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.EditedMessage.chat_id`)' href=#trueconf.types.EditedMessage.chat_id>chat_id | `str` | Unique identifier of the chat where the message was edited. | Examples: ``` from trueconf.types import EditedMessage @.edited_message() async def on_edited(event: EditedMessage): print(f"Message in chat {event.chat_id} was edited: {event.content.text}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` content `instance-attribute` ⚓︎ ``` content ``` ### `` timestamp `instance-attribute` ⚓︎ ``` timestamp ``` ## `` trueconf.types.InputFile ⚓︎ ``` InputFile(file_name=None, file_size=None, mime_type=None) ``` Base abstract class representing uploadable files. This class defines a common interface for all file types that can be uploaded to the TrueConf Server. It should not be used directly. Instead, use one of its subclasses: - `BufferedInputFile` — for in-memory byte data - `FSInputFile` — for files from the local filesystem - `URLInputFile` — for downloading files from a URL Each subclass implements the `read()` and `clone()` methods required for asynchronous uploads and reusability of the same file object. ### Source trueconf.com/docs/chatbot-connector/en/files/#upload-file-to-server-storage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file_name` | `str` | Name of the file to display when sending. | `None` | | `file_size` | `int | None` | File size in bytes (optional). | `None` | | `mime_type` | `str | None` | MIME type of the file. Can be detected automatically. | `None` | ### Abstract Methods read(): Asynchronously reads the file content. clone(): Creates a new copy of the file object. Useful for reuse (e.g., preview uploads). ### Example ``` file = FSInputFile("example.pdf") await bot.send_document(chat_id="...", file=file) ``` ### `` extension `instance-attribute` ⚓︎ ``` extension = ( Path(file_name).suffix.lower()[1:] if file_name else "" ) ``` ### `` file_name `instance-attribute` ⚓︎ ``` file_name = file_name ``` ### `` file_size `instance-attribute` ⚓︎ ``` file_size = file_size ``` ### `` mime_type `instance-attribute` ⚓︎ ``` mime_type = mime_type ``` ### `` clone `abstractmethod` ⚓︎ ``` clone() ``` ### `` read `abstractmethod` `async` ⚓︎ ``` read() ``` ## `` trueconf.types.BufferedInputFile ⚓︎ ``` BufferedInputFile( file, file_name=None, file_size=None, mime_type=None, **kwargs, ) ``` Represents a file uploaded from a bytes buffer. This class is useful when the file is already available as a `bytes` object, for example, if it was retrieved from a database, memory, or downloaded from an external source. Automatically detects MIME type and file size if not provided. ### Example ``` file = BufferedInputFile(file=data_bytes, file_name="example.txt") await bot.send_document(chat_id="...", file=file) ``` ### Note Use `BufferedInputFile.from_file(...)` for convenient file loading from disk. Initializes a file from a bytes buffer. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `bytes` | Raw file content in bytes. | required | | `file_name` | `str` | The name of the file. | `None` | | `file_size` | `int` | Size of the file in bytes. Auto-detected if not specified. | `None` | | `mime_type` | `str` | MIME type of the file. Auto-detected if not specified. | `None` | ### `` data `instance-attribute` ⚓︎ ``` data = file ``` ### `` extension `instance-attribute` ⚓︎ ``` extension = ( Path(file_name).suffix.lower()[1:] if file_name else "" ) ``` ### `` file_name `instance-attribute` ⚓︎ ``` file_name = file_name ``` ### `` file_size `instance-attribute` ⚓︎ ``` file_size = file_size ``` ### `` mime_type `instance-attribute` ⚓︎ ``` mime_type = mime_type ``` ### `` clone ⚓︎ ``` clone() ``` Creates a clone of the current file object. This method is useful when the same file needs to be reused (e.g., as a preview), while keeping the original instance intact. Returns: | Name | Type | Description | | --- | --- | --- | | `BufferedInputFile` | `` trueconf.types.BufferedInputFile (`trueconf.types.input_file.BufferedInputFile`)' href=#trueconf.types.BufferedInputFile>BufferedInputFile | A new instance with identical content. | ### `` from_file `classmethod` ⚓︎ ``` from_file( path, file_name=None, file_size=None, mime_type=None, **kwargs, ) ``` Creates a `BufferedInputFile` from a file on disk. This is a convenient way to load a file into memory if it needs to be reused or processed before sending. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `path` | `str | Path` | Path to the local file. | required | | `file_name` | `str` | File name to propagate. Defaults to the name extracted from path. | `None` | | `file_size` | `int` | File size in bytes. Auto-detected if not specified. | `None` | | `mime_type` | `str` | MIME type of the file. Auto-detected if not specified. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `BufferedInputFile` | `` trueconf.types.BufferedInputFile (`trueconf.types.input_file.BufferedInputFile`)' href=#trueconf.types.BufferedInputFile>BufferedInputFile | A new instance ready for upload. | ### `` read `async` ⚓︎ ``` read() ``` Asynchronously returns the file content as a `BytesIO` stream. Returns: | Name | Type | Description | | --- | --- | --- | | `BytesIO` | | A stream containing the file content. | ## `` trueconf.types.FSInputFile ⚓︎ ``` FSInputFile( path, file_name=None, file_size=None, mime_type=None, **kwargs, ) ``` Represents a file uploaded from the local filesystem. Used for uploading documents, images, or any other files directly from disk. Automatically detects the file name, size, and MIME type when not explicitly provided. ### Example ``` file = FSInputFile("path/to/file.zip") await bot.send_document(chat_id="...", file=file) ``` Initializes an `FSInputFile` instance from a local file. If not provided, `file_name`, `file_size`, and `mime_type` are automatically detected: - `file_name` is extracted from the file path. - `file_size` is determined via `os.path.getsize()`. - `mime_type` is detected from the first 2048 bytes of the file content (using `python-magic` if available). Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `path` | `str | Path` | Path to the local file. | required | | `file_name` | `str` | File name to be propagated in the upload. | `None` | | `file_size` | `int` | File size in bytes. | `None` | | `mime_type` | `str` | File MIME type. | `None` | ### `` extension `instance-attribute` ⚓︎ ``` extension = ( Path(file_name).suffix.lower()[1:] if file_name else "" ) ``` ### `` file_name `instance-attribute` ⚓︎ ``` file_name = file_name ``` ### `` file_size `instance-attribute` ⚓︎ ``` file_size = file_size ``` ### `` mime_type `instance-attribute` ⚓︎ ``` mime_type = mime_type ``` ### `` path `instance-attribute` ⚓︎ ``` path = path ``` ### `` clone ⚓︎ ``` clone() ``` Creates a clone of the current `FSInputFile` instance. Useful when the same file needs to be reused, for example, when sending preview images. The cloned object retains the same path, name, size, and MIME type but is a separate instance in memory. Returns: | Name | Type | Description | | --- | --- | --- | | `FSInputFile` | `` trueconf.types.FSInputFile (`trueconf.types.input_file.FSInputFile`)' href=#trueconf.types.FSInputFile>FSInputFile | A new instance of `FSInputFile` with identical properties. | ### `` read `async` ⚓︎ ``` read() ``` Asynchronously reads the file content from the local filesystem. Returns: | Name | Type | Description | | --- | --- | --- | | `bytes` | | The file content as raw bytes. | ## `` trueconf.types.URLInputFile ⚓︎ ``` URLInputFile( url, headers=None, file_name=None, file_size=None, mime_type=None, timeout=30, verify_ssl=True, **kwargs, ) ``` Represents a file to be downloaded and uploaded from a remote URL. Used for uploading files from external sources (e.g., public file links, APIs). Automatically handles MIME type detection and file size parsing from HTTP headers. ### Example ``` file = URLInputFile("https://example.com/file.pdf") await bot.send_document(chat_id="...", file=file) ``` Initializes a `URLInputFile` instance from a remote URL. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `url` | `str` | URL of the file to download. | required | | `headers` | `Optional[Dict[str, Any]]` | Optional HTTP headers for the request. | `None` | | `file_name` | `str` | Optional file name to propagate in the upload. | `None` | | `file_size` | `int` | Optional file size in bytes. | `None` | | `mime_type` | `str` | Optional MIME type of the file. | `None` | | `timeout` | `int` | Timeout (in seconds) for the HTTP request. | `30` | ### `` extension `instance-attribute` ⚓︎ ``` extension = ( Path(file_name).suffix.lower()[1:] if file_name else "" ) ``` ### `` file_name `instance-attribute` ⚓︎ ``` file_name = file_name ``` ### `` file_size `instance-attribute` ⚓︎ ``` file_size = file_size ``` ### `` headers `instance-attribute` ⚓︎ ``` headers = headers ``` ### `` mime_type `instance-attribute` ⚓︎ ``` mime_type = mime_type ``` ### `` timeout `instance-attribute` ⚓︎ ``` timeout = timeout ``` ### `` url `instance-attribute` ⚓︎ ``` url = url ``` ### `` verify_ssl `instance-attribute` ⚓︎ ``` verify_ssl = verify_ssl ``` ### `` clone ⚓︎ ``` clone() ``` Creates a clone of the current `URLInputFile` instance. Useful when the same file needs to be reused (e.g., sending a preview). The cloned object retains the same URL, headers, and metadata, and shares the already downloaded content: no second download is performed. Returns: | Name | Type | Description | | --- | --- | --- | | `URLInputFile` | `` trueconf.types.URLInputFile (`trueconf.types.input_file.URLInputFile`)' href=#trueconf.types.URLInputFile>URLInputFile | A new instance with identical parameters. | ### `` prepare `async` ⚓︎ ``` prepare() ``` Prepares file metadata from HTTP response headers without downloading the body. Sends a streaming GET request and reads only the response headers: - MIME type from the `Content-Type` header. - File name from the `Content-Disposition` header or URL path. - File size from the `Content-Length` header. ### Note `Content-Length` is only an estimate for dynamic sources (e.g. a camera snapshot endpoint returns a new image per request). The authoritative `file_size` is set by `read()` from the actual downloaded bytes. Raises: | Type | Description | | --- | --- | | `HTTPStatusError` | If the server responds with an error status code. | | `` FileUploadError (`trueconf.exceptions.FileUploadError`)' href=../Exceptions/#trueconf.exceptions.FileUploadError>FileUploadError | If the file name cannot be resolved from the `Content-Disposition` header or the URL path. | ### `` read `async` ⚓︎ ``` read(max_size=None) ``` Downloads the file content from the remote URL. The content is downloaded once and cached: repeated calls (and calls on clones) return the same bytes. After a successful download `file_size` is set to the actual size of the downloaded body, so the size declared to the server always matches the uploaded content — even for sources that return a new file per request. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `max_size` | `int | None` | Optional download limit in bytes. If the accumulated content exceeds it, the download is aborted and `FileSizeTooLargeError` is raised. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `bytes` | | File content. | Raises: | Type | Description | | --- | --- | | `HTTPStatusError` | If the server responds with an error status code. | | `` FileSizeTooLargeError (`trueconf.exceptions.FileSizeTooLargeError`)' href=../Exceptions/#trueconf.exceptions.FileSizeTooLargeError>FileSizeTooLargeError | If the content exceeds `max_size`. | ## `` trueconf.types.Message `dataclass` ⚓︎ ``` Message( *, chat, timestamp, type, author, box=None, content, message_id, is_edited, reply_message_id=None, reply_message=None, ) ``` Represents a single chat message within TrueConf Chatbot Connector. The `Message` object is automatically created for each incoming update and contains metadata (author, chat, timestamp, type) along with the actual message content. It also provides helper properties and shortcut methods to interact with the message (e.g., replying, forwarding, deleting, sending media files). ### Source trueconf.com/docs/chatbot-connector/en/messages/#sendMessage Attributes: | Name | Type | Description | | --- | --- | --- | | `` timestamp `instance-attribute` (`trueconf.types.Message.timestamp`)' href=#trueconf.types.Message.timestamp>timestamp | `int` | Unix timestamp of the message. | | `` type `instance-attribute` (`trueconf.types.Message.type`)' href=#trueconf.types.Message.type>type | `` MessageType (`trueconf.enums.message_type.MessageType`)' href=../Enums/#trueconf.enums.MessageType>MessageType | Type of the message (e.g., TEXT, ATTACHMENT). | | `` author `instance-attribute` (`trueconf.types.Message.author`)' href=#trueconf.types.Message.author>author | `EnvelopeAuthor` | Information about the user who sent the message. | | `` box `class-attribute` `instance-attribute` (`trueconf.types.Message.box`)' href=#trueconf.types.Message.box>box | `EnvelopeBox` | Information about the chat (box) where the message was sent. | | `` content `class-attribute` `instance-attribute` (`trueconf.types.Message.content`)' href=#trueconf.types.Message.content>content | `UserMessageContent` | The message content, selected from the user-message models according to `type`. | | `` chat `instance-attribute` (`trueconf.types.Message.chat`)' href=#trueconf.types.Message.chat>chat | `` trueconf.types.Chat `dataclass` (`trueconf.types.chat.Chat`)' href=#trueconf.types.Chat>Chat | The chat this message belongs to. | | `` message_id `class-attribute` `instance-attribute` (`trueconf.types.Message.message_id`)' href=#trueconf.types.Message.message_id>message_id | `str` | Unique identifier of the message. | | `` chat_id `property` (`trueconf.types.Message.chat_id`)' href=#trueconf.types.Message.chat_id>chat_id | `str` | .. deprecated:: Use :attr:`chat.chat_id` instead. | | `` is_edited `class-attribute` `instance-attribute` (`trueconf.types.Message.is_edited`)' href=#trueconf.types.Message.is_edited>is_edited | `bool` | Indicates whether the message was edited. | | `` reply_message_id `class-attribute` `instance-attribute` (`trueconf.types.Message.reply_message_id`)' href=#trueconf.types.Message.reply_message_id>reply_message_id | `Optional[str]` | Identifier of the message this one replies to. | | `` reply_message `class-attribute` `instance-attribute` (`trueconf.types.Message.reply_message`)' href=#trueconf.types.Message.reply_message>reply_message | `Optional[` trueconf.types.Message `dataclass` (`trueconf.types.message.Message`)' href=#trueconf.types.Message>Message] | Full message this one replies to. The server expands only the directly referenced message: if that message is also a reply, its `reply_message_id` is available but its `reply_message` remains `None`. Use `Bot.get_message_by_id()` to load the next message in the reply chain. | | `` from_user `property` (`trueconf.types.Message.from_user`)' href=#trueconf.types.Message.from_user>from_user | `EnvelopeAuthor` | Shortcut for accessing the message author. | | `` content_type `property` (`trueconf.types.Message.content_type`)' href=#trueconf.types.Message.content_type>content_type | `` MessageType (`trueconf.enums.message_type.MessageType`)' href=../Enums/#trueconf.enums.MessageType>MessageType | Returns the type of the message. | | `` text `property` (`trueconf.types.Message.text`)' href=#trueconf.types.Message.text>text | `Optional[str]` | Returns the message text if it contains text, else None. | | `` quote `property` (`trueconf.types.Message.quote`)' href=#trueconf.types.Message.quote>quote | `Optional[str]` | Returns the quoted part of the replied message extracted from the `` block, else None. | | `` mention `property` (`trueconf.types.Message.mention`)' href=#trueconf.types.Message.mention>mention | `Optional[bool]` | Returns True if the message mentions the bot, else None. | | `` document `property` (`trueconf.types.Message.document`)' href=#trueconf.types.Message.document>document | `Optional[Document]` | Returns a document attachment if the message contains a non-media file (not photo, video, sticker). | | `` photo `property` (`trueconf.types.Message.photo`)' href=#trueconf.types.Message.photo>photo | `Optional[Photo]` | Returns a photo attachment if available. | | `` video `property` (`trueconf.types.Message.video`)' href=#trueconf.types.Message.video>video | `Optional[Video]` | Returns a video attachment if available. | | `` sticker `property` (`trueconf.types.Message.sticker`)' href=#trueconf.types.Message.sticker>sticker | `Optional[Sticker]` | Returns a sticker attachment if available. | | `` location `property` (`trueconf.types.Message.location`)' href=#trueconf.types.Message.location>location | `Optional[` trueconf.types.content.location.Location `dataclass` ' href=#trueconf.types.content.location.Location>Location] | Returns the location content if the message contains a geolocation, else None. | Methods: | Name | Description | | --- | --- | | `` answer `async` (`trueconf.types.Message.answer`)' href=#trueconf.types.Message.answer>answer | Sends a text message in the same chat. | | `` reply `async` (`trueconf.types.Message.reply`)' href=#trueconf.types.Message.reply>reply | Sends a reply message referencing the current one. | | `` forward `async` (`trueconf.types.Message.forward`)' href=#trueconf.types.Message.forward>forward | Forwards the current message to another chat. | | `` copy_to `async` (`trueconf.types.Message.copy_to`)' href=#trueconf.types.Message.copy_to>copy_to | Sends a copy of the current message (text-only). | | `` answer_photo `async` (`trueconf.types.Message.answer_photo`)' href=#trueconf.types.Message.answer_photo>answer_photo | Sends a photo to the current chat. | | `` answer_document `async` (`trueconf.types.Message.answer_document`)' href=#trueconf.types.Message.answer_document>answer_document | Sends a document to the current chat. | | `` answer_sticker `async` (`trueconf.types.Message.answer_sticker`)' href=#trueconf.types.Message.answer_sticker>answer_sticker | Sends a sticker to the current chat. | | `` delete `async` (`trueconf.types.Message.delete`)' href=#trueconf.types.Message.delete>delete | Deletes the current message from the chat. | ### `` author `instance-attribute` ⚓︎ ``` author ``` ### `` box `class-attribute` `instance-attribute` ⚓︎ ``` box = None ``` ### `` chat `instance-attribute` ⚓︎ ``` chat ``` ### `` chat_id `property` ⚓︎ ``` chat_id ``` ### `` content `class-attribute` `instance-attribute` ⚓︎ ``` content = field( metadata={ "deserialize": pass_through, "serialize": lambda value: value.to_dict(), } ) ``` ### `` content_type `property` ⚓︎ ``` content_type ``` Returns the type of the current message content. Returns: | Name | Type | Description | | --- | --- | --- | | `MessageType` | `` MessageType (`trueconf.enums.message_type.MessageType`)' href=../Enums/#trueconf.enums.MessageType>MessageType | Message content type (e.g., TEXT, ATTACHMENT). | ### `` document `property` ⚓︎ ``` document ``` Returns the attached document if the message contains a non-media file. Use this property only for documents that are not photos, videos, or stickers. For media attachments, use the corresponding properties: `photo`, `video`, or `sticker`. If you need to handle any attached file (including media), use `message.content` directly. Returns: | Type | Description | | --- | --- | | `Document | None` | Optional[Document]: Document attachment bound to the bot, or None if not applicable. | ### `` forwarded_message `property` ⚓︎ ``` forwarded_message ``` Returns the forwarded original message if this message is a forward. The server sends a forward as an `Envelope` of `type` 201 whose `content` is the `Envelope` of the forwarded original (without its `box`). That inner envelope is parsed into a `ForwardMessage`, which is a full `Message`, so all regular shortcuts (`text`, `voice`, `reply_message`, ...) work on it. Returns: | Type | Description | | --- | --- | | `` trueconf.types.Message `dataclass` (`trueconf.types.message.Message`)' href=#trueconf.types.Message>Message | None | Optional[Message]: The forwarded original message, or None if the | | `` trueconf.types.Message `dataclass` (`trueconf.types.message.Message`)' href=#trueconf.types.Message>Message | None | message is not a forward. | ### `` from_user `property` ⚓︎ ``` from_user ``` Returns the author of the current message. Returns: | Name | Type | Description | | --- | --- | --- | | `EnvelopeAuthor` | `EnvelopeAuthor` | Shortcut for accessing the message author. | ### `` is_edited `class-attribute` `instance-attribute` ⚓︎ ``` is_edited = field(metadata={'alias': 'isEdited'}) ``` ### `` location `property` ⚓︎ ``` location ``` Returns the location content if the current message contains a geolocation. Returns: | Type | Description | | --- | --- | | `` trueconf.types.content.location.Location `dataclass` ' href=#trueconf.types.content.location.Location>Location | None | Optional[Location]: The location object with latitude, longitude and title, or None if the message is not a location message. | ### `` mention `property` ⚓︎ ``` mention ``` Returns whether the current text message mentions the bot. The shortcut checks two supported mention formats: - `@all` — treated as a mention because it targets all chat participants. - TrueConf user mentions rendered as HTML links, for example `[John Doe](trueconf:john_doe@video.example.com)`. For user mentions, the extracted TrueConf ID is compared with `bot.me_id`. Returns: | Type | Description | | --- | --- | | `bool | None` | bool | None: `True` if the message mentions the bot, otherwise `None`. | ### `` message_id `class-attribute` `instance-attribute` ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` ### `` photo `property` ⚓︎ ``` photo ``` Returns the attached photo object if the current message contains an image. This is a shortcut for accessing photo metadata from image attachments. Returns: | Type | Description | | --- | --- | | `Photo | None` | Optional[Photo]: A `Photo` object bound to the bot, or None if the message does not contain an image. | ### `` quote `property` ⚓︎ ``` quote ``` Returns the quoted part of the replied message, if present. Extracts the content of the first `...` block from the message HTML text and unescapes HTML entities, so the returned value can be reused as the `quote` argument of `async` ' href=#trueconf.types.Message.reply>`Message.reply()` or `async` ' href=../Bot/#trueconf.Bot.send_message>`Bot.send_message()`. Returns: | Type | Description | | --- | --- | | `str | None` | Optional[str]: Quoted text, or None if the message has no quote block. | ### `` reply_message `class-attribute` `instance-attribute` ⚓︎ ``` reply_message = field( default=None, metadata={"alias": "replyMessage"} ) ``` ### `` reply_message_id `class-attribute` `instance-attribute` ⚓︎ ``` reply_message_id = field( default=None, metadata={"alias": "replyMessageId"} ) ``` ### `` sticker `property` ⚓︎ ``` sticker ``` Returns the attached sticker object if the current message contains a sticker. Returns: | Type | Description | | --- | --- | | `Sticker | None` | Optional[Sticker]: A `Sticker` object bound to the bot, or None if the message does not contain a sticker. | ### `` text `property` ⚓︎ ``` text ``` Returns the text of the current message if present. For a reply with a quote, the leading `...` block (and the following ` ` breaks) is stripped from the returned value; use :attr:`quote` to get the quoted fragment itself. Returns: | Type | Description | | --- | --- | | `str | None` | Optional[str]: Message text, or None if the message has no text content. | ### `` timestamp `instance-attribute` ⚓︎ ``` timestamp ``` ### `` type `instance-attribute` ⚓︎ ``` type ``` ### `` video `property` ⚓︎ ``` video ``` Returns the attached video object if the current message contains a video. This is a shortcut for accessing video metadata from video attachments. Returns: | Type | Description | | --- | --- | | `Video | None` | Optional[Video]: A `Video` object bound to the bot, or None if the message does not contain a video. | ### `` voice `property` ⚓︎ ``` voice ``` Returns the attached voice object if the current message contains a voice message. This is a shortcut for accessing video metadata from voice attachments. Returns: | Type | Description | | --- | --- | | `` trueconf.types.content.voice.Voice `dataclass` ' href=#trueconf.types.content.voice.Voice>Voice | None | Optional[Voice]: A `Voice` object bound to the bot, or None if the message does not contain a voice. | ### `` answer `async` ⚓︎ ``` answer(text, parse_mode= HTML class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.HTML)' href=../Enums/#trueconf.enums.ParseMode.HTML>HTML, *, buttons=None) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_message>`send_message` method of the bot instance. Use this method to send a text message to the current chat. ### Automatically fills the following attributes - `chat_id` ### Source trueconf.com/docs/chatbot-connector/en/messages/#sendMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `text` | `str` | Text of the message to be sent. | required | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode. Defaults to HTML. | `` HTML `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.HTML`)' href=../Enums/#trueconf.enums.ParseMode.HTML>HTML | Returns: | Name | Type | Description | | --- | --- | --- | | `SendMessageResponse` | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | Object containing the result of the message delivery. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer("Hi, there!") ``` ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer("Hi, **there!**", parse_mode=ParseMode.MARKDOWN) ``` ### `` answer_document `async` ⚓︎ ``` answer_document(file, caption=None, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_document>`send_document` method of the bot instance. Use this method to send a document in response to the current message. ### Automatically fills the following attributes - `chat_id` ### Source trueconf.com/docs/chatbot-connector/en/files/#working-with-files Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | The file to be uploaded. Must be a subclass of `InputFile`. | required | | `caption` | `str | None` | Optional caption text to be sent with the file. | `None` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode (e.g., Markdown, HTML, or plain text). | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | Object containing the result of the document upload. If the file was sent with a caption, `caption_message_id` contains the ID of the caption message. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer_document(file=FSInputFile("sticker.webp")) ``` ### `` answer_photo `async` ⚓︎ ``` answer_photo(file, preview, caption=None, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_photo>`send_photo` method of the bot instance. Use this method to send a photo in response to the current message. ### Automatically fills the following attributes - `chat_id` ### Source trueconf.com/docs/chatbot-connector/en/files/#sending-an-image Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | The photo file to upload. Must be a subclass of `InputFile`. | required | | `preview` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | None | Optional preview image. Must also be an `InputFile` if provided. | required | | `caption` | `str | None` | Optional caption to be sent along with the image. | `None` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Formatting mode for the caption (e.g., Markdown, HTML, plain text). | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | Object containing the result of the photo upload. If the photo was sent with a caption, `caption_message_id` contains the ID of the caption message. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer_photo(file=FSInputFile("sticker.webp"), preview=FSInputFile("sticker.webp")) ``` ### `` answer_sticker `async` ⚓︎ ``` answer_sticker(file) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_sticker>`send_sticker` method of the bot instance. Use this method to send a sticker in response to the current message. ### Automatically fills the following attributes - `chat_id` ### Source trueconf.com/docs/chatbot-connector/en/files/#upload-file-to-server-storage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | The sticker file in WebP format. Must be a subclass of `InputFile`. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | Object containing the result of the sticker delivery. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer_sticker(file=FSInputFile("sticker.webp")) ``` ### `` contact `async` ⚓︎ ``` contact() ``` Returns the contact of the current message, if any. The result is cached on the message, so a vCard file is downloaded from the server only once. Two formats are recognized: - A vCard attachment (`mimeType: text/vcard`). The file is downloaded from the server and parsed into a contact with the structured name (`N`), phone number (`TEL`) and the raw vCard text. - A TrueConf contact link, i.e. a text message whose entire content is exactly one `[Name](trueconf:login&do=profile)` link (the same markup `Message.mention` uses for user mentions). The display name is fetched from the server via `get_user_display_name`; if that fails (e.g. the user was deleted) the link text is used instead. `first_name` holds the whole display name and `last_name`/`phone_number` stay `None`. Returns: | Type | Description | | --- | --- | | `` trueconf.types.contact.Contact `dataclass` ' href=#trueconf.types.contact.Contact>Contact | None | Contact | None: The parsed contact, or None if the message is not | | `` trueconf.types.contact.Contact `dataclass` ' href=#trueconf.types.contact.Contact>Contact | None | a vCard attachment or a TrueConf contact link. | Examples: ``` >>> @.message() >>> async def on_message(message: Message): >>> contact = await message.contact >>> if contact is not None: >>> await message.answer(f"Phone: {contact.phone_number}") ``` ### `` copy_to `async` ⚓︎ ``` copy_to(chat_id) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_message>`send_message` method of the bot instance. Use this method to send a copy of the current message (without metadata or reply context) to another chat. ### Automatically fills the following attributes - `text` - `parse_mode` ### Source trueconf.com/docs/chatbot-connector/en/messages/#sendMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the target chat to send the copied message to. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `SendMessageResponse` | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | None | Object containing the result of the message delivery. | ### `` delete `async` ⚓︎ ``` delete(for_all=False) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.remove_message>`remove_message` method of the bot instance. Use this method to delete the current message from the chat. ### Automatically fills the following attributes - `message_id` ### Source trueconf.com/docs/chatbot-connector/en/messages/#removeMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `for_all` | `bool` | If True, delete the message for all participants. Defaults to False (deletes only for the bot). | `False` | Returns: | Name | Type | Description | | --- | --- | --- | | `RemoveMessageResponse` | `` RemoveMessageResponse (`trueconf.types.responses.remove_message_response.RemoveMessageResponse`)' href=../Responses/#trueconf.types.responses.RemoveMessageResponse>RemoveMessageResponse | Object containing the result of the message deletion. | ### `` forward `async` ⚓︎ ``` forward(chat_id) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.forward_message>`forward_message` method of the bot instance. Use this method to forward the current message to another chat. ### Automatically fills the following attributes - `message_id` ### Source trueconf.com/docs/chatbot-connector/en/messages/#forwardMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `chat_id` | `str` | Identifier of the target chat to forward the message to. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `ForwardMessageResponse` | `` ForwardMessageResponse (`trueconf.types.responses.forward_message_response.ForwardMessageResponse`)' href=../Responses/#trueconf.types.responses.ForwardMessageResponse>ForwardMessageResponse | Object containing the result of the message forwarding. | ### `` reply `async` ⚓︎ ``` reply(text, parse_mode= HTML class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.HTML)' href=../Enums/#trueconf.enums.ParseMode.HTML>HTML, *, buttons=None, quote=None) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_message>`send_message` method. Sends a reply to this message in the current chat. ### Automatically fills the following attributes - `chat_id`: Current chat identifier. - `reply_message_id`: ID of the current message. Source: trueconf.com/docs/chatbot-connector/en/messages/#replyMessage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `text` | `str` | Text of the reply message. | required | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode. Defaults to HTML. | `` HTML `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.HTML`)' href=../Enums/#trueconf.enums.ParseMode.HTML>HTML | | `quote` | `str` | Part of this message to highlight in the reply preview. Must be a substring of the message text; raises `ValueError` otherwise. The quote body follows the message `parse_mode`: HTML and plain text are wrapped into an HTML quote block (plain text is escaped, parse mode becomes HTML), while Markdown uses a `>quote` blockquote. | `None` | Returns: | Name | Type | Description | | --- | --- | --- | | `SendMessageResponse` | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | Object containing the result of the message delivery. | ### `` reply_document `async` ⚓︎ ``` reply_document(file, caption=None, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_document>`send_document` method of the bot instance. Sends a document as a reply to the current message in this chat. ### Automatically fills the following attributes - `chat_id`: Current chat identifier. - `reply_message_id`: ID of the current message. ### Source trueconf.com/docs/chatbot-connector/en/files/#working-with-files Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | The file to be uploaded. Must be a subclass of `InputFile`. | required | | `caption` | `str | None` | Optional caption text to be sent with the file. | `None` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Text formatting mode (e.g., Markdown, HTML, or plain text). | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | Object containing the result of the document upload. If the file was sent with a caption, `caption_message_id` contains the ID of the caption message. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer_document(file=FSInputFile("sticker.webp")) ``` ### `` reply_photo `async` ⚓︎ ``` reply_photo(file, preview, caption=None, parse_mode= TEXT class-attribute instance-attribute (trueconf.enums.parse_mode.ParseMode.TEXT)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_photo>`send_photo` method of the bot instance. Sends a photo as a reply to the current message in this chat. ### Automatically fills the following attributes - `chat_id`: Current chat identifier. - `reply_message_id`: ID of the current message. ### Source trueconf.com/docs/chatbot-connector/en/files/#sending-an-image Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | The photo file to upload. Must be a subclass of `InputFile`. | required | | `preview` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | None | Optional preview image. Must also be an `InputFile` if provided. | required | | `caption` | `str | None` | Optional caption to be sent along with the image. | `None` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | Formatting mode for the caption (e.g., Markdown, HTML, plain text). | `` TEXT `class-attribute` `instance-attribute` (`trueconf.enums.parse_mode.ParseMode.TEXT`)' href=../Enums/#trueconf.enums.ParseMode.TEXT>TEXT | | `reply_message_id` | `str | None` | Optional identifier of the message to which this message is a reply. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | Object containing the result of the photo upload. If the photo was sent with a caption, `caption_message_id` contains the ID of the caption message. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer_photo(file=FSInputFile("sticker.webp"), preview=FSInputFile("sticker.webp")) ``` ### `` reply_sticker `async` ⚓︎ ``` reply_sticker(file) ``` Shortcut for the `async` ' href=../Bot/#trueconf.Bot.send_sticker>`send_sticker` method of the bot instance. Sends a sticker as a reply to the current message in this chat. ### Automatically fills the following attributes - `chat_id`: Current chat identifier. - `reply_message_id`: ID of the current message. ### Source trueconf.com/docs/chatbot-connector/en/files/#upload-file-to-server-storage Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `file` | `` trueconf.types.InputFile (`trueconf.types.input_file.InputFile`)' href=#trueconf.types.InputFile>InputFile | The sticker file in WebP format. Must be a subclass of `InputFile`. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `SendFileResponse` | `` SendFileResponse (`trueconf.types.responses.send_file_response.SendFileResponse`)' href=../Responses/#trueconf.types.responses.SendFileResponse>SendFileResponse | Object containing the result of the sticker delivery. | Examples: ``` >>> @.message() >>> async def on_message(message:Message): >>> await message.answer_sticker(file=FSInputFile("sticker.webp")) ``` ### `` save_to_favorites `async` ⚓︎ ``` save_to_favorites(copy=False) ``` Saves the current message to the bot's "Favorites" chat. By default, the message is forwarded to the bot's personal Favorites chat. If `copy=True`, the message will be copied instead — only for text messages. Use this method to store important messages, logs, or media content in the bot’s private space. ### Notes - The Favorites chat is created automatically on first use. - `copy=True` only works for text messages and does not preserve metadata (like replies or sender info). - Non-text messages with `copy=True` will be ignored with a warning. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `copy` | `bool` | If True, copies the message instead of forwarding it. Defaults to False. | `False` | Returns: | Type | Description | | --- | --- | | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | ForwardMessageResponse | None | SendMessageResponse | ForwardMessageResponse | None: | | `` SendMessageResponse (`trueconf.types.responses.send_message_response.SendMessageResponse`)' href=../Responses/#trueconf.types.responses.SendMessageResponse>SendMessageResponse | ForwardMessageResponse | None | Result of sending or forwarding the message. Returns `None` if copying is not supported for the message type. | ### Example ``` @router.message() async def on_message(msg: Message): await msg.save_to_favorites() # forwards message await msg.save_to_favorites(copy=True) # copies if possible ``` ## `` trueconf.types.SystemMessage `dataclass` ⚓︎ ``` SystemMessage( chat, timestamp, type, author, box, content, message_id ) ``` A system Envelope recorded in chat history or received as a live message. ### `` author `instance-attribute` ⚓︎ ``` author ``` ### `` box `instance-attribute` ⚓︎ ``` box ``` ### `` chat `instance-attribute` ⚓︎ ``` chat ``` ### `` content `class-attribute` `instance-attribute` ⚓︎ ``` content = field(metadata={'deserialize': pass_through}) ``` ### `` message_id `class-attribute` `instance-attribute` ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` ### `` timestamp `instance-attribute` ⚓︎ ``` timestamp ``` ### `` type `instance-attribute` ⚓︎ ``` type ``` ## `` trueconf.types.RemovedChat `dataclass` ⚓︎ ``` RemovedChat(chat_id) ``` Event type: a chat was removed. This object is received in the handler when a private, group, channel, or conference chat is deleted. ### Notes This class is used as the event type in handler functions decorated with `@.removed_chat()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#removedChat Attributes: | Name | Type | Description | | --- | --- | --- | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.RemovedChat.chat_id`)' href=#trueconf.types.RemovedChat.chat_id>chat_id | `str` | Unique identifier of the chat that was removed. | Examples: ``` from trueconf.types import RemovedChat @.removed_chat() async def on_removed(event: RemovedChat): print(f"Chat removed: {event.chat_id}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ## `` trueconf.types.RemovedChatParticipant `dataclass` ⚓︎ ``` RemovedChatParticipant( timestamp, chat_id, user_id, removed_by ) ``` Event type: a participant was removed from a chat. This object is received in the handler when a user is removed from a group, channel, or conference chat. ### Notes This class is used as the event type in handler functions decorated with `@.removed_chat_participant()`. ### Source trueconf.com/docs/chatbot-connector/en/chats/#removedChatParticipant Attributes: | Name | Type | Description | | --- | --- | --- | | `` timestamp `instance-attribute` (`trueconf.types.RemovedChatParticipant.timestamp`)' href=#trueconf.types.RemovedChatParticipant.timestamp>timestamp | `int` | Unix timestamp (milliseconds) of when the event occurred. | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.RemovedChatParticipant.chat_id`)' href=#trueconf.types.RemovedChatParticipant.chat_id>chat_id | `str` | Unique identifier of the chat where the participant was removed. | | `` user_id `class-attribute` `instance-attribute` (`trueconf.types.RemovedChatParticipant.user_id`)' href=#trueconf.types.RemovedChatParticipant.user_id>user_id | `str` | TrueConf ID of the participant who was removed. | | `` removed_by `class-attribute` `instance-attribute` (`trueconf.types.RemovedChatParticipant.removed_by`)' href=#trueconf.types.RemovedChatParticipant.removed_by>removed_by | `EnvelopeAuthor` | Information about the user who removed the participant. | Examples: ``` from trueconf.types import RemovedChatParticipant @.removed_chat_participant() async def on_removed(event: RemovedChatParticipant): print(event.user_id) ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` removed_by `class-attribute` `instance-attribute` ⚓︎ ``` removed_by = field(metadata={'alias': 'removedBy'}) ``` ### `` timestamp `instance-attribute` ⚓︎ ``` timestamp ``` ### `` user_id `class-attribute` `instance-attribute` ⚓︎ ``` user_id = field(metadata={'alias': 'userId'}) ``` ## `` trueconf.types.RemovedMessage `dataclass` ⚓︎ ``` RemovedMessage(chat_id, message_id, removed_by) ``` Event type: a message was removed. This object is received in the handler when a message is deleted from a chat. ### Notes This class is used as the event type in handler functions decorated with `@.removed_message()`. ### Source trueconf.com/docs/chatbot-connector/en/messages/#removedMessage Attributes: | Name | Type | Description | | --- | --- | --- | | `` chat_id `class-attribute` `instance-attribute` (`trueconf.types.RemovedMessage.chat_id`)' href=#trueconf.types.RemovedMessage.chat_id>chat_id | `str` | Unique identifier of the chat from which the message was removed. | | `` message_id `class-attribute` `instance-attribute` (`trueconf.types.RemovedMessage.message_id`)' href=#trueconf.types.RemovedMessage.message_id>message_id | `str` | Unique identifier of the removed message. | | `` removed_by `class-attribute` `instance-attribute` (`trueconf.types.RemovedMessage.removed_by`)' href=#trueconf.types.RemovedMessage.removed_by>removed_by | `EnvelopeAuthor` | Information about the user who removed the message. | Examples: ``` from trueconf.types import RemovedMessage @.removed_message() async def on_removed(event: RemovedMessage): print(f"Message {event.message_id} removed from chat {event.chat_id}") ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` message_id `class-attribute` `instance-attribute` ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` ### `` removed_by `class-attribute` `instance-attribute` ⚓︎ ``` removed_by = field(metadata={'alias': 'removedBy'}) ``` ## `` trueconf.types.Update `dataclass` ⚓︎ ``` Update(method, type, id, payload) ``` ### `` id `instance-attribute` ⚓︎ ``` id ``` ### `` method `instance-attribute` ⚓︎ ``` method ``` ### `` payload `instance-attribute` ⚓︎ ``` payload ``` ### `` type `instance-attribute` ⚓︎ ``` type ``` ## `` trueconf.types.UploadingProgress `dataclass` ⚓︎ ``` UploadingProgress(file_id, progress) ``` Event type: file upload progress. This object is received in the handler when a file is being uploaded and the upload progress is updated. ### Notes This class is used as the event type in handler functions decorated with `@.uploading_progress()`. ### Source trueconf.com/docs/chatbot-connector/en/files/#uploadingProgress Attributes: | Name | Type | Description | | --- | --- | --- | | `` file_id `class-attribute` `instance-attribute` (`trueconf.types.UploadingProgress.file_id`)' href=#trueconf.types.UploadingProgress.file_id>file_id | `str` | Unique identifier of the file being uploaded. | | `` progress `instance-attribute` (`trueconf.types.UploadingProgress.progress`)' href=#trueconf.types.UploadingProgress.progress>progress | `int` | Number of bytes uploaded to the server. | Examples: ``` from trueconf.types import UploadingProgress @.uploading_progress() async def on_progress(event: UploadingProgress): print(f"File {event.file_id}: uploaded {event.progress} bytes") ``` ### `` file_id `class-attribute` `instance-attribute` ⚓︎ ``` file_id = field(metadata={'alias': 'fileId'}) ``` ### `` progress `instance-attribute` ⚓︎ ``` progress ``` ## `` trueconf.types.contact.Contact `dataclass` ⚓︎ ``` Contact( phone_number=None, first_name="", last_name=None, user_id=None, vcard=None, ) ``` Represents a contact parsed from a vCard file or a TrueConf contact link. Mirrors the Telegram/aiogram `Contact` shape. A vCard attachment provides a structured name (`N`), a phone number (`TEL`) and the raw vCard text; a TrueConf contact link (`[`) provides a user id and a display name. Attributes: | Name | Type | Description | | --- | --- | --- | | `` phone_number `class-attribute` `instance-attribute` (`trueconf.types.contact.Contact.phone_number`)' href=#trueconf.types.contact.Contact.phone_number>phone_number | `str | None` | Phone number parsed from the vCard `TEL` field. Always `None` for TrueConf contacts (no phone in the API). | | `` first_name `class-attribute` `instance-attribute` (`trueconf.types.contact.Contact.first_name`)' href=#trueconf.types.contact.Contact.first_name>first_name | `str` | Given name for vCards (from `N`/`FN`). For TrueConf contacts it holds the whole display name: the server-side name convention (ФИ/ИФ/ФИО) varies, so it is never split. | | `` last_name `class-attribute` `instance-attribute` (`trueconf.types.contact.Contact.last_name`)' href=#trueconf.types.contact.Contact.last_name>last_name | `str | None` | Family name parsed from the structured vCard `N` field. Always `None` for TrueConf contacts and for vCards that lack `N`. | | `` user_id `class-attribute` `instance-attribute` (`trueconf.types.contact.Contact.user_id`)' href=#trueconf.types.contact.Contact.user_id>user_id | `str | None` | TrueConf user id (e.g. `ai-bot@domain`) for TrueConf contacts; `None` for vCards. | | `` vcard `class-attribute` `instance-attribute` (`trueconf.types.contact.Contact.vcard`)' href=#trueconf.types.contact.Contact.vcard>vcard | `str | None` | Raw vCard text for vCard files; `None` otherwise. | `` first_name `class-attribute` `instance-attribute` ⚓︎](trueconf:login&do=profile) ``` first_name = '' ``` ### `` last_name `class-attribute` `instance-attribute` ⚓︎ ``` last_name = None ``` ### `` phone_number `class-attribute` `instance-attribute` ⚓︎ ``` phone_number = None ``` ### `` user_id `class-attribute` `instance-attribute` ⚓︎ ``` user_id = None ``` ### `` vcard `class-attribute` `instance-attribute` ⚓︎ ``` vcard = None ``` ## `` trueconf.types.CallbackQuery `dataclass` ⚓︎ ``` CallbackQuery( command_source, command_payload, command_id=None ) ``` ### `` chat `property` ⚓︎ ``` chat ``` ### `` command `property` ⚓︎ ``` command ``` ### `` command_id `class-attribute` `instance-attribute` ⚓︎ ``` command_id = field( default=None, metadata={"alias": "commandId"} ) ``` ### `` command_payload `class-attribute` `instance-attribute` ⚓︎ ``` command_payload = field( metadata={"alias": "commandPayload"} ) ``` ### `` command_source `class-attribute` `instance-attribute` ⚓︎ ``` command_source = field(metadata={'alias': 'commandSource'}) ``` ### `` custom_data `property` ⚓︎ ``` custom_data ``` ### `` message `property` ⚓︎ ``` message ``` ### `` answer `async` ⚓︎ ``` answer( text, *, answer_type, status=None, visibility=None, level=None, ) ``` ### `` edit_message `async` ⚓︎ ``` edit_message( text=UNSET, parse_mode=UNSET, *, buttons=UNSET ) ``` Shortcut for `async` ' href=../Bot/#trueconf.Bot.edit_message>`bot.edit_message` that edits the bot's own message this callback came from. The server treats `editMessage` as a full content overwrite (PUT): every edit carries the full text, formatting and buttons. Text and `parse_mode` are already present in the click event (`commandSource.message.content`), so only buttons are missing — when `buttons` is not given explicitly, the current buttons are fetched via `getMessageById`: - `edit_message(text="new")` — changes text, keeps buttons and formatting - `edit_message(buttons=kb)` — changes buttons, keeps text (no extra request) - `edit_message(text="new", buttons=kb)` — changes both (no extra request) - `edit_message(buttons=None)` — removes buttons, keeps text (no extra request) - `edit_message(text="new", buttons=None)` — changes text, removes buttons (no extra request) Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `text` | `str | UNSET` | New text. `UNSET` keeps the current. | `UNSET` | | `parse_mode` | `` ParseMode (`trueconf.enums.parse_mode.ParseMode`)' href=../Enums/#trueconf.enums.ParseMode>ParseMode | str | UNSET | Formatting mode. `UNSET` keeps the current `content.parseMode`. | `UNSET` | | `buttons` | `` trueconf.types.InlineKeyboardMarkup `dataclass` (`trueconf.types.keyboard.InlineKeyboardMarkup`)' href=#trueconf.types.InlineKeyboardMarkup>InlineKeyboardMarkup | None | UNSET | New inline keyboard. `UNSET` keeps the current buttons (fetched via `getMessageById`); `None` removes them. | `UNSET` | Returns: | Name | Type | Description | | --- | --- | --- | | `EditMessageResponse` | `` EditMessageResponse (`trueconf.types.responses.edit_message_response.EditMessageResponse`)' href=../Responses/#trueconf.types.responses.EditMessageResponse>EditMessageResponse | Result of the message update. | ## `` trueconf.types.Chat `dataclass` ⚓︎ ``` Chat(chat_id, chat_title, chat_type) ``` ### `` chat_id `class-attribute` `instance-attribute` ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` chat_title `class-attribute` `instance-attribute` ⚓︎ ``` chat_title = field(metadata={'alias': 'chatTitle'}) ``` ### `` chat_type `class-attribute` `instance-attribute` ⚓︎ ``` chat_type = field(metadata={'alias': 'chatType'}) ``` ## `` trueconf.types.InlineKeyboardButton `dataclass` ⚓︎ ``` InlineKeyboardButton( text=None, command=None, url=None, message=None, copy_data=None, custom_data=None, wait_reply=False, to=None, draft=False, button_id=None, style=None, ) ``` ### `` button_id `class-attribute` `instance-attribute` ⚓︎ ``` button_id = field(default=None, metadata={'alias': 'id'}) ``` ### `` command `class-attribute` `instance-attribute` ⚓︎ ``` command = None ``` ### `` copy_data `class-attribute` `instance-attribute` ⚓︎ ``` copy_data = field(default=None, metadata={'alias': 'data'}) ``` ### `` custom_data `class-attribute` `instance-attribute` ⚓︎ ``` custom_data = field( default=None, metadata={"alias": "customData"} ) ``` ### `` draft `class-attribute` `instance-attribute` ⚓︎ ``` draft = False ``` ### `` message `class-attribute` `instance-attribute` ⚓︎ ``` message = None ``` ### `` style `class-attribute` `instance-attribute` ⚓︎ ``` style = None ``` ### `` text `class-attribute` `instance-attribute` ⚓︎ ``` text = field(default=None, metadata={'alias': 'label'}) ``` ### `` to `class-attribute` `instance-attribute` ⚓︎ ``` to = None ``` ### `` type `class-attribute` `instance-attribute` ⚓︎ ``` type = field(init=False) ``` ### `` url `class-attribute` `instance-attribute` ⚓︎ ``` url = None ``` ### `` wait_reply `class-attribute` `instance-attribute` ⚓︎ ``` wait_reply = field( default=False, metadata={"alias": "waitReply"} ) ``` ### `` Config ⚓︎ #### `` omit_default `class-attribute` `instance-attribute` ⚓︎ ``` omit_default = True ``` #### `` omit_none `class-attribute` `instance-attribute` ⚓︎ ``` omit_none = True ``` #### `` serialize_by_alias `class-attribute` `instance-attribute` ⚓︎ ``` serialize_by_alias = True ``` ## `` trueconf.types.InlineKeyboardMarkup `dataclass` ⚓︎ ``` InlineKeyboardMarkup(buttons) ``` ### `` buttons `class-attribute` `instance-attribute` ⚓︎ ``` buttons = field(metadata={'alias': 'buttons'}) ``` ### `` Config ⚓︎ #### `` serialize_by_alias `class-attribute` `instance-attribute` ⚓︎ ``` serialize_by_alias = True ``` ## `` trueconf.types.content.location.Location `dataclass` ⚓︎ ``` Location(latitude, longitude, title) ``` ### `` latitude `instance-attribute` ⚓︎ ``` latitude ``` ### `` longitude `instance-attribute` ⚓︎ ``` longitude ``` ### `` title `instance-attribute` ⚓︎ ``` title ``` ## `` trueconf.types.content.voice.Voice `dataclass` ⚓︎ ``` Voice(file_id, file_size, mime_type, duration) ``` Represents a voice attached to a message. This class provides access to file metadata and utility methods such as downloading and preview access. Attributes: | Name | Type | Description | | --- | --- | --- | | `` file_id `class-attribute` `instance-attribute` (`trueconf.types.content.voice.Voice.file_id`)' href=#trueconf.types.content.voice.Voice.file_id>file_id | `str` | Unique identifier of the voice file. | | `` file_size `class-attribute` `instance-attribute` (`trueconf.types.content.voice.Voice.file_size`)' href=#trueconf.types.content.voice.Voice.file_size>file_size | `int` | Size of the file in bytes. | | `` mime_type `class-attribute` `instance-attribute` (`trueconf.types.content.voice.Voice.mime_type`)' href=#trueconf.types.content.voice.Voice.mime_type>mime_type | `str` | MIME type of the voice file. | | `` duration `instance-attribute` (`trueconf.types.content.voice.Voice.duration`)' href=#trueconf.types.content.voice.Voice.duration>duration | `int` | | ### `` bot `property` ⚓︎ ``` bot ``` ### `` duration `instance-attribute` ⚓︎ ``` duration ``` ### `` file_id `class-attribute` `instance-attribute` ⚓︎ ``` file_id = field(metadata={'alias': 'fileId'}) ``` ### `` file_size `class-attribute` `instance-attribute` ⚓︎ ``` file_size = field(metadata={'alias': 'size'}) ``` ### `` mime_type `class-attribute` `instance-attribute` ⚓︎ ``` mime_type = field(metadata={'alias': 'mimeType'}) ``` ### `` preview_url `async` `property` ⚓︎ ``` preview_url ``` Returns the preview URL of the voice file, if available. ### Source trueconf.com/docs/chatbot-connector/en/files/#getFileInfo Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | A URL pointing to the preview version of the voice file. | ### `` url `async` `property` ⚓︎ ``` url ``` Returns the direct download URL of the voice file. ### Source trueconf.com/docs/chatbot-connector/en/files/#getFileInfo Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | A URL pointing to the original voice file. | ### `` bind ⚓︎ ``` bind(bot) ``` ### `` download `async` ⚓︎ ``` download(dest_path=None, *, file_path=None) ``` Shortcut for the `download_file_by_id` method of the bot instance. ### Automatically fills the following attributes - `file_id` Use this method to download the current file by its ID. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `dest_path` | `str | Path` | Deprecated destination directory. | `None` | | `file_path` | `str | Path` | Exact path where the file should be saved. If neither path is specified, the file content is returned as bytes. | `None` | Returns: | Type | Description | | --- | --- | | `bytes | Path | None` | bytes | Path | None: File content, saved path, or None if the download failed. | October 1, 2026 September 3, 2025 --- # DOCUMENT: Formatting **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Formatting.md # Formatting ## `` trueconf.utils.formatting ⚓︎ ### `` AllMention ⚓︎ Represents an `@all` mention. #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders an `@all` mention. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered `@all` mention. | ### `` Bold ⚓︎ ``` Bold(*body) ``` Represents bold text. Initializes a text container. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Plain strings or formatting nodes. | `()` | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the nested content as bold text. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered bold text. | ### `` Italic ⚓︎ ``` Italic(*body) ``` Represents italic text. Initializes a text container. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Plain strings or formatting nodes. | `()` | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the nested content as italic text. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered italic text. | ### `` LineBreak ⚓︎ Represents a line break. Rendered as ` ` in HTML and as `\n` in Markdown, since raw newlines are collapsed to spaces in HTML messages. #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders a line break. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered line break. | ### `` Link ⚓︎ ``` Link(*body, url) ``` Represents a hyperlink. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Link label as plain text or formatting nodes. | `()` | | `url` | `str` | Link target URL. | required | Initializes a hyperlink node. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Link label as plain text or formatting nodes. | `()` | | `url` | `str` | Link target URL. | required | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` url `instance-attribute` ⚓︎ ``` url = url ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the nested content as a hyperlink. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered hyperlink. | ### `` Mention ⚓︎ ``` Mention(*body, user_id) ``` Represents a TrueConf user mention. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Mention label as plain text or formatting nodes. | `()` | | `user_id` | `str` | TrueConf user ID, for example `john_doe@video.example.com`. | required | Initializes a TrueConf mention node. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Mention label as plain text or formatting nodes. | `()` | | `user_id` | `str` | TrueConf user ID. | required | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` user_id `instance-attribute` ⚓︎ ``` user_id = user_id ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the nested content as a TrueConf user mention. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered mention. | ### `` Strikethrough ⚓︎ ``` Strikethrough(*body) ``` Represents strikethrough text. Initializes a text container. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Plain strings or formatting nodes. | `()` | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the nested content as strikethrough text. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered strikethrough text. | ### `` Text ⚓︎ ``` Text(*body) ``` Container node for plain text and nested formatting nodes. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Plain strings or formatting nodes to concatenate. | `()` | ### Example ``` content = Text("Hello, ", Bold("world")) html = content.as_html() ``` Initializes a text container. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Plain strings or formatting nodes. | `()` | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the text container using the provided decoration strategy. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered text. | ### `` Underline ⚓︎ ``` Underline(*body) ``` Represents underlined text. Initializes a text container. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `*body` | `str | TextNode` | Plain strings or formatting nodes. | `()` | #### `` body `instance-attribute` ⚓︎ ``` body = body ``` #### `` as_html ⚓︎ ``` as_html() ``` Renders the node as HTML. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | HTML representation of the formatted text. | #### `` as_markdown ⚓︎ ``` as_markdown() ``` Renders the node as Markdown. Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Markdown representation of the formatted text. | #### `` render ⚓︎ ``` render(decoration) ``` Renders the nested content as underlined text. Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `decoration` | `TextDecoration` | Formatting strategy used for rendering. | required | Returns: | Name | Type | Description | | --- | --- | --- | | `str` | `str` | Rendered underlined text. | June 30, 2026 May 5, 2026 --- # DOCUMENT: Chat activity **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/chat_activity.md # Chat activity ## `` trueconf.utils.chat_activity ⚓︎ ### `` DEFAULT_INITIAL_SLEEP `module-attribute` ⚓︎ ``` DEFAULT_INITIAL_SLEEP = 0.0 ``` ### `` ChatActivitySender ⚓︎ ``` ChatActivitySender( *, bot, chat_id, activity= TYPING class-attribute instance-attribute (trueconf.enums.chat_activity.ChatActivity.TYPING)' href=../Enums/#trueconf.enums.ChatActivity.TYPING>TYPING, initial_sleep= DEFAULT_INITIAL_SLEEP module-attribute (trueconf.utils.chat_activity.DEFAULT_INITIAL_SLEEP)' href=#trueconf.utils.chat_activity.DEFAULT_INITIAL_SLEEP>DEFAULT_INITIAL_SLEEP, ) ``` Sends a chat activity (for example, typing) in the background until a long operation finishes. The TrueConf server shows the activity indicator only for a short time, so it needs to be re-sent periodically. This utility starts a background task that re-sends the activity while the context is active. The cadence is taken from the server: each response carries `retryAfter` in milliseconds, and the sender waits that long before the next send. Examples: ``` >>> async with ChatActivitySender.typing(bot=bot, chat_id=chat_id): >>> await generate_text_answer() ``` Parameters: | Name | Type | Description | Default | | --- | --- | --- | --- | | `bot` | `` trueconf.Bot (`trueconf.client.bot.Bot`)' href=../Bot/#trueconf.Bot>Bot | Instance of the bot used to send activities. | required | | `chat_id` | `str` | Identifier of the target chat. | required | | `activity` | `` ChatActivity (`trueconf.enums.chat_activity.ChatActivity`)' href=../Enums/#trueconf.enums.ChatActivity>ChatActivity | str | Activity type to show. Defaults to typing. | `` TYPING `class-attribute` `instance-attribute` (`trueconf.enums.chat_activity.ChatActivity.TYPING`)' href=../Enums/#trueconf.enums.ChatActivity.TYPING>TYPING | | `initial_sleep` | `float` | Delay before the first send in seconds. Defaults to 0.0. | `` DEFAULT_INITIAL_SLEEP `module-attribute` (`trueconf.utils.chat_activity.DEFAULT_INITIAL_SLEEP`)' href=#trueconf.utils.chat_activity.DEFAULT_INITIAL_SLEEP>DEFAULT_INITIAL_SLEEP | #### `` activity `instance-attribute` ⚓︎ ``` activity = activity ``` #### `` bot `instance-attribute` ⚓︎ ``` bot = bot ``` #### `` chat_id `instance-attribute` ⚓︎ ``` chat_id = chat_id ``` #### `` initial_sleep `instance-attribute` ⚓︎ ``` initial_sleep = initial_sleep ``` #### `` running `property` ⚓︎ ``` running ``` #### `` typing `classmethod` ⚓︎ ``` typing(bot, chat_id, **kwargs) ``` Create an instance of the sender with the `typing` activity. October 1, 2026 October 1, 2026 --- # DOCUMENT: Exceptions **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Exceptions.md # Exceptions ## `` trueconf.exceptions ⚓︎ ### `` ApiErrorException ⚓︎ ``` ApiErrorException(code, detail, payload=None) ``` Raised when TrueConf Server returns an API error response. This exception stores the server error code, human-readable detail, and optional response payload for additional context. Attributes: | Name | Type | Description | | --- | --- | --- | | `` code `instance-attribute` (`trueconf.exceptions.ApiErrorException.code`)' href=#trueconf.exceptions.ApiErrorException.code>code | | Error code returned by the server. | | `` detail `instance-attribute` (`trueconf.exceptions.ApiErrorException.detail`)' href=#trueconf.exceptions.ApiErrorException.detail>detail | | Human-readable error description. | | `` payload `instance-attribute` (`trueconf.exceptions.ApiErrorException.payload`)' href=#trueconf.exceptions.ApiErrorException.payload>payload | | Raw error payload returned by the server, or an empty dict. | #### `` code `instance-attribute` ⚓︎ ``` code = code ``` #### `` detail `instance-attribute` ⚓︎ ``` detail = detail ``` #### `` payload `instance-attribute` ⚓︎ ``` payload = payload or {} ``` ### `` ChannelTitleTooLongError ⚓︎ ``` ChannelTitleTooLongError(actual_length, limit=256) ``` Raised when a channel title exceeds the maximum allowed length. Attributes: | Name | Type | Description | | --- | --- | --- | | `` actual_value `instance-attribute` (`trueconf.exceptions.ChannelTitleTooLongError.actual_value`)' href=#trueconf.exceptions.ChannelTitleTooLongError.actual_value>actual_value | | Actual length of the channel title. | | `` limit `instance-attribute` (`trueconf.exceptions.ChannelTitleTooLongError.limit`)' href=#trueconf.exceptions.ChannelTitleTooLongError.limit>limit | | Maximum allowed channel title length. | #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` ChatTitleTooLongError ⚓︎ ``` ChatTitleTooLongError(message, actual_value, limit) ``` Base exception for chat title length errors. This class is inherited by more specific exceptions for group and channel title length validation. #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` FileCaptionTooLongError ⚓︎ ``` FileCaptionTooLongError(actual_length, limit=4096) ``` Raised when a file caption exceeds the maximum allowed length. The default caption limit is 4096 visible characters. For long captions, use `safe_split_text` from `trueconf.utils` and send the returned chunks separately when appropriate. Attributes: | Name | Type | Description | | --- | --- | --- | | `` actual_value `instance-attribute` (`trueconf.exceptions.FileCaptionTooLongError.actual_value`)' href=#trueconf.exceptions.FileCaptionTooLongError.actual_value>actual_value | | Actual visible length of the caption. | | `` limit `instance-attribute` (`trueconf.exceptions.FileCaptionTooLongError.limit`)' href=#trueconf.exceptions.FileCaptionTooLongError.limit>limit | | Maximum allowed caption length. | #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` FileSizeTooLargeError ⚓︎ ``` FileSizeTooLargeError(actual_size, limit) ``` Raised when a file exceeds the maximum size allowed by the server. File size limits are configured by the TrueConf Server administrator and are checked by the bot before sending a file. Attributes: | Name | Type | Description | | --- | --- | --- | | `` actual_value `instance-attribute` (`trueconf.exceptions.FileSizeTooLargeError.actual_value`)' href=#trueconf.exceptions.FileSizeTooLargeError.actual_value>actual_value | | Actual file size in bytes. | | `` limit `instance-attribute` (`trueconf.exceptions.FileSizeTooLargeError.limit`)' href=#trueconf.exceptions.FileSizeTooLargeError.limit>limit | | Maximum allowed file size in bytes. | #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` FileUploadError ⚓︎ Raised when a file cannot be uploaded to the server. ### `` FileValidationError ⚓︎ Base exception for file validation errors. This class is used for errors related to file size limits, extension filters, and other file validation rules received from TrueConf Server. ### `` GroupTitleTooLongError ⚓︎ ``` GroupTitleTooLongError(actual_length, limit=256) ``` Raised when a group title exceeds the maximum allowed length. Attributes: | Name | Type | Description | | --- | --- | --- | | `` actual_value `instance-attribute` (`trueconf.exceptions.GroupTitleTooLongError.actual_value`)' href=#trueconf.exceptions.GroupTitleTooLongError.actual_value>actual_value | | Actual length of the group title. | | `` limit `instance-attribute` (`trueconf.exceptions.GroupTitleTooLongError.limit`)' href=#trueconf.exceptions.GroupTitleTooLongError.limit>limit | | Maximum allowed group title length. | #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` InMemoryDownloadLimitExceededError ⚓︎ ``` InMemoryDownloadLimitExceededError(actual_size, limit) ``` Raised when a file exceeds the configured in-memory download limit. #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` InvalidFileExtensionError ⚓︎ ``` InvalidFileExtensionError( extension, extensions=None, mode="allow" ) ``` Raised when a file extension does not satisfy the server extension filter. File extension rules are configured by the TrueConf Server administrator. Depending on the filter mode, the extension list can work either as an allow list or as a block list. Attributes: | Name | Type | Description | | --- | --- | --- | | `` extension `instance-attribute` (`trueconf.exceptions.InvalidFileExtensionError.extension`)' href=#trueconf.exceptions.InvalidFileExtensionError.extension>extension | | File extension that failed validation. | | `` extensions `instance-attribute` (`trueconf.exceptions.InvalidFileExtensionError.extensions`)' href=#trueconf.exceptions.InvalidFileExtensionError.extensions>extensions | | Set of extensions used for validation. | | `` mode `instance-attribute` (`trueconf.exceptions.InvalidFileExtensionError.mode`)' href=#trueconf.exceptions.InvalidFileExtensionError.mode>mode | | Extension filter mode. | #### `` extension `instance-attribute` ⚓︎ ``` extension = extension ``` #### `` extensions `instance-attribute` ⚓︎ ``` extensions = extensions or set() ``` #### `` mode `instance-attribute` ⚓︎ ``` mode = mode ``` ### `` InvalidGrantError ⚓︎ Raised when the server rejects the provided authorization grant. This usually means that the token or credentials are invalid, expired, revoked, or cannot be used to authorize the bot. ### `` LimitExceededError ⚓︎ ``` LimitExceededError(message, actual_value, limit) ``` Base exception for all limit-related errors. This class is used for errors related to text length, title length, file size, and other numeric limits. Attributes: | Name | Type | Description | | --- | --- | --- | | `` actual_value `instance-attribute` (`trueconf.exceptions.LimitExceededError.actual_value`)' href=#trueconf.exceptions.LimitExceededError.actual_value>actual_value | | Actual value that exceeded the limit. | | `` limit `instance-attribute` (`trueconf.exceptions.LimitExceededError.limit`)' href=#trueconf.exceptions.LimitExceededError.limit>limit | | Maximum allowed value. | #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` OAuthMissingScopeError ⚓︎ ``` OAuthMissingScopeError( message="The OAuth application has no scope configured. Add at least one scope (e.g. version:read) to the OAuth application on the server.", ) ``` Raised when the OAuth application has no scope configured. The TrueConf Server rejected the OAuth token request because the OAuth application has no scope. Add at least one scope (e.g. `version:read`) to the OAuth application on the server. ### `` PasswordAuthDisabledError ⚓︎ ``` PasswordAuthDisabledError( message="Password-based authentication is disabled on this server. Use Bot.from_oauth() instead.", ) ``` Raised when the server has disabled password-based authentication. This usually means the TrueConf server does not allow login/password authentication (e.g., only SSO/NTLM/Kerberos or MFA is enabled). Use `Bot.from_oauth()` with an OAuth application instead. ### `` TextMessageTooLongError ⚓︎ ``` TextMessageTooLongError(actual_length, limit=4096) ``` Raised when a text message exceeds the maximum allowed length. The default text message limit is 4096 visible characters. For long texts, such as LLM-generated responses, use `safe_split_text` from `trueconf.utils` and send the returned chunks one by one. Attributes: | Name | Type | Description | | --- | --- | --- | | `` actual_value `instance-attribute` (`trueconf.exceptions.TextMessageTooLongError.actual_value`)' href=#trueconf.exceptions.TextMessageTooLongError.actual_value>actual_value | | Actual visible length of the message text. | | `` limit `instance-attribute` (`trueconf.exceptions.TextMessageTooLongError.limit`)' href=#trueconf.exceptions.TextMessageTooLongError.limit>limit | | Maximum allowed message length. | #### `` actual_value `instance-attribute` ⚓︎ ``` actual_value = actual_value ``` #### `` limit `instance-attribute` ⚓︎ ``` limit = limit ``` ### `` TokenValidationError ⚓︎ Raised when the bot token fails local validation. This error indicates that the token value has an invalid format or cannot be used by the connector before the authorization request is sent. ### `` TrueConfChatBotError ⚓︎ Base exception for all TrueConf ChatBot Connector errors. All custom exceptions raised by the library inherit from this class. You can catch this exception to handle any library-specific error in a single place. ### `` WSConnectionError ⚓︎ Raised when WebSocket connection retries are exhausted. June 30, 2026 May 5, 2026 --- # DOCUMENT: Responses ⚓︎ **Source:** https://trueconf.github.io/python-trueconf-bot/v1.5.4/reference/Responses.md # Responses⚓︎ ``` from trueconf import Bot ``` ## `` trueconf.types.responses ⚓︎ ### `` AddChatParticipantResponse ⚓︎ ``` AddChatParticipantResponse() ``` ### `` AnswerCommandResponse ⚓︎ ``` AnswerCommandResponse() ``` ### `` ApiError ⚓︎ ``` ApiError(error_code) ``` #### `` error_code ⚓︎ ``` error_code = field(metadata={'alias': 'errorCode'}) ``` #### `` message ⚓︎ ``` message() ``` #### `` to_exception ⚓︎ ``` to_exception(payload=None) ``` ### `` AuthResponsePayload ⚓︎ ``` AuthResponsePayload(user_id, connection_id) ``` #### `` connection_id ⚓︎ ``` connection_id = field(metadata={'alias': 'connectionId'}) ``` #### `` user_id ⚓︎ ``` user_id = field(metadata={'alias': 'userId'}) ``` ### `` ChangeParticipantRoleResponse ⚓︎ ``` ChangeParticipantRoleResponse() ``` ### `` CreateChannelResponse ⚓︎ ``` CreateChannelResponse(chat_id) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` CreateGroupChatResponse ⚓︎ ``` CreateGroupChatResponse(chat_id) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` CreateP2PChatResponse ⚓︎ ``` CreateP2PChatResponse(chat_id) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` ### `` EditChatTitleResponse ⚓︎ ``` EditChatTitleResponse(chat_id, timestamp) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` EditMessageResponse ⚓︎ ``` EditMessageResponse(message_id, timestamp) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` EditSurveyResponse ⚓︎ ``` EditSurveyResponse(message_id, timestamp) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` ForwardMessageResponse ⚓︎ ``` ForwardMessageResponse(chat_id, message_id, timestamp) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` GetChatByIdResponse ⚓︎ ``` GetChatByIdResponse( title, chat_id, chat_type, unread_messages, avatar_url=None, last_message=None, ) ``` #### `` avatar_url ⚓︎ ``` avatar_url = field( default=None, metadata={"alias": "avatarUrl"} ) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` chat_type ⚓︎ ``` chat_type = field(metadata={'alias': 'chatType'}) ``` #### `` last_message ⚓︎ ``` last_message = field( default=None, metadata={"alias": "lastMessage"} ) ``` #### `` title ⚓︎ ``` title ``` #### `` unread_messages ⚓︎ ``` unread_messages = field( metadata={"alias": "unreadMessages"} ) ``` ### `` GetChatHistoryResponse ⚓︎ ``` GetChatHistoryResponse(count, chat_id, messages=list()) ``` #### `` bot ⚓︎ ``` bot ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` count ⚓︎ ``` count ``` #### `` messages ⚓︎ ``` messages = field( default_factory=list, metadata={ "alias": "messages", "deserialize": deserialize_envelopes, }, ) ``` #### `` bind ⚓︎ ``` bind(bot) ``` ### `` GetChatParticipantsResponse ⚓︎ ``` GetChatParticipantsResponse(participants=list()) ``` #### `` participants ⚓︎ ``` participants = field( default_factory=list, metadata={"alias": "participants"} ) ``` ### `` GetChatsResponse ⚓︎ ``` GetChatsResponse(chats=list()) ``` #### `` chats ⚓︎ ``` chats = field( default_factory=list, metadata={"alias": "chats"} ) ``` ### `` GetFileInfoResponse ⚓︎ ``` GetFileInfoResponse( name, size, mimetype, ready_state, file_id, previews=None, download_url=None, ) ``` #### `` download_url ⚓︎ ``` download_url = field( default=None, metadata={"alias": "downloadUrl"} ) ``` #### `` file_id ⚓︎ ``` file_id = field(metadata={'alias': 'fileId'}) ``` #### `` mimetype ⚓︎ ``` mimetype = field(metadata={'alias': 'mimeType'}) ``` #### `` name ⚓︎ ``` name ``` #### `` previews ⚓︎ ``` previews = field(default=None) ``` #### `` ready_state ⚓︎ ``` ready_state = field(metadata={'alias': 'readyState'}) ``` #### `` size ⚓︎ ``` size ``` ### `` GetFileUploadLimitsResponse ⚓︎ ``` GetFileUploadLimitsResponse(extensions, max_size=None) ``` #### `` extensions ⚓︎ ``` extensions ``` #### `` max_size ⚓︎ ``` max_size = field( default=None, metadata={"alias": "maxSize"} ) ``` ### `` GetMessageByIdResponse ⚓︎ ``` GetMessageByIdResponse( timestamp, type, author, box, content, message_id, chat_id, is_edited, reply_message_id=None, reply_message=None, ) ``` #### `` author ⚓︎ ``` author ``` #### `` bot ⚓︎ ``` bot ``` #### `` box ⚓︎ ``` box ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` content ⚓︎ ``` content = field(metadata={'deserialize': pass_through}) ``` #### `` is_edited ⚓︎ ``` is_edited = field(metadata={'alias': 'isEdited'}) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` reply_message ⚓︎ ``` reply_message = field( default=None, metadata={"alias": "replyMessage"} ) ``` #### `` reply_message_id ⚓︎ ``` reply_message_id = field( default=None, metadata={"alias": "replyMessageId"} ) ``` #### `` timestamp ⚓︎ ``` timestamp ``` #### `` type ⚓︎ ``` type ``` #### `` bind ⚓︎ ``` bind(bot) ``` ### `` GetUserDisplayNameResponse ⚓︎ ``` GetUserDisplayNameResponse(display_name) ``` #### `` display_name ⚓︎ ``` display_name = field(metadata={'alias': 'displayName'}) ``` ### `` HasChatParticipantResponse ⚓︎ ``` HasChatParticipantResponse(result) ``` #### `` result ⚓︎ ``` result ``` ### `` Previews ⚓︎ ``` Previews(name, size, mimetype, download_url) ``` #### `` download_url ⚓︎ ``` download_url = field(metadata={'alias': 'downloadUrl'}) ``` #### `` mimetype ⚓︎ ``` mimetype = field(metadata={'alias': 'mimeType'}) ``` #### `` name ⚓︎ ``` name ``` #### `` size ⚓︎ ``` size ``` ### `` RemoveChatParticipantResponse ⚓︎ ``` RemoveChatParticipantResponse() ``` ### `` RemoveChatResponse ⚓︎ ``` RemoveChatResponse() ``` ### `` RemoveMessageResponse ⚓︎ ``` RemoveMessageResponse() ``` ### `` SendChatActivityResponse ⚓︎ ``` SendChatActivityResponse( chat_id, activity_type, retry_after ) ``` #### `` activity_type ⚓︎ ``` activity_type = field(metadata={'alias': 'activityType'}) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` retry_after ⚓︎ ``` retry_after = field(metadata={'alias': 'retryAfter'}) ``` ### `` SendFileResponse ⚓︎ ``` SendFileResponse( timestamp, chat_id, message_id, file_id, caption_message_id=None, ) ``` #### `` caption_message_id ⚓︎ ``` caption_message_id = field( default=None, metadata={"alias": "captionMessageId"} ) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` file_id ⚓︎ ``` file_id = field(metadata={'alias': 'fileId'}) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` SendMessageResponse ⚓︎ ``` SendMessageResponse(chat_id, message_id, timestamp) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` SendSurveyResponse ⚓︎ ``` SendSurveyResponse(chat_id, message_id, timestamp) ``` #### `` chat_id ⚓︎ ``` chat_id = field(metadata={'alias': 'chatId'}) ``` #### `` message_id ⚓︎ ``` message_id = field(metadata={'alias': 'messageId'}) ``` #### `` timestamp ⚓︎ ``` timestamp ``` ### `` SubscribeFileProgressResponse ⚓︎ ``` SubscribeFileProgressResponse(result) ``` #### `` result ⚓︎ ``` result ``` ### `` UnsubscribeFileProgressResponse ⚓︎ ``` UnsubscribeFileProgressResponse(result) ``` #### `` result ⚓︎ ``` result ``` ### `` UploadFileResponse ⚓︎ ``` UploadFileResponse(upload_task_id) ``` #### `` upload_task_id ⚓︎ ``` upload_task_id = field(metadata={'alias': 'uploadTaskId'}) ``` June 30, 2026 February 27, 2026 ---