# telegram_menu package
<img src="https://img.shields.io/badge/python-3.8-blue.svg" alt="drawing"/> <img src="https://img.shields.io/badge/python-3.11-blue.svg" alt="drawing"/>
<br/>
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
```bash
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:
```python
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:
```python
second_menu = SecondMenuMessage(navigation)
self.add_button(label="Second menu", callback=second_menu)
```
Then define the second message:
```python
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()``.
```python
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
<img src="https://raw.githubusercontent.com/mevellea/telegram_menu/master/resources/packages.png" width="400"/>
Following class diagram describes all public interfaces:
<img src="https://raw.githubusercontent.com/mevellea/telegram_menu/master/resources/classes.png" width="800"/>
[navigation.py]: https://github.com/mevellea/telegram_menu/blob/master/telegram_menu/navigation.py
[models.py]: https://github.com/mevellea/telegram_menu/blob/master/telegram_menu/models.py
[create a Telegram bot]: https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API
[Demo: TelegramMenuSession]: https://raw.githubusercontent.com/mevellea/telegram_menu/master/resources/demo.gif
## Unit-tests
To execute the test suite, run the following command and then start a session from a Telegram client with the keyword **/start**.
```bash
python -m unittest
```
Raw data
{
"_id": null,
"home_page": "https://github.com/mevellea/telegram_menu",
"name": "telegram-menu",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "telegram",
"author": "Armel Mevellec",
"author_email": "mevellea@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/8b/c2/68eae09ad4108091103c5618a2ea643e47465d863fb6e8eab35b9d609d98/telegram_menu-2.1.3.tar.gz",
"platform": "any",
"description": "# telegram_menu package\r\n\r\n<img src=\"https://img.shields.io/badge/python-3.8-blue.svg\" alt=\"drawing\"/> <img src=\"https://img.shields.io/badge/python-3.11-blue.svg\" alt=\"drawing\"/>\r\n<br/>\r\nA python library to generate navigation menus using Telegram Bot API.\r\n\r\nFeatures:\r\n\r\n* Menu navigation using tree structure, unlimited depth\r\n* Support for sending pictures (local file or url), stickers, notifications, webapps and polls\r\n* Session manager with multiple users connecting to the same bot\r\n* Messages can read text input from the keyboard\r\n* Automatic deletion of messages when configurable timer has expired\r\n* Integration of HTML formatting + emojis\r\n\r\n> **_[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.\r\n\r\nHere is an example of navigation with menus and inlined buttons:\r\n\r\n![Demo: TelegramMenuSession] \r\n\r\n## Installation\r\n\r\n```bash\r\npip install telegram_menu\r\n```\r\n\r\n## Getting Started\r\n\r\nYou 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.\r\n\r\nA session can be started with the keyword ``/start`` from a Telegram client.\r\n\r\nFollowing code block creates a ``Hello, World!`` message:\r\n\r\n```python\r\nfrom telegram_menu import BaseMessage, TelegramMenuSession, NavigationHandler\r\n\r\nAPI_KEY = \"put_your_telegram_bot_api_key_here\"\r\n\r\nclass StartMessage(BaseMessage):\r\n \"\"\"Start menu, create all app sub-menus.\"\"\"\r\n\r\n LABEL = \"start\"\r\n\r\n def __init__(self, navigation: NavigationHandler) -> None:\r\n \"\"\"Init StartMessage class.\"\"\"\r\n super().__init__(navigation, StartMessage.LABEL)\r\n\r\n def update(self) -> str:\r\n \"\"\"Update message content.\"\"\"\r\n return \"Hello, world!\"\r\n\r\nTelegramMenuSession(API_KEY).start(StartMessage)\r\n```\r\n\r\nYou can add new buttons in ``StartMessage``, using ``self.add_button()`` method. \r\nThe callback of a button can be used to update the content of the current message, or to open a new menu.\r\nFor example, adding these lines in the constructor of the previous class will open a second menu:\r\n\r\n```python\r\nsecond_menu = SecondMenuMessage(navigation)\r\nself.add_button(label=\"Second menu\", callback=second_menu)\r\n```\r\n\r\nThen define the second message:\r\n\r\n```python\r\nclass SecondMenuMessage(BaseMessage):\r\n \"\"\"Second menu, create an inlined button.\"\"\"\r\n\r\n LABEL = \"action\"\r\n\r\n def __init__(self, navigation: NavigationHandler) -> None:\r\n \"\"\"Init SecondMenuMessage class.\"\"\"\r\n super().__init__(navigation, StartMessage.LABEL, inlined=True)\r\n\r\n # 'run_and_notify' function executes an action and return a string as Telegram notification.\r\n self.add_button(label=\"Action\", callback=self.run_and_notify)\r\n # 'back' button goes back to previous menu\r\n self.add_button_back()\r\n # 'home' button goes back to main menu\r\n self.add_button_home()\r\n\r\n def update(self) -> str:\r\n \"\"\"Update message content.\"\"\"\r\n # emoji can be inserted with a keyword enclosed with ::\r\n # list of emojis can be found at this link: https://www.webfx.com/tools/emoji-cheat-sheet/\r\n return \":warning: Second message\"\r\n\r\n @staticmethod\r\n def run_and_notify() -> str:\r\n \"\"\"Update message content.\"\"\"\r\n return \"This is a notification\"\r\n```\r\n\r\nAn application message can contain several inlined buttons, the behavior is similar to MenuMessage buttons.\r\nTo define a message as inlined, the property ``inlined`` must be set to ``True``.\r\n\r\nA message can also be used to create a poll or show a picture, using property ``btype``.\r\n\r\nThe 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. \r\n\r\nThe default number of buttons per row is 2 for base keyboards, 4 for inlined keyboards, \r\nto create a new row the property ``new_row`` can be set to ``True`` when calling ``add_button()``.\r\n\r\n```python\r\nfrom telegram_menu import MenuButton\r\n\r\n# 'get_content' function must return the text content to display, eventually with Markdown formatting\r\nself.add_button(label=\"Display content\", callback=self.get_content, btype=ButtonType.MESSAGE)\r\n\r\n# 'get_picture' function must return the path of a picture to display in Telegram\r\nself.add_button(label=\"Show picture\", callback=self.get_picture, btype=ButtonType.PICTURE, new_row=True)\r\n\r\n# 'get_sticker' function must return the path of a sticker to display in Telegram\r\nself.add_button(label=\"Show sticker\", callback=self.get_sticker, btype=ButtonType.STICKER)\r\n\r\n# 'webapp_cb' function will receive the result of the given web-app\r\nwebapp_url = \"https://python-telegram-bot.org/static/webappbot\"\r\nself.add_button(label=\"Show picture\", callback=self.webapp_cb, web_app_url=webapp_url)\r\n\r\n# New buttons can be added to the 'keyboard' property of the message instance too.\r\n# Next poll message will get items to display from function 'get_playlists_arg', and run 'select_playlist' when \r\n# the poll button is selected, identified with emoji 'closed_book'\r\npoll_button = MenuButton(\r\n label=\":closed_book:\", callback=self.select_playlist, btype=ButtonType.POLL, args=self.get_playlists_arg()\r\n)\r\nself.keyboard.append([poll_button])\r\n```\r\n\r\n## Structure\r\n\r\nClasses in package ``telegram_menu`` are stored in 2 python files:\r\n\r\n\r\n* [navigation.py] - Main interface, menu and message generation and management\r\n* [models.py] - Menu and message models, classes definition\r\n\r\n<img src=\"https://raw.githubusercontent.com/mevellea/telegram_menu/master/resources/packages.png\" width=\"400\"/>\r\n\r\nFollowing class diagram describes all public interfaces:\r\n\r\n<img src=\"https://raw.githubusercontent.com/mevellea/telegram_menu/master/resources/classes.png\" width=\"800\"/>\r\n\r\n[navigation.py]: https://github.com/mevellea/telegram_menu/blob/master/telegram_menu/navigation.py\r\n[models.py]: https://github.com/mevellea/telegram_menu/blob/master/telegram_menu/models.py\r\n[create a Telegram bot]: https://github.com/python-telegram-bot/python-telegram-bot/wiki/Introduction-to-the-API\r\n[Demo: TelegramMenuSession]: https://raw.githubusercontent.com/mevellea/telegram_menu/master/resources/demo.gif\r\n\r\n## Unit-tests\r\n\r\nTo execute the test suite, run the following command and then start a session from a Telegram client with the keyword **/start**.\r\n\r\n```bash\r\npython -m unittest\r\n```\r\n\r\n",
"bugtrack_url": null,
"license": "GNU GPLv3",
"summary": "A python library to generate navigation menus using Telegram Bot API.",
"version": "2.1.3",
"project_urls": {
"Homepage": "https://github.com/mevellea/telegram_menu"
},
"split_keywords": [
"telegram"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8bc268eae09ad4108091103c5618a2ea643e47465d863fb6e8eab35b9d609d98",
"md5": "d8bacb69575b4139cfde4cfacee76e2a",
"sha256": "9b270fddb0d4ad37c0fb2902b133d24510a6af68afbdf3d44c51cb97d017e2a1"
},
"downloads": -1,
"filename": "telegram_menu-2.1.3.tar.gz",
"has_sig": false,
"md5_digest": "d8bacb69575b4139cfde4cfacee76e2a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 33104,
"upload_time": "2023-09-14T18:32:35",
"upload_time_iso_8601": "2023-09-14T18:32:35.094981Z",
"url": "https://files.pythonhosted.org/packages/8b/c2/68eae09ad4108091103c5618a2ea643e47465d863fb6e8eab35b9d609d98/telegram_menu-2.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-09-14 18:32:35",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mevellea",
"github_project": "telegram_menu",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "telegram-menu"
}