Skip to main content

Declarative, developer-friendly library for building Telegram bots

Project description

TeleKit

TeleKit Library

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(message, 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(chat_id)

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, bot.send_photo, or other Telegram API methods.

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`:
self.chain.set_inline_keyboard(
    {
        "« Change": prompt,  # Executes `prompt()` when clicked
        "Yes »": lambda: print("User: Okay!"),  # Runs this lambda when clicked
        "Youtube": "https://youtube.com"  # Opens a link
    }, row_width=2
)

# 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()

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(message, 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(message: telebot.types.Message, 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(message, 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 is published in PyPI, so it can be installed with one command:

pip install telekit

You can write the entire bot in a single file, but it’s recommended to organize your project using a simple structure like this one:

handlers/
    __init__.py
    start.py    # `/start` handler
    help.py     # `/help` handler
    ...
server.py       # entry point

Here is a server.py example (entry point) for a project on TeleKit

import telekit
import handlers # Package with all your handlers

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

Here you can see an example of the handlers/__init__.py file:

from . import (
    start, help #, ...
)

Here is an example of defining a handler using TeleKit (handlers/start.py file):

import telekit

class StartHandler(telekit.Handler):

    @classmethod
    def init_handler(cls) -> None:
        ...

One-file bot example (Echo Bot):

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()

For a full walkthrough, check out Tutorial or see more Examples


Contact


1.11.0 changelog:

Chain Improvements

  • New methods:
    • set_entry - general callback for any message.
    • set_entry_text - callback for text messages only.
    • set_entry_photo - callback for photo messages.
    • set_entry_document - callback for document messages.
    • set_entry_text_document - callback for text-based documents; auto-downloads and decodes text.
    • set_entry_location - callback for location messages.
    • Each of these methods has a corresponding decorator with the same name, but without the set_ prefix.
      • Setter:
      def handle_name(self, message: Message, name: str):
          print(name)
      
      def handle(self):
          ...
          self.chain.set_entry_text(self.handle_name) # self.handle_name: Callable[[Message, name], Any]
          self.chain.send()
      
      • Decorator:
      def handle(self):
          ...
          @self.chain.entry_text()
          def _handle_name(message: Message, name: str):
              print(name)
              
          self.chain.send()
      

DSL Improvements

  • You can now use text= directly instead of separate title and message fields.
  • Anonymous Scene Declaration: @ { ... }
  • New button type: "return" – navigates to the specified scene and clears the history between the current state and the target scene.
    For example, if the history looks like [a, b, previous, rooms, d, f, current] and return("Menu ↺", "rooms") is called from the current scene, the history after the transition becomes [a, b, previous, rooms]. (not [a, b, previous, rooms, d, f, current, rooms] as would happen with a regular rooms("Menu ↺")) This allows the back button in the rooms scene to return the user not to the current scene, but to the previous.
    If the target scene (rooms) appears multiple times in the history, return moves to the last occurrence of the target scene.
  • Complete refactor of the rendering process.
  • Improved performance.

Sender Improvements

  • _use_italics is now False by default. Use sender.set_use_italics() to enable italics in message.

Other Improvements

  • types module:
from telekit.types import ParseMode
self.chain.sender.set_parse_mode(ParseMode.HTML)

from telekit.types import ChatAction
self.chain.sender.send_chat_action(ChatAction.TYPING)

from telekit.types import Effect
self.chain.sender.set_effect(Effect.HEART)

# Other:
from telekit.types import TextDocument
from telekit.types import Styles
from telekit.types import User

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-1.11.0.tar.gz (72.2 kB view details)

Uploaded Source

Built Distribution

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

telekit-1.11.0-py3-none-any.whl (83.2 kB view details)

Uploaded Python 3

File details

Details for the file telekit-1.11.0.tar.gz.

File metadata

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

File hashes

Hashes for telekit-1.11.0.tar.gz
Algorithm Hash digest
SHA256 0f2e05b9cf39dbc67d87bf7a327a80e743432acece2880bb3a2a79ef5eae7607
MD5 c5ea17b0218bd33a5b098f79b63541f7
BLAKE2b-256 bb38e685b2625875a5bb153e409deedcb3c4d77a3c0349d17733d3460f12686d

See more details on using hashes here.

File details

Details for the file telekit-1.11.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for telekit-1.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f6f19c7b53a7f4e534363f6742e7d7d434f9ccdc983d900e5916115797052cb6
MD5 9286f64e734ae8661d1f31b7914189d7
BLAKE2b-256 779397881a879469e7a61f1d508548b4a510ac66521f272cfbac38a649b4ea85

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