Skip to main content

Lightweight Telegram Bot API client - send messages, keyboards, webhooks, async, zero deps

Project description

telegram-bot-lite-py

Lightweight Telegram Bot API client — send messages, build keyboards, handle webhooks, all async with zero dependencies.

Pure Python ≥ 3.9. No httpx, no aiohttp, no requests. Just the stdlib.

pip install telegram-bot-lite-py

Features

  • Async-first — built on asyncio + stdlib SSL
  • Full Bot API coverage: messages, media, keyboards, commands, callbacks
  • Composable update filters (&, |, ~)
  • Long-polling and webhook modes
  • Fluent keyboard builders
  • Typed dataclasses for every API object
  • Zero third-party dependencies

Quick Start

Echo bot (long polling)

import asyncio
from telegram_bot_lite_py import TelegramBot, Dispatcher
from telegram_bot_lite_py.filters import Filters

bot = TelegramBot("YOUR_BOT_TOKEN")
dp = Dispatcher(bot)

@dp.on_command("start")
async def on_start(bot, update):
    await bot.reply(update.message, "Hello! I'm alive 🤖")

@dp.on_message(Filters.text)
async def on_text(bot, update):
    await bot.reply(update.message, f"You said: {update.message.text}")

dp.run_polling()

One-shot notification (no dispatcher needed)

import asyncio
from telegram_bot_lite_py import TelegramBot

async def notify():
    bot = TelegramBot("YOUR_BOT_TOKEN")
    await bot.send_message(CHAT_ID, "<b>Deploy complete!</b>", parse_mode="HTML")

asyncio.run(notify())

Installation

pip install telegram-bot-lite-py

Requires Python 3.9+. No other packages needed.


API Reference

TelegramBot

from telegram_bot_lite_py import TelegramBot

bot = TelegramBot(
    token="YOUR_BOT_TOKEN",
    timeout=30.0,        # per-request timeout in seconds
    parse_mode="HTML",   # default parse mode: "HTML", "Markdown", "MarkdownV2", or None
)

Sending messages

Method Description
await bot.send_message(chat_id, text, *, parse_mode, reply_markup, ...) Send a text message
await bot.reply(message, text, *, parse_mode, reply_markup) Reply to a specific message
await bot.notify(chat_id, text) Shorthand alias for send_message
await bot.send_photo(chat_id, photo, *, caption, ...) Send photo by file_id, URL, or bytes
await bot.send_document(chat_id, document, *, caption, ...) Send document
await bot.send_audio(chat_id, audio, *, caption, performer, title, ...) Send audio
await bot.send_video(chat_id, video, *, caption, duration, ...) Send video
await bot.send_location(chat_id, lat, lon, ...) Send a map pin
await bot.send_contact(chat_id, phone, first_name, ...) Send a contact
await bot.send_chat_action(chat_id, action) Show "typing…" or other indicators
await bot.forward_message(chat_id, from_chat_id, message_id) Forward a message
await bot.copy_message(chat_id, from_chat_id, message_id) Copy (without forward tag)

Editing & deleting

Method Description
await bot.edit_message_text(text, *, chat_id, message_id, ...) Edit message text
await bot.edit_message_reply_markup(*, chat_id, message_id, reply_markup) Update keyboard only
await bot.delete_message(chat_id, message_id) Delete a message

Callback queries

Method Description
await bot.answer_callback_query(callback_query_id, *, text, show_alert, url) Answer an inline button press

Chat management

Method Description
await bot.get_chat(chat_id) Fetch Chat info
await bot.leave_chat(chat_id) Leave a group/channel
await bot.ban_chat_member(chat_id, user_id, ...) Ban a user
await bot.unban_chat_member(chat_id, user_id) Unban a user
await bot.get_chat_member_count(chat_id) Member count

Bot setup

Method Description
await bot.get_me() Fetch the bot's User object
await bot.set_my_commands(commands) Set the command list shown in clients
await bot.get_my_commands() Get current commands
await bot.delete_my_commands() Remove all commands

Webhook

Method Description
await bot.set_webhook(url, *, secret_token, max_connections, ...) Register a webhook
await bot.delete_webhook(*, drop_pending_updates) Remove the webhook
await bot.get_webhook_info() Fetch current webhook status

Files

