Skip to main content

Declarative, developer-friendly library for building Telegram bots

Project description

TeleKit

PyPI Python

Telekit

Telekit is a declarative, developer-friendly library for building Telegram bots. It gives developers a dedicated Sender to manage message composition and a Chain to handle user input and responses. The library also handles message formatting, user input, and callback routing automatically, letting you focus on the botโ€™s behavior instead of repetitive tasks.

import telekit

class MyBotHandler(telekit.Handler):
    @classmethod
    def init_handler(cls):
        cls.on.command('start').invoke(cls.handle_start)

    def handle_start(self):
        self.chain.sender.set_text("Hello!")
        self.chain.sender.set_photo("robot.png")
        self.chain.send()

telekit.Server("BOT_TOKEN").polling()

Example taken out of context

Telekit comes with a built-in DSL, allowing developers to create fully interactive bots with minimal code. The DSL also supports Jinja templates, providing support for loops, conditionals, expressions, and filters directly within template fields to generate dynamic content.

@ main {
    title   = "๐ŸŽ‰ Fun Facts Quiz";
    message = "Test your knowledge with 10 fun questions!";

    buttons {
        question_1("Start Quiz");
    }
}

See the full example

Even in its beta stage, Telekit accelerates bot development, offering ready-to-use building blocks for commands, user interactions, and navigation. Its declarative design makes bots easier to read, maintain, and extend.

Key features:

  • Declarative bot logic with chains for effortless handling of complex workflows
  • Ready-to-use DSL for FAQs and other interactive scripts
  • Automatic handling of message formatting via Sender and callback routing
  • Deep Linking support with type-checked Command Parameters for flexible user input
  • Built-in Permission and Logging system for user management
  • Seamless integration with pyTelegramBotAPI
  • Fast to develop and easy-to-extend code

GitHub PyPi Community Gallery Examples Tutorial

Contents

Overview

To get the most out of Telekit, we recommend following the full, step-by-step tutorial that covers everything from installation to advanced features and DSL usage.

Even if you donโ€™t go through the entire guide right now, you can quickly familiarize yourself with the core concepts of Telekit below. This section will introduce you to chains, handlers, message formatting, and some examples, giving you a solid foundation to start building bots right away.

Below is an example of a bot that responds to messages like "My name is {name}":

import telekit

class NameHandler(telekit.Handler):

    @classmethod
    def init_handler(cls) -> None:
        cls.on.text("My name is {name}").invoke(cls.display_name)

    def display_name(self, name: str) -> None:
        self.chain.sender.set_title(f"Hello {name}!")
        self.chain.sender.set_message("Your name has been set. You can change it below if you want")
        self.chain.set_inline_keyboard({"โœ๏ธ Change": self.change_name})
        self.chain.edit()

    def change_name(self):
        self.chain.sender.set_title("โŒจ๏ธ Enter your name...")
        self.chain.sender.set_message("Please, type your new name below:")

        @self.chain.entry_text(delete_user_response=True)
        def name_handler(name: str):
            self.display_name(name)

        self.chain.edit()

telekit.Server("TOKEN").polling()

Letโ€™s see how it works in practice ๐Ÿ‘‡

Message formatting:

  • You can configure everything manually:
self.chain.sender.set_text("*Hello, user!*\n\nWelcome to the Bot!")
self.chain.sender.set_parse_mode("markdown")
  • Or let Telekit handle the layout for you:
self.chain.sender.set_title("๐Ÿ‘‹ Hello, user!") # Bold title
self.chain.sender.set_message("Welcome to the Bot!")  # Text after the title

Approximate result:

๐Ÿ‘‹ Hello, user!

Welcome to the Bot!

If you want more control, you can use the following methods:

self.chain.sender.set_use_italics(True) # Italicize message body
self.chain.sender.set_use_newline(False) # Disable spacing between title and message
self.chain.sender.set_parse_mode(ParseMode.HTML) # Set parse mode. Use enum or string
self.chain.sender.set_reply_to(message)
self.chain.sender.set_chat_id(472584)

Want to add an image, document or an effect in a single line?

self.chain.sender.set_effect(Effect.HEART) # Add effect to message. Use enum or string
self.chain.sender.set_photo("robot.png") # Attach photo. URL, file_id, or path
self.chain.sender.set_document("README.md") # Attach document. URL, file_id, or path
self.chain.sender.set_text_as_document("Hello, this is a text document!")
self.chain.sender.send_chat_action(ChatAction.TYPING) # Use enum or string

[!NOTE] Telekit automatically decides whether to use 'bot.send_message' or 'bot.send_photo' based on the content

More styling options are available in the documentation.

Text Styling with Styles

Telekit provides a convenient style classes to create styled text objects for HTML or Markdown:

Bold("Bold") + " and " + Italic("Italic")

