The easiest and most convenient Telegram Bot API with a declarative interface, featuring a wide range of built-in tools and ready-to-use solutions for fast bot development
Project description
TeleKit Library
Telekit is a compilation of my early unpublished libraries, now working together seamlessly as a single unit. Intuitive and flexible, it doesn’t restrict you—you can still use handlers and other elements from the original library.
Instead, it adds new tools and a declarative style, where you only need to “fill in the fields” in self.chain and "confirm" using self.chain.send(). Telekit automatically formats messages, handles potential errors (like unclosed HTML tags), and processes user responses.
GitHub PyPi Telegram Real Example
Overview
The library is designed to reduce boilerplate code and make Python development more efficient:
import telebot
import telekit
class NameHandler(telekit.Handler):
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
@cls.on_text("My name is {name}")
def _(message: telebot.types.Message, name: str):
cls(message).display_name(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 new 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()
bot = telebot.TeleBot("TOKEN")
telekit.Server(bot).polling()
Let’s examine each element individually:
Message formatting:
- You can configure everything manually:
self.chain.sender.set_text("*Hello, user!*\n\nWelcome to the Bot!")
- 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!") # Italic message after the title
Approximate result:
👋 Hello, user!
Welcome to the Bot!
If you want more control:
self.chain.sender.set_use_italic(False)
self.chain.sender.set_parse_mode("HTML")
self.chain.sender.set_reply_to(message)
self.chain.sender.set_chat_id(chat_id)
# And this is just the beginning...
Want to add an image or an effect in a single line?
self.chain.sender.set_effect(sender.Effect.HEART)
self.chain.sender.set_photo("url, bytes or path")
Telekit decides whether to use bot.send_message or bot.send_photo automatically!
Handling callbacks and Logic
If your focus is on logic and functionality, Telekit is the ideal library:
- Inline keyboard:
# Inline keyboard `label-callback`:
self.chain.set_inline_keyboard(
{
# label: `str`
# callback: `Chain` | `str` | `Callable[[], Any]` | `Callable[[Message], Any]`
"« Change": prompt, # When the user clicks this button, `prompt.send()` will be executed
"Yes »": lambda: print("User: Okay!"), # When the user clicks this button, this lambda function will run
"Youtube": "https://youtube.com" # Can even be a link
}, row_width=2
)
# Inline keyboard `label-value`:
@self.chain.inline_keyboard({
# label: `str`
# value: `Any`
"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 and files:
# 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, name: str):
print(name)
# 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.
- You can find information about the new decorators by checking their doc-strings in Python.
Quick Guide
Here is a server.py example (entry point) for a project on TeleKit
import telebot
import telekit
import handlers # Package with all your handlers
bot = telebot.TeleBot("TOKEN")
telekit.Server(bot).polling()
Here you can see an example of the handlers/__init__.py file:
from . import (
start, entry, help
)
Here is an example of defining a handler using TeleKit (handlers/start.py file):
import telekit
import typing
import telebot.types
class StartHandler(telekit.Handler):
# ------------------------------------------
# Initialization
# ------------------------------------------
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes the command handler.
"""
@bot.message_handler(commands=['start']) # Standard handler declaration
def handler(message: telebot.types.Message) -> None:
cls(message).handle()
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def handle(self) -> None:
# Get the `chain` object:
chain: telekit.Chain = self.get_chain()
# Below we change the message view using `chain.sender`:
chain.sender.set_title("Hello") # Set the title for the message
chain.sender.set_message("Welcome to the bot! Click the button below to start interacting.") # Set the message text
chain.sender.set_photo("https://static.wikia.nocookie.net/ssb-tourney/images/d/db/Bot_CG_Art.jpg/revision/latest?cb=20151224123450") # Add a photo to the message (optional)
chain.sender.set_effect(chain.sender.Effect.PARTY) # Add an effect (optional)
# Handler's own logic:
def counter_factory() -> typing.Callable[[int], int]:
count = 0
def counter(value: int=1) -> int:
nonlocal count
count += value
return count
return counter
click_counter = counter_factory()
# Add a keyboard to the message via `chain`:
# {"⊕": 1, ...} - {"caption": value}
# The button caption should be a string
# The value of the button can be any object and is not sent to Telegram servers
@chain.inline_keyboard({"⊕": 1, "⊖": -1}, row_width=2)
def _(message: telebot.types.Message, value: int) -> None:
# ^ ^
# Callback turns to Message |
# Value from `{caption: value}` – not sent to Telegram servers
chain.sender.set_message(f"You clicked {click_counter(value)} times") # Change the message text
chain.edit_previous_message() # Сhange the previous message instead of sending the new one.
# ^ You can also call this once at the beginning of the function:
# ^ `chain.set_always_edit_previous_message(True)`
chain.send() # Edit previous message
chain.send() # Send message
It is recommended to declare each handler in a separate file and place all handlers in the handlers folder.
But you can write everything in one file:
import telebot
import telekit
class NameAgeHandler(telekit.Handler):
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes the message handlers.
"""
@cls.on_text("My name is {name} and I am {age} years old")
def _(message: telebot.types.Message, name: str, age: str):
cls(message).handle(name, age)
@cls.on_text("My name is {name}")
def _(message: telebot.types.Message, name: str):
cls(message).handle(name, None)
@cls.on_text("I'm {age} years old")
def _(message: telebot.types.Message, age: str):
cls(message).handle(None, age)
def handle(self, name: str | None, age: str | None) -> None:
# Starting from TeleKit 0.0.3, the initial chain is created automatically.
# However, you can still create a new one manually: `chain: telekit.Chain = self.get_chain()`
if not name:
name = self.user.get_username()
if not age:
age = "An unknown number of"
self.chain.sender.set_text(f"👋 Hello {name}! {age} years is a wonderful stage of life!")
self.chain.send()
bot = telebot.TeleBot("TOKEN")
telekit.Server(bot).polling()
Chains
A Chain is the core element of Telekit, combining a Sender and an InputHandler.
(The latter usually works “under the hood,” so you typically don’t interact with it directly)
Proper usage of a Chain is crucial for predictable bot behavior.
Case 1 — Using the Same Chain Across All Methods
In this approach, the same Chain instance is used throughout all methods of the class:
class MyHandler(telekit.Handler):
...
def handle(self) -> None:
self.chain.sender.set_text("1st page")
self.chain.set_inline_keyboard(
{
"Next": self.handle_next
}
)
self.chain.edit()
def handle_next(self) -> None:
self.chain.sender.set_text("2nd page")
self.chain.set_inline_keyboard(
{
"Back": self.handle
}
)
self.chain.edit()
Using the same Chain can help save memory and automatically replaces the previous message with smooth animations. However, it also retains previous settings. For example, if you don’t call self.chain.set_inline_keyboard in handle_next or otherwise (don't) update the inline keyboard, the old configuration will persist in the new message.
Case 2 — Using Separate Chains for Each Step
In this approach, a new Chain instance is created for each step:
class MyHandler(telekit.Handler):
...
def handle(self) -> None:
chain = self.get_chain()
chain.sender.set_text("1st page")
chain.set_inline_keyboard(
{
"Next": self.handle_next
}
)
chain.edit()
def handle_next(self) -> None:
chain = self.get_chain()
chain.sender.set_text("2nd page")
chain.set_inline_keyboard(
{
"Back": self.handle
}
)
chain.edit()
Using a separate Chain for each step is also fine for memory usage, but it won’t provide automatic animations—you’ll need to call chain.sender.set_edit_message(...) yourself.
On the plus side, it doesn’t retain any previous settings.
Case 3 — Using Child Chains with Explicit Parent
In this approach, each child chain is explicitly linked to a parent chain to avoid uncontrolled recursion:
class MyHandler(telekit.Handler):
...
def handle(self) -> None:
main: telekit.Chain = self.get_chain()
main.set_always_edit_previous_message(True)
main.sender.set_title(...)
main.sender.set_message(...)
@main.inline_keyboard(pages)
def _(message: telebot.types.Message, value: tuple[str, str]) -> None:
page: telekit.Chain = self.get_child(main) # Explicitly assign `main` as the parent
page.sender.set_title(value[0])
page.sender.set_message(value[1])
page.set_inline_keyboard({"« Back": main}) # btw: `page.parent` == `main`
page.send()
main.send()
If you don’t explicitly provide the parent chain, get_child will keep creating a child of the previous child indefinitely. The longer a user interacts with this function, the deeper the chain nesting grows, consuming more memory as each Chain object holds its inline keyboard and callbacks. Always specify the parent to prevent memory leaks.
Case 4 — Using Sequential Child Chains
Each method creates a new child chain from the previous one, and (important:) there’s no way for the user to generate an infinite sequence:
class MyHandler(telekit.Handler):
...
def handle_1st(self) -> None:
chain = self.get_chain()
chain.sender.set_text("1st page")
chain.set_inline_keyboard(
{
"Next": self.handle_2nd
}
)
chain.edit()
def handle_2nd(self) -> None:
chain = self.get_child()
chain.sender.set_text("2nd page")
chain.set_inline_keyboard(
{
"Next": self.handle_3rd
}
)
chain.edit()
def handle_3rd(self) -> None:
chain = self.get_child()
chain.sender.set_text("3rd page")
chain.edit()
Here everything is safe because there’s no “Back” button, so the user cannot endlessly create new chains that consume server memory. Each chain is a child of the previous one, but this sequence has a natural limit determined by program logic, preventing memory bloat.
By the way:
self.get_chain()andself.get_child()updates thechainattribute in thehandler(self.chain):
chain = self.get_chain()
print(chain == self.chain) # True
child = self.get_child()
print(child == self.chain) # True
print(chain == child) # False
print(chain == child.parent) # True
# ---
chain1 = self.chain
self.get_chain()
print(chain1 == self.chain) # False
- Ways to create child chains:
self.get_child() # Child chain of previous chain
self.get_child(parent) # Or explicitly provide the parent chain
# Assign a parent chain after the current chain has been created:
self.get_chain().set_parent(parent)
Other Chain`s Methods
Method chain.edit_previous_message()
Sets whether to edit the previously sent message instead of sending a new one.
chain.edit_previous_message() # The next chain.send() will edit the previous message
Method chain.set_always_edit_previous_message()
Allows you to specify that the previous message should always be edited when sending a new one. When used in a chain, this setting is automatically applied to all (future) child chains of this object.
chain.set_always_edit_previous_message(True)
Method chain.get_previous_message()
Returns the previously sent message (telebot.types.Message) or None if no message has been sent yet.
Handler
Attribute handler.message
class MyHandler(telekit.Handler):
...
def handle(self) -> None:
self.message # First message in the chain (probably the user command / message that started it)
self.message.chat.id # Chat ID
Attribute handler.user
The User class provides a simple abstraction for working with Telegram users inside your bot. It stores the chat_id, the from_user object, and provides convenient methods to get the username.
User's Method handler.user.get_username() -> str | None
Returns the username of the user.
- If the user has a Telegram username, it will be returned with an @ prefix.
- If not, falls back to the user’s first_name.
- If unable to fetch data, returns None.
class MyHandler(telekit.Handler):
...
def handle(self) -> None:
username = self.user.get_username()
if username:
self.chain.sender.set_text(f"👋 Hello {username}!")
else:
self.chain.sender.set_text(f"🥴 Hello?")
self.chain.send()
User's Method handler.user.chat_id: int
class MyHandler(telekit.Handler):
...
def handle(self) -> None:
print(self.user.chat_id() == self.message.chat.id) # True
## Listeners
Decorator handler.on_text()
Decorator for handling messages that match a given text pattern with placeholders {}. Each placeholder is passed as a separate argument to the decorated function:
import telebot.types
import telekit
class OnTextHandler(telekit.Handler):
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes the message handlers.
"""
@cls.on_text("Name: {name}. Age: {age}")
def _(message: telebot.types.Message, name: str, age: str):
cls(message).handle(name, age)
@cls.on_text("My name is {name} and I am {age} years old")
def _(message: telebot.types.Message, name: str, age: str):
cls(message).handle(name, age)
@cls.on_text("My name is {name}")
def _(message: telebot.types.Message, name: str):
cls(message).handle(name, None)
@cls.on_text("I'm {age} years old")
def _(message: telebot.types.Message, age: str):
cls(message).handle(None, age)
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def handle(self, name: str | None, age: str | None) -> None:
if not name:
name = self.user.get_username()
if not age:
age = "An unknown number of"
self.chain.sender.set_title(f"Hello {name}!")
self.chain.sender.set_message(f"{age} years is a wonderful stage of life!")
self.chain.send()
This allows you to define multiple on_text handlers with different patterns, each extracting the placeholders automatically.
Decorator handler.message_handler()
Decorator for handling any kind of incoming message — text, photo, sticker, etc. The decorated function receives a telebot.types.Message object as a parameter. Handlers are executed in the order they are added.
import telebot.types
import telekit
from typing import Callable, Any
class MessageHandlerExample(telekit.Handler):
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes message handlers.
"""
@cls.message_handler(commands=['help'])
def help_handler(message: telebot.types.Message) -> None:
cls(message).show_help()
@cls.message_handler(regexp=r"^My name is (.+)$")
def name_handler(message: telebot.types.Message) -> None:
name = message.text.split("My name is ")[1]
cls(message).greet(name)
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def show_help(self) -> None:
self.chain.sender.set_title("Help Menu")
self.chain.sender.set_message("Here are some useful commands to get started...")
self.chain.send()
def greet(self, name: str) -> None:
self.chain.sender.set_title(f"Hello {name}!")
self.chain.sender.set_message("Welcome to the bot!")
self.chain.send()
This allows you to define multiple message_handler decorators with different triggers (commands, regex patterns, content types, etc.) for flexible message processing. You can also use optional parameters such as whitelist to restrict handling to specific chat IDs.
Senders
Senders in Telekit provide a high-level interface for sending and managing messages in Telegram bots. They wrap the standard TeleBot API, adding convenience features such as temporary messages, automatic editing, error handling, formatting, and effects.
Key Attributes:
bot: The global TeleBot instance.chat_id: Target chat ID.text: Message text.reply_markup: Inline or keyboard markup.is_temporary: Marks the message as temporary.delele_temporaries: Deletes previous temporary messages if set.parse_mode: Message formatting (HTMLorMarkdown).reply_to_message_id: Optional message to reply to.edit_message_id: Optional message ID to edit.thread_id: Thread or topic ID (optional).message_effect_id: Optional effect like 🔥 or 🎉.photo: Optional photo to send.
Key Methods:
set_text(text): Update the message text.- Or let Telekit handle the layout for you:
set_title(title)+set_message(message)set_use_italics(flag)– Enable/disable italics for the message body.set_add_new_line(flag)– Add/remove a blank line between title and message.
set_photo(photo): Attach a photo.set_parse_mode(mode): Set formatting mode.set_reply_to(message): Reply to a specific message.set_effect(effect): Apply a visual effect.set_edit_message(message): Set the message to edit.get_message_id(message): Get the ID of a message.delete_message(message): Delete a message.error(title, message): Send a custom error.pyerror(exception): Send exception details.send(): Send or edit the message.try_send(): Attempt sending, returns(message, exception).send_or_handle_error(): Send a message and show a Python exception if it fails.set_temporary(flag): Mark message as temporary.set_delete_temporaries(flag): Delete previous temporary messages.set_chat_id(chat_id): Change target chat.set_reply_markup(reply_markup): Add inline/keyboard markup. Raw.
Chapters
TeleKit provides a simple way to organize large texts or structured content in .txt files and access them as Python dictionaries. This is ideal for help texts, documentation, or any content that should be separate from your code.
How It Works
Each section in a .txt file starts with a line beginning with #, followed by the section title. All subsequent lines until the next # are treated as the content for that section.
Example help.txt
# intro
Welcome to TeleKit library. Here are the available commands:
# commands
/start — Start command
/entry — Example command for handling input
# about
TeleKit is a general-purpose library for Python projects.
You can parse this file in Python:
import telekit
chapters: dict[str, str] = telekit.chapters.read("help.txt")
print(chapters["intro"])
# Output: "Welcome to TeleKit library. Here are the available commands:"
print(chapters["entry"])
# Output: "/entry — Example command for handling input"
This method allows you to separate content from code, making it easier to manage large texts or structured help documentation. It's especially useful for commands like /help, where each section can be displayed individually in a bot interface.
Examples and Solutions
Counter
import telebot.types # type: ignore
import telekit
import typing
class Entry2Handler(telekit.Handler):
# ------------------------------------------
# Initialization
# ------------------------------------------
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes the message handler for the '/entry' command.
"""
@bot.message_handler(commands=['entry2'])
def handler(message: telebot.types.Message) -> None:
cls(message).handle()
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def handle(self) -> None:
chain: telekit.Chain = self.get_chain()
chain.sender.set_title("Hello")
chain.sender.set_message("Welcome to the bot! Click the button below to start interacting.")
def counter_factory() -> typing.Callable[[int], int]:
count = 0
def counter(value: int=1) -> int:
nonlocal count
count += value
return count
return counter
click_counter = counter_factory()
@chain.inline_keyboard({"⊕": 1, "⊖": -1}, row_width=2)
def _(message: telebot.types.Message, value: int) -> None:
chain.sender.set_message(f"You clicked {click_counter(value)} times") # The title remains unchanged (Hello)
chain.edit() # Edit previous message
chain.send()
FAQ Pages
import telebot.types
import telekit
pages: dict[str, tuple[str, str]] = {}
for title, text in telekit.chapters.read("help.txt").items():
pages[title] = (title, text)
class HelpHandler(telekit.Handler):
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes the command handler.
"""
@bot.message_handler(commands=['help'])
def handler(message: telebot.types.Message) -> None:
cls(message).handle()
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def handle(self) -> None:
main: telekit.Chain = self.get_chain()
main.set_always_edit_previous_message(True)
main.sender.set_title("FAQ - Frequently Asked Questions")
main.sender.set_message("Here are some common questions and answers to help you get started:")
@main.inline_keyboard(pages)
def _(message: telebot.types.Message, value: tuple[str, str]) -> None:
page: telekit.Chain = self.get_child(main)
page.sender.set_title(value[0])
page.sender.set_message(value[1])
page.set_inline_keyboard({"« Back": main})
page.send()
main.send()
Registration
import telebot.types
import telekit
class UserData:
names: telekit.Vault = telekit.Vault(
path = "data_base",
table_name = "names",
key_field_name = "user_id",
value_field_name = "name"
)
ages: telekit.Vault = telekit.Vault(
path = "data_base",
table_name = "ages",
key_field_name = "user_id",
value_field_name = "age"
)
def __init__(self, chat_id: int):
self.chat_id = chat_id
def get_name(self, default: str | None=None) -> str | None:
return self.names.get(self.chat_id, default)
def set_name(self, value: str):
self.names[self.chat_id] = value
def get_age(self, default: int | None=None) -> int | None:
return self.ages.get(self.chat_id, default)
def set_age(self, value: int):
self.ages[self.chat_id] = value
class EntryHandler(telekit.Handler):
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes the command handler.
"""
@bot.message_handler(commands=['entry'])
def handler(message: telebot.types.Message) -> None:
cls(message).handle()
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def handle(self) -> None:
self._user_data = UserData(self.message.chat.id)
self.entry_name()
# -------------------------------
# NAME HANDLING
# -------------------------------
# The message parameter is optional,
# but you can receive it to access specific information
def entry_name(self, message: telebot.types.Message | None=None) -> None:
self.chain.sender.set_title("⌨️ What`s your name?")
self.chain.sender.set_message("Please, send a text message")
self.add_name_listener()
name: str | None = self._user_data.get_name( # from own data base
default=self.user.get_username() # from telebot API
)
if name:
self.chain.set_entry_suggestions([name])
self.chain.edit()
def add_name_listener(self):
@self.chain.entry_text(delete_user_response=True)
def _(message: telebot.types.Message, name: str) -> None:
self.chain.sender.set_title(f"👋 Bonjour, {name}!")
self.chain.sender.set_message(f"Is that your name?")
self._user_data.set_name(name)
self.chain.set_inline_keyboard(
{
"« Change": self.entry_name,
"Yes »": self.entry_age,
}, row_width=2
)
self.chain.edit()
# -------------------------------
# AGE HANDLING
# -------------------------------
def entry_age(self, message: telebot.types.Message | None=None) -> None:
self.chain.sender.set_title("⏳ How old are you?")
self.chain.sender.set_message("Please, send a numeric message")
self.add_age_listener()
age: int | None = self._user_data.get_age()
if age:
self.chain.set_entry_suggestions([str(age)])
self.chain.edit()
def add_age_listener(self):
@self.chain.entry_text(
filter_message=lambda message, text: text.isdigit() and 0 < int(text) < 130,
delete_user_response=True
)
def _(message: telebot.types.Message, text: str) -> None:
self._user_data.set_age(int(text))
self.chain.sender.set_title(f"😏 {text} years old?")
self.chain.sender.set_message("Noted. Now I know which memes are safe to show you")
self.chain.set_inline_keyboard(
{
"« Change": self.entry_age,
"Ok »": self.show_result,
}, row_width=2
)
self.chain.edit()
# ------------------------------------------
# RESULT
# ------------------------------------------
def show_result(self):
name = self._user_data.get_name()
age = self._user_data.get_age()
self.chain.sender.set_title("😏 Well well well")
self.chain.sender.set_message(f"So your name is {name} and you're {age}? Fancy!")
self.chain.set_inline_keyboard({
"« No, change": self.entry_name,
}, row_width=2)
self.chain.edit()
Optimized version: minimal memory usage and no recursive creation of chain objects
Dialogue
import telebot.types
import telekit
import typing
class DialogueHandler(telekit.Handler):
# ------------------------------------------
# Initialization
# ------------------------------------------
@classmethod
def init_handler(cls, bot: telebot.TeleBot) -> None:
"""
Initializes message handlers
"""
@cls.on_text("Hello!", "hello!", "Hello", "hello")
def _(message: telebot.types.Message):
cls(message).handle_hello()
# ------------------------------------------
# Handling Logic
# ------------------------------------------
def handle_hello(self) -> None:
self.chain.sender.set_text("👋 Hello! What is your name?")
@self.chain.entry_text()
def _(message: telebot.types.Message, name: str):
self.handle_name(name)
self.chain.send()
def handle_name(self, name: str):
self._user_name: str = name
self.chain.sender.set_text(f"Nice! How are you?")
@self.chain.entry_text()
def _(message, feeling: str):
self.handle_feeling(feeling)
self.chain.send() # Sends new message (it's dialogue)
def handle_feeling(self, feeling: str):
self.chain.sender.set_text(f"Got it, {self._user_name.title()}! You feel: {feeling}")
self.chain.send()
Developer
Telegram: @TeleKitLib
Changelog:
0.1.1
Bug Fixes:
- Fixed an issue where
@self.chain.entry_text(delete_user_response=True)would delete the bot’s message ifset_entry_suggestionswas used.
0.1.0
New Features:
Handler Methods
- Added
simulate_user_messagemethod to programmatically simulate user messages. Useful for testing handlers or switching between commands without sending real Telegram messages:
self.simulate_user_message("/start")
New Decorators
- Added
entry_documentdecorator:
@self.chain.entry_document(allowed_extensions=(".zip",))
def doc_handler(message: telebot.types.Message, document: telebot.types.Document):
print(document.file_name, document)
- Added
entry_text_documentdecorator:
@self.chain.entry_text_document(allowed_extensions=(".txt", ".js"))
def text_document_handler(message: telebot.types.Message, text_document: telekit.types.TextDocument):
print(
text_document.text,
text_document.file_name,
text_document.encoding,
text_document.document
)
Logging Functionality
- Introduced a new
loggermodule to handle logging for the library and individual users. - Implemented full logging functionality across the Telekit library.
- Integrated logging into key components, including handlers, senders, and the server.
2025-11-08 17:20:37 | WARNING | senders.py | Failed to delete message 521. Maybe the user deleted it. Exception: A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: message to delete not found
2025-11-08 17:20:37 | WARNING | senders.py | Failed to edit message 521, sending new one instead. Exception: A request to the Telegram API was unsuccessful. Error code: 400. Description: Bad Request: message to edit not found
- Added methods to enable user-specific logging in the
Userclass:
# help.py [self = HelpHandler()]; [HelpHandler.handle(self)]:
# Call `self.user.enable_logging(1914626823, ...)` to enable logging for specific users.
self.user.enable_logging(1914626823)
self.user.logger.info(f"You (admin) clicked: {value[0]}")
# If no `chat_id`s are provided, logging is enabled for the current user (`self.user.chat_id`).
self.user.enable_logging()
self.user.logger.info(f"User clicked: {value[0]}")
2025-11-08 17:20:43 | INFO | help.py:61 | [IDIDIDIDID] User clicked: Another Page
Other Improvements:
- Updated error handling to log exceptions with appropriate severity levels.
- Typing improvements: New class
telekit.types
Bug Fixes:
- #1 Fixed! The main Telekit issue — Double Handling:
Previously, if a user sent two or more commands to the bot while it was offline, the bot would process all of them concurrently after restarting.
This behavior could cause unexpected results and race conditions.
Planned:
- Ability to disable logging
server.enable_logging(True) - Localization of the method effect
self.user.enable_logging()(Currently working globally)
0.0.11
- The message parameter for functions used in set_inline_keyboard is now optional. Handlers can be defined without requiring a message object.
- Refactor Parser class to accept data directly and improve error handling in read function
0.0.10
- Add delete_user_initial_message method to remove user's initial message
0.0.9
- Refactor imports and remove commented-out code
0.0.8
inline_keyboardandentrys no longer conflict- New
entry_photodecorator!
0.0.4
- New
@Handler.on_text()decorator – example available intelekit/example/example_handlers/on_text.py!
0.0.3
- Documentation update (README.md).
- Improved inline documentation within the library.
Handlernow automatically callsself.get_chain()during initialization.- Other fixes and preparation for release.
0.0.2
- Snapvault and Chapters packages were not loading. (BUG)
0.0.1
- Published
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file telekit-0.1.1.tar.gz.
File metadata
- Download URL: telekit-0.1.1.tar.gz
- Upload date:
- Size: 49.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a42796ac07de924458e56f34ba6c33eca9fa2668798de4af6624985039981f2
|
|
| MD5 |
a317c41ba5165212461f97e9b8070bf3
|
|
| BLAKE2b-256 |
31f67420698b395f0d06638922d9ca4ad5a121efdd2e8f2de1a1de517da61fb6
|
File details
Details for the file telekit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: telekit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 38.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32a1c065017b589c7e703eb79874bb7ac8ae5d09c7ff702f2758480f46079096
|
|
| MD5 |
a431372f95ff4cf7988e277db380ca48
|
|
| BLAKE2b-256 |
02e2fde47e530954dc08da4d75325020dae16af64067628f09d5fe47beda154e
|