Method Description
await bot.get_file(file_id) Fetch File metadata
bot.get_file_url(file_path) Build the download URL for a File

Dispatcher

from telegram_bot_lite_py import Dispatcher

dp = Dispatcher(bot, workers=4)

Decorators

@dp.on_command("start", "help")
async def cmd_handler(bot, update): ...

@dp.on_message(Filters.text & ~Filters.command("start"))
async def text_handler(bot, update): ...

@dp.on_callback("confirm", "cancel")
async def callback_handler(bot, update): ...

@dp.on_callback(prefix="page:")
async def paginate(bot, update): ...

@dp.on_error()
async def error_handler(bot, update, exc): ...

Low-level registration

from telegram_bot_lite_py.filters import Filters

dp.add_handler(my_fn, Filters.photo, priority=10)

Running

# Blocking (runs asyncio event loop internally)
dp.run_polling(timeout=30, drop_pending=True)

# Inside an existing event loop
await dp.start_polling(timeout=30)

Filters

from telegram_bot_lite_py.filters import Filters

Filters.message          # any message update
Filters.edited_message   # edited message
Filters.callback_query   # callback query
Filters.channel_post     # channel post

Filters.text             # message has text
Filters.photo            # message has photo
Filters.document         # message has document
Filters.audio
Filters.video
Filters.location
Filters.contact
Filters.sticker

Filters.private          # private chat
Filters.group            # group or supergroup
Filters.channel          # channel

Filters.command("start", "help")
Filters.regex(r"order #\d+")
Filters.text_equals("yes", "no")
Filters.text_contains("hello")
Filters.user(123456, 789012)     # whitelist by user_id
Filters.chat(-100123456789)      # whitelist by chat_id
Filters.callback_data("ok", "cancel")
Filters.callback_prefix("page:")
Filters.custom_filter(lambda u: u.effective_user.is_premium)

Combine with &, |, ~:

private_text = Filters.text & Filters.private
not_bot      = ~Filters.user(bot_id)
media        = Filters.photo | Filters.video | Filters.document

Keyboard builders

Inline keyboards

from telegram_bot_lite_py.keyboards import InlineKeyboard, inline_keyboard

# Fluent builder
kb = (
    InlineKeyboard()
    .button("Yes", callback_data="yes")
    .button("No", callback_data="no")
    .row()
    .button("Visit", url="https://sarmkadan.com")
    .build()
)

# Compact factory
kb = inline_keyboard(
    [("Option A", "a"), ("Option B", "b")],
    [("Cancel", "cancel")],
)

await bot.send_message(chat_id, "Choose:", reply_markup=kb)

Reply keyboards

from telegram_bot_lite_py.keyboards import ReplyKeyboard, reply_keyboard

# Fluent builder
kb = (
    ReplyKeyboard(resize=True, one_time=True)
    .button("Share Location", request_location=True)
    .row()
    .button("Share Contact", request_contact=True)
    .build()
)

# Compact factory
kb = reply_keyboard(["Yes", "No"], ["Maybe", "Cancel"], resize=True)

await bot.send_message(chat_id, "Choose:", reply_markup=kb)

Remove / force reply

from telegram_bot_lite_py.keyboards import remove_keyboard, force_reply

await bot.send_message(chat_id, "Keyboard removed", reply_markup=remove_keyboard())
await bot.send_message(chat_id, "Enter your name:", reply_markup=force_reply(placeholder="Your name"))

Webhook server

import ssl
from telegram_bot_lite_py import TelegramBot, Dispatcher, WebhookServer

bot = TelegramBot("YOUR_BOT_TOKEN")
dp  = Dispatcher(bot)

@dp.on_command("start")
async def start(bot, update):
    await bot.reply(update.message, "Hello from webhook!")

# Optional TLS termination
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("cert.pem", "key.pem")

server = WebhookServer(
    dp,
    host="0.0.0.0",
    port=8443,
    path="/webhook",
    secret_token="my-secret",
    ssl_context=ctx,
)

# Register webhook then start
import asyncio

async def main():
    await bot.set_webhook(
        "https://your-domain.com/webhook",
        secret_token="my-secret",
        max_connections=40,
    )
    await server.start()
    # keep running
    await asyncio.Event().wait()

asyncio.run(main())

Types