Combine multiple styles:

Strikethrough(Bold("Hello") + Italic("World!"))

Then pass it to set_text, set_title, or other sender methods, and the sender will automatically determine the correct parse_mode.

For more details, see our tutorial

Handling callbacks and Logic

If your focus is on logic and functionality, Telekit is the ideal library:

Inline keyboard with callback support:

Inline keyboard label-callback:

from telekit.types import LinkButton, CopyTextButton

self.chain.set_inline_keyboard(
    {   
        # When the user clicks this button, `change_name()` will be executed
        "Change": change_name,
        # When the user clicks this button, this lambda function will run
        "Okay": lambda: print("User: Okay!"),
        # When the user clicks this button, this method will be executed
        "Reload": self.reload,
        # Can even be a link (`str` or `LinkButton` object)
        "PyPi": "https://pypi.org/project/telekit/",
        "GitHub": LinkButton("https://github.com/Romashkaa/telekit"),
        # Or copy button
        "Copy Text": CopyTextButton("Text to copy")
    }, row_width=(3, 2, 1)
)

Result:

โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚   Change   โ”‚   Okay   โ”‚  Reload  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚       PyPi      โ”‚     GitHub     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚            Copy Text             โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Inline keyboard label-value:

@self.chain.inline_keyboard({
    "Red": (255, 0, 0),
    "Green": (0, 255, 0),
    "Blue": (0, 0, 255),
}, row_width=3)
def _(message, value: tuple[int, int, int]) -> None:
    r, g, b = value
    self.chain.set_message(f"You selected RGB color: ({r}, {g}, {b})")
    self.chain.edit()

Inline choice keyboard:

self.chain.set_inline_choice(
    lambda value: print(f"User picked {value}"),
    choices=["Choice 1", "Choice 2"]
)

Receiving messages with callback support:

# Receive any message type:
@self.chain.entry(
    filter_message=lambda message: bool(message.text),
    delete_user_response=True
)
def handler(message):
    print(message.text)

# Receive text message:
@self.chain.entry_text()
def name_handler(text: str):
    print(text)

# Inline keyboard with suggested options:
chain.set_entry_suggestions(["Suggestion 1", "Suggestion 2"])

# Receive a .zip document:
@self.chain.entry_document(allowed_extensions=(".zip",))
def doc_handler(document: telebot.types.Document):
    print(document.file_name, document)

# Receive a text document (Telekit auto-detects encoding):
@self.chain.entry_text_document(allowed_extensions=(".txt", ".js", ".py"))
def text_document_handler(text_document: telekit.types.TextDocument):
    print(
        text_document.text,      # "Example\n ..."
        text_document.file_name, # "example.txt"
        text_document.encoding,  # "utf-8"
        text_document.document   # <telebot.types.Document>
    )

Telekit is lightweight yet powerful, giving you a full set of built-in tools and solutions for building advanced Telegram bots effortlessly.

[!TIP] You can find more information about the decorators by checking their doc-strings in Python.

Command Parameters and Deep Linking

Telekit allows you to define commands with typed parameters and handle deep links. This makes it easy to pass arguments directly in the /command parameter call or through a URL link like https://t.me/YourBot?start=parameter.

You can define a command and specify expected parameter types using telekit.parameters:

import telekit
from telekit.parameters import Int, Str

class StartHandler(telekit.Handler):

    @classmethod
    def init_handler(cls) -> None:
        # Define parameters: first an integer, then a string
        cls.on.command("start", params=[Int(-1), Str()]).invoke(cls.handle)
    
    # Default values are required:   โ†“โ†“โ†“โ†“                   โ†“โ†“โ†“โ†“
    def handle(self, age: int | None=None, name: str | None=None):
        if age is None:
            self.chain.sender.set_text("Please provide your age and name.")
        elif age == -1:
            self.chain.sender.set_text("Invalid age provided.")
        elif name is None:
            self.chain.sender.set_text("Name is missing.")
        else:
            self.chain.sender.set_text(f"Hello {name}! You are {age} years old.")
        
        self.chain.send()

Send /start 21 "Name Surname" to your bot to see it in action.


Quick Start

Telekit makes building Telegram bots fast and clean.
Even if youโ€™ve never written one before, this guide will take you from zero to a working bot in minutes.

Installation

Telekit is published in PyPI, so it can be installed with command:

pip install telekit

Getting a Bot Token

First, get your bot token from BotFather.

After that, you can run the example bot to explore Telekitโ€™s basic features:

import telekit # import library

telekit.example(BOT_TOKEN) # run the example bot

Basic Setup

To create your own bot server, replace example with the Server class and call polling() to start listening for updates:

import telekit

telekit.Server(BOT_TOKEN).polling() # here

Thatโ€™s it โ€” your bot is connected.

