Skip to content

A python library to generate navigation menus using Telegram Bot API

License

Notifications You must be signed in to change notification settings

mevellea/telegram_menu

Repository files navigation

telegram_menu package

drawing drawing
A python library to generate navigation menus using Telegram Bot API.

Features:

  • Menu navigation using tree structure, unlimited depth
  • Support for sending pictures (local file or url), stickers, notifications, webapps and polls
  • Session manager with multiple users connecting to the same bot
  • Messages can read text input from the keyboard
  • Automatic deletion of messages when configurable timer has expired
  • Integration of HTML formatting + emojis

[2023-01] NOTE: asyncio support was added in version 2.0.0. Previous versions use the oldest non-asynchronous version of python-telegram-bot and are not compatible.

Here is an example of navigation with menus and inlined buttons:

Demo: TelegramMenuSession

Installation

pip install telegram_menu

Getting Started

You first need to create a Telegram bot, then you can refer to the sample code in tests\test_connection.py to run a complete use-case.

A session can be started with the keyword /start from a Telegram client.

Following code block creates a Hello, World! message:

from telegram_menu import BaseMessage, TelegramMenuSession, NavigationHandler

API_KEY = "put_your_telegram_bot_api_key_here"

class StartMessage(BaseMessage):
    """Start menu, create all app sub-menus."""

    LABEL = "start"

    def __init__(self, navigation: NavigationHandler) -> None:
        """Init StartMessage class."""
        super().__init__(navigation, StartMessage.LABEL)

    def update(self) -> str:
        """Update message content."""
        return "Hello, world!"

TelegramMenuSession(API_KEY).start(StartMessage)

You can add new buttons in StartMessage, using self.add_button() method. The callback of a button can be used to update the content of the current message, or to open a new menu. For example, adding these lines in the constructor of the previous class will open a second menu:

second_menu = SecondMenuMessage(navigation)
self.add_button(label="Second menu", callback=second_menu)

Then define the second message:

class SecondMenuMessage(BaseMessage):
    """Second menu, create an inlined button."""

    LABEL = "action"

    def __init__(self, navigation: NavigationHandler) -> None:
        """Init SecondMenuMessage class."""
        super().__init__(navigation, StartMessage.LABEL, inlined=True)

        # 'run_and_notify' function executes an action and return a string as Telegram notification.
        self.add_button(label="Action", callback=self.run_and_notify)
        # 'back' button goes back to previous menu
        self.add_button_back()
        # 'home' button goes back to main menu
        self.add_button_home()

    def update(self) -> str:
        """Update message content."""
        # emoji can be inserted with a keyword enclosed with ::
        # list of emojis can be found at this link: https://www.webfx.com/tools/emoji-cheat-sheet/
        return ":warning: Second message"

    @staticmethod
    def run_and_notify() -> str:
        """Update message content."""
        return "This is a notification"

An application message can contain several inlined buttons, the behavior is similar to MenuMessage buttons. To define a message as inlined, the property inlined must be set to True.

A message can also be used to create a poll or show a picture, using property btype.

The input field can be set using the property input_field (non-inlined messages only). You can use the keyword <disable> to restore the default behaviour.

The default number of buttons per row is 2 for base keyboards, 4 for inlined keyboards, to create a new row the property new_row can be set to True when calling add_button().

from telegram_menu import MenuButton

# 'get_content' function must return the text content to display, eventually with Markdown formatting
self.add_button(label="Display content", callback=self.get_content, btype=ButtonType.MESSAGE)

# 'get_picture' function must return the path of a picture to display in Telegram
self.add_button(label="Show picture", callback=self.get_picture, btype=ButtonType.PICTURE, new_row=True)

# 'get_sticker' function must return the path of a sticker to display in Telegram
self.add_button(label="Show sticker", callback=self.get_sticker, btype=ButtonType.STICKER)

# 'webapp_cb' function will receive the result of the given web-app
webapp_url = "https://python-telegram-bot.org/static/webappbot"
self.add_button(label="Show picture", callback=self.webapp_cb, web_app_url=webapp_url)

# New buttons can be added to the 'keyboard' property of the message instance too.
# Next poll message will get items to display from function 'get_playlists_arg', and run 'select_playlist' when 
# the poll button is selected, identified with emoji 'closed_book'
poll_button = MenuButton(
    label=":closed_book:", callback=self.select_playlist, btype=ButtonType.POLL, args=self.get_playlists_arg()
)
self.keyboard.append([poll_button])

Structure

Classes in package telegram_menu are stored in 2 python files:

  • navigation.py - Main interface, menu and message generation and management
  • models.py - Menu and message models, classes definition

Following class diagram describes all public interfaces:

Unit-tests

To execute the test suite, run the following command and then start a session from a Telegram client with the keyword /start.

python -m unittest

About

A python library to generate navigation menus using Telegram Bot API

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published