All Telegram API objects are plain Python dataclasses.

from telegram_bot_lite_py import Update, Message, User, Chat, CallbackQuery

update: Update
update.update_id
update.message           # Message | None
update.edited_message    # Message | None
update.callback_query    # CallbackQuery | None
update.effective_message # first non-None of message / edited_message / channel_post
update.effective_chat    # Chat | None
update.effective_user    # User | None

message: Message
message.message_id
message.chat             # Chat
message.from_user        # User | None
message.text             # str | None
message.content_type     # "text" | "photo" | "document" | ...
message.get_command()    # "/start" | None
message.get_args()       # "arg1 arg2" – everything after the command

user: User
user.id
user.full_name           # "First Last"
user.mention             # "@username" or full name

chat: Chat
chat.id
chat.type                # "private" | "group" | "supergroup" | "channel"
chat.is_private          # bool
chat.is_group            # bool
chat.display_name        # title or first_name

Error handling

from telegram_bot_lite_py.exceptions import (
    TelegramAPIError,
    RetryAfterError,
    ForbiddenError,
    NetworkError,
)

@dp.on_error()
async def handle_error(bot, update, exc):
    if isinstance(exc, RetryAfterError):
        print(f"Flood limit. Retry after {exc.retry_after}s")
    elif isinstance(exc, ForbiddenError):
        print("Bot was blocked by user")
    elif isinstance(exc, NetworkError):
        print(f"Network problem: {exc}")
    else:
        print(f"Unhandled error: {exc}")

Examples

Notification bot

import asyncio
from telegram_bot_lite_py import TelegramBot

async def alert(chat_id: int, message: str):
    bot = TelegramBot("YOUR_TOKEN")
    await bot.send_message(chat_id, f"<b>Alert</b>\n{message}", parse_mode="HTML")

asyncio.run(alert(-100123456789, "Server CPU above 90%"))

Paginated inline buttons

@dp.on_command("list")
async def cmd_list(bot, update):
    kb = inline_keyboard(
        [("Item 1", "item:1"), ("Item 2", "item:2")],
        [("< Prev", "page:0"), ("Next >", "page:2")],
    )
    await bot.reply(update.message, "Choose an item:", reply_markup=kb)

@dp.on_callback(prefix="item:")
async def on_item(bot, update):
    item_id = update.callback_query.data.split(":")[1]
    await bot.answer_callback_query(update.callback_query.id, text=f"Selected item {item_id}")

@dp.on_callback(prefix="page:")
async def on_page(bot, update):
    page = int(update.callback_query.data.split(":")[1])
    await bot.answer_callback_query(update.callback_query.id, text=f"Page {page}")

Admin-only commands

ADMIN_IDS = [123456789]

@dp.on_command("ban", priority=100)
async def cmd_ban(bot, update):
    if update.effective_user.id not in ADMIN_IDS:
        await bot.reply(update.message, "Access denied.")
        return
    # ... ban logic

License

MIT — see LICENSE.

© 2024 Vladyslav Zaiets — sarmkadan.com

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

telegram_bot_lite_py-1.0.0.tar.gz (21.8 kB view details)

Uploaded Source

Built Distribution

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

telegram_bot_lite_py-1.0.0-py3-none-any.whl (26.8 kB view details)

Uploaded Python 3

File details

Details for the file telegram_bot_lite_py-1.0.0.tar.gz.

File metadata

  • Download URL: telegram_bot_lite_py-1.0.0.tar.gz
  • Upload date:
  • Size: 21.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for telegram_bot_lite_py-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3b400fb1c6691aa237beca3e9bfa7367779786f59f76949e3375c0f0acfaaa2f
MD5 a525eef11b0d494cb2c7055d5d3c45ed
BLAKE2b-256 2b7523478ed4b371a0ad7d6e16c0ebb60d421c4e9db8d08366eb3d73ab29c24e

See more details on using hashes here.

File details

Details for the file telegram_bot_lite_py-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for telegram_bot_lite_py-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a21fb98e03c329b79bc7e9f1ea4d917939b0a003540213331e6352e89531c28d
MD5 de4fab18d823e2e9b0769973e3fbae23
BLAKE2b-256 82a09587feec6002becec1ce54b068be82697f0426bcb47fb151b7caeee1fd56

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