Skip to content

Releases: smoxy/telegram-menu-builder

v0.4.0

Choose a tag to compare

@smoxy smoxy released this 04 Jun 10:37

telegram-menu-builder v0.4.0

This release makes menus usable outside a python-telegram-bot Application, adds an atomic
multi-operator claim
primitive, and ships first-class test helpers — the high-leverage set
from real downstream feedback.

Added

  • Application-free, budget-enforced menus. MenuBuilder.to_markup() (synchronous →
    telegram.InlineKeyboardMarkup) and MenuBuilder.to_raw() (synchronous → a plain Telegram Bot API
    dict {"inline_keyboard": [[...]]}, built directly from items so it can be consumed without
    python-telegram-bot) build a menu with no event loop, no storage, and no worker thread. Every
    button is encoded inline; any item that would otherwise spill to storage raises EncodingError
    (use build_async() for those). assert_inline() is a cheap pre-flight, and the new
    MenuBuilder(on_oversize="spill" | "error") policy makes build_async() fail loudly instead of
    silently spilling. Backed by a new synchronous CallbackEncoder.encode_inline().
  • Atomic claim / idempotency for multi-operator workflows. A new atomic set-if-absent primitive
    StorageBackend.add(key, data, ttl=None) -> bool (non-atomic default on BaseStorage so existing
    custom backends keep working; concurrency-safe overrides for MemoryStorage, RedisStorage via
    SET … NX, and SQLAlchemyStorage via a single transaction that frees expired rows then INSERTs
    no-op-on-conflict). On top of it, MenuRouter.claim(key, user_id, *, ttl=3600), who_claimed(key),
    and release(key) provide a single-winner guarantee — verified end-to-end against live
    PostgreSQL 16, Redis 7, and Valkey 8
    (concurrent claimers → exactly one wins).
  • Testing helpers — new telegram_menu_builder.testing module (standard-library unittest.mock
    only; imported as a submodule). simulate_tap(router, callback_data, ...) and
    tap(router, handler, /, **params) drive a MenuRouter with no live Telegram and return a
    TapResult (answered, answer_text, edited_text, handler_error); assert_inline(target)
    verifies a MenuBuilder / InlineKeyboardMarkup / raw dict contains only inline I:/IC: callback
    buttons (no S:/P: storage references).

Full changelog: v0.3.0...v0.4.0

v0.3.0

Choose a tag to compare

@smoxy smoxy released this 03 Jun 23:36

telegram-menu-builder v0.3.0

Two built-in storage backends land in this release — SQL (SQLAlchemy 2.0 async) and
Redis/Valkey — both verified end-to-end against live servers.

Added

  • Redis / Valkey backendRedisStorage on redis-py, with first-class Valkey support
    (RESP-compatible: point a redis:// URL at either server, or pass a duck-typed valkey-py
    client). Native server-side TTL, namespaced keys, owns-vs-borrows client lifecycle, SCAN-based
    clear/keys (never FLUSHDB), and a lazy [redis] import. Verified end-to-end against live
    Redis 7.4.9 and Valkey 8.1.8 (fakeredis covers the default test run). Valkey is the
    recommended option. Install: pip install "telegram-menu-builder[redis]".
  • SQL backendSQLAlchemyStorage for PostgreSQL/Supabase, MySQL/MariaDB, and SQLite via
    SQLAlchemy 2.0 (async); new optional extras [postgres] and [mysql]; explicit schema management
    via create_schema()/drop_schema(). Verified end-to-end against live PostgreSQL 16 and
    MariaDB 12.3.2 (suite gated by TMB_TEST_POSTGRES_URL / TMB_TEST_MYSQL_URL).

Changed

  • The [sql] extra now pins sqlalchemy[asyncio]>=2.0.30,<3.0.
  • Documentation refreshed across the storage, installation, dependency-audit, and development
    guides (per-DB driver matrix incl. the pure-Python aiomysql alternative to asyncmy, UTC
    expires_at handling, portable get_stats, Docker-based integration testing). Corrected the
    documented python-telegram-bot range to >=20.0,<22.8.

Full changelog: v0.2.0...v0.3.0

v0.2.0

Choose a tag to compare

@smoxy smoxy released this 03 Jun 18:43

telegram-menu-builder 0.2.0

This release fixes a critical correctness bug in async usage, hardens the
dependency posture, and adds a full documentation site, CI, and project tooling.

🐛 Fixed

  • Critical: callback data is no longer lost when a menu is built inside a running
    event loop. add_item() previously discarded the handler and parameters in async
    contexts (the normal Telegram-bot case), producing buttons with empty callback_data.
    Encoding is now deferred to build_async() so every item is encoded correctly.
  • MenuBuilder.build() now works when called inside a running event loop (it runs the
    async build on a short-lived worker thread) instead of raising RuntimeError. In async
    code, prefer await build_async().
  • add_submenu() no longer stores the non-serializable submenu builder in callback params;
    only a JSON-safe _submenu_id is stored, with the builder kept in an internal registry
    accessible via the new get_submenu().
  • __version__ is now single-sourced from package metadata (was hard-coded and drifted).
  • Hardened the deterministic dedup hash with hashlib.md5(..., usedforsecurity=False).

✨ Added

  • Exported the exception hierarchy (MenuBuilderError, EncodingError, DecodingError,
    StorageError, ValidationError) from the package root, plus MenuBuilder.get_submenu().
  • MkDocs Material documentation site (API reference, guides, security and
    dependency/CVE audit, Python-compatibility analysis).
  • Tests for the router, storage backends, type validators, and package metadata
    (coverage ~62% → ~90%).
  • CI workflow (ruff, black, mypy, pyright, pytest, pip-audit) on every push/PR, plus a
    docs-deploy workflow; SECURITY.md, Dependabot, and issue/PR templates.

🔧 Changed

  • Raised the pydantic floor to >=2.4 to exclude CVE-2024-3772 (ReDoS in pydantic
    email validation, fixed in 2.4.0). The library does not use email validation, so it was
    never exploitable here — this is defense-in-depth.
  • StorageStrategy now subclasses enum.StrEnum; refactored navigation buttons and
    MenuRouter.route() (no behavior change).

Full changelog: https://github.com/smoxy/telegram-menu-builder/blob/v0.2.0/CHANGELOG.md

Release v0.1.1

Release v0.1.1 Pre-release
Pre-release

Choose a tag to compare

@smoxy smoxy released this 08 Nov 22:24

[0.1.1] - 2025-11-08

Added

  • Comprehensive guide for using MenuBuilder with ConversationHandler
  • New example conversation_handler_menu.py demonstrating proper per_message configuration
  • Documentation file docs/conversation_handler_guide.md with best practices
  • Support for python-telegram-bot up to version 22.5

Changed

  • Updated dependency range: python-telegram-bot>=20.0,<22.6 (was <22.0)
  • Clarified ConversationHandler integration requirements in documentation

Fixed

  • Documented solution for CallbackQueryHandler in fallbacks not working with per_message=False
  • Added warning about PTBUserWarning when using incompatible handler types with per_message=True

Release v0.1.0

Release v0.1.0 Pre-release
Pre-release

Choose a tag to compare

@smoxy smoxy released this 08 Nov 20:25
fix: resolve linting errors - merge startswith calls, move imports to…