Eัho Bot Example

import telekit

class EchoHandler(telekit.Handler):

    @classmethod
    def init_handler(cls) -> None:
        cls.on.text().invoke(cls.echo) # accepts all text messages

    def echo(self) -> None:
        self.chain.sender.set_text(f"{self.message.text}!")
        self.chain.send()

telekit.Server("TOKEN").polling()

To understand how the example above works, I recommend continuing with:

Creating Basic Handler ยป


Contact


Changes in version 2.0.0a

Obsidian Canvas Mode (Beta)

Build bots visually โ€” no DSL required. Design your dialog flow as a flowchart in Obsidian and connect it to Telekit with a single method call.

  • Added analyze_canvas() to DSLHandler โ€” loads a .canvas file as an executable model

Styles Improvements

The style system has been rewritten from the ground up. Previously, automatic escaping was quite unpredictable โ€” users couldn't always tell when a string would be escaped or not. That's over.

  • Migrated markdown rendering to MarkdownV2
  • Added Stack style for structured list rendering
  • Added Mention style
  • Renamed Sanitize to Escape
  • Renamed NoSanitize to Raw
  • Added utils.sanitize_markdown() โ€” escapes all MarkdownV2 special characters outside valid entities
  • Added utils.adapt_markdown() โ€” converts **bold** / *italic* to Telegram-compatible format
  • Added utils.telegramify_markdown() โ€” convenience pipeline: adapt + sanitize
  • StyleFormatter renamed to TextEntity

Inline Keyboards

Inline keyboards got a proper type system. Previously, any string value in the keyboard dict was treated as a link. Now every button type is explicit.

  • Introduced InlineButton base class with subclasses: LinkButton, WebAppButton, SuggestButton, CopyTextButton, CallbackButton
  • CallbackButton โ€” pass arguments to callbacks and set visual style
  • Added ButtonStyle enum โ€” style your inline buttons (Bot API 9.4)
  • Added inline_choice / set_inline_choice methods
  • set_entry_suggestions now warns when Telegram Bot API limits are exceeded
  • It's no longer pass Message object to callbacks
  • Reduced closure size and improved callback performance

Chain Improvements

  • Added set_break_only_on_match() โ€” control whether chain interrupts only on valid handler match, not random input
  • Added set_break_on_commands() โ€” control whether commands take priority over entry handlers
  • Improved file extension validation via pathlib
  • entry_* handlers no longer pass Message by default โ€” use include_message=True to restore

CallbackQueryHandler

  • Callbacks now invoked directly โ€” no virtual message conversion, faster response times
  • Native alert support for expired or inactive buttons
  • Added set_invalid_data_answer() and set_button_is_no_active_answer() for global customization

DSL Improvements

  • jinja_env is now private โ€” use get_jinja_env() instead
  • TelekitDSL class:
    • All from_* factory methods now use type() for class creation

Fixes

  • Fixed one-time trigger bug โ€” triggers like on.text now fire reliably across multiple messages while a chain timeout is active

Other

  • Added utils.read_token() and utils.read_canvas_path() โ€” clean helpers for reading credentials from files
  • Added utils.format_file_size()
  • Added set_license_text to senders
  • Added format_size to TextDocument
  • Added TelekitState class
  • Bumped pyTelegramBotAPI to v4.31.0
  • Added GPL v3 License

๐Ÿš€ Upcoming

  • New triggers: document, text_document
  • Telekit DSL: shorter notation and button attributes with style, alert, ... support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

telekit-2.0.0a0.tar.gz (104.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

telekit-2.0.0a0-py3-none-any.whl (125.7 kB view details)

Uploaded Python 3

File details

Details for the file telekit-2.0.0a0.tar.gz.

File metadata

  • Download URL: telekit-2.0.0a0.tar.gz
  • Upload date:
  • Size: 104.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for telekit-2.0.0a0.tar.gz
Algorithm Hash digest
SHA256 2881e7f1ae2e7cb00378950fd720b34d6fe6d0834555617d5e3f4656a7d48ee8
MD5 d53ee3d251182b5cb67512a469b28617
BLAKE2b-256 413f336dd3ae908298a7f4d457fcc66340358668f3733899eccc1e86928849a1

See more details on using hashes here.

File details

Details for the file telekit-2.0.0a0-py3-none-any.whl.

File metadata

  • Download URL: telekit-2.0.0a0-py3-none-any.whl
  • Upload date:
  • Size: 125.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for telekit-2.0.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 7ccc2ac2e95d1421ab1b795f55d70d15dc39570cb9fd68ba007f92d194f41cd6
MD5 0c22f34b2225e2609cfc52adfa864e9c
BLAKE2b-256 7c70ac0f75c280897aa517ba5f5d15d8126944d70cf88bc85ea6a585b119b8b1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page