Skip to content

Arbitrary callback data #1844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 54 commits into from
Jun 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
0b463d1
Allow arbitrary callback data and sign it
Bibo-Joshi Mar 22, 2020
f6ce586
Add tests
Bibo-Joshi Mar 23, 2020
6b98c0a
Allow callable for pattern in CallbackQueryHandler
Bibo-Joshi Mar 23, 2020
e556dcb
Make pytest happier
Bibo-Joshi Mar 25, 2020
ca2fbb5
Make it opt-in
Bibo-Joshi Apr 15, 2020
6729b72
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Jan 3, 2021
1f5e20e
pre-commit
Bibo-Joshi Jan 3, 2021
dfcc308
tests
Bibo-Joshi Jan 3, 2021
eb9b64f
CallbackDataCache
Bibo-Joshi Jan 3, 2021
4e932ab
Update integration into bot, get tests to work and add some new ones
Bibo-Joshi Jan 3, 2021
df65f62
CQHandler, Persistence, Tests
Bibo-Joshi Jan 4, 2021
d987d6d
Minor tweaks
Bibo-Joshi Jan 4, 2021
32479b3
Try increasing code coverage
Bibo-Joshi Jan 4, 2021
7bafe1a
Fix that one failing test
Bibo-Joshi Jan 4, 2021
ed7a143
Don't sign the data
Bibo-Joshi Jan 6, 2021
524d776
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Jan 10, 2021
2d95aee
Another rework. no tests & stuff yet.
Bibo-Joshi Jan 10, 2021
e92f3b8
Introduce tg.ext.bot and move CallbackDataCache to ext
Bibo-Joshi Jan 23, 2021
c17a8be
Introduce cachetools
Bibo-Joshi Jan 23, 2021
810bc30
Get started on tests
Bibo-Joshi Jan 23, 2021
02f35b8
Finish tests & some other stuff
Bibo-Joshi Jan 24, 2021
82abd74
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Jan 24, 2021
e5b0815
Work on some more things
Bibo-Joshi Jan 24, 2021
19d2124
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Feb 11, 2021
a53ce6a
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Feb 28, 2021
a18c8d6
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Mar 14, 2021
4a2eec3
Update pre-commits additional_reqs
Bibo-Joshi Mar 14, 2021
d5818ce
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Apr 15, 2021
6ba08fe
Move CDC & ICD to tg.ext & some minor things
Bibo-Joshi Apr 20, 2021
8701843
Add some comments
Bibo-Joshi Apr 21, 2021
e83acfa
Update CDC.process_message and a bunch of new tests
Bibo-Joshi Apr 21, 2021
83bb78e
Fix a thing
Bibo-Joshi Apr 21, 2021
2bae211
Fine tuning & More tests & Webhook-Support (can't belive, I've missed…
Bibo-Joshi Apr 22, 2021
e470f8c
IKB.update_callback_data & Avoid returns for in-place functions
Bibo-Joshi Apr 23, 2021
f8e95da
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi May 28, 2021
7868cb5
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi May 28, 2021
f307f6d
Review
Bibo-Joshi May 29, 2021
b2454a2
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi May 29, 2021
58635a8
Add slot tests for new classes
Bibo-Joshi May 30, 2021
ce6db97
Fix tests
Bibo-Joshi May 30, 2021
3748ebb
Rename ext.Bot to ext.ExtBot
Bibo-Joshi May 30, 2021
ff980a0
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi May 30, 2021
d6e4b0f
pre-commit
Bibo-Joshi May 30, 2021
57a5fb0
address first review comments
Bibo-Joshi May 31, 2021
6820367
Bump pre-commit versions
Bibo-Joshi Jun 1, 2021
ce4f11b
More review
Bibo-Joshi Jun 1, 2021
1076700
Fix DictPersistence & add versioning directives
Bibo-Joshi Jun 2, 2021
5f42b08
Add example
Bibo-Joshi Jun 2, 2021
da08e30
Drop double copying from persistence & adjust tests
Bibo-Joshi Jun 3, 2021
cb2fba9
Review
Bibo-Joshi Jun 5, 2021
ef63946
Up coverage
Bibo-Joshi Jun 5, 2021
9559bc5
DeepSource
Bibo-Joshi Jun 5, 2021
286b63f
Even more coverage
Bibo-Joshi Jun 5, 2021
7233af7
Merge branch 'master' into arbitrary-callback-data
Bibo-Joshi Jun 6, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ Hey! You're PRing? Cool! Please have a look at the below checklist. It's here to
- [ ] Added new filters for new message (sub)types
- [ ] Added or updated documentation for the changed class(es) and/or method(s)
- [ ] Updated the Bot API version number in all places: `README.rst` and `README_RAW.rst` (including the badge), as well as `telegram.constants.BOT_API_VERSION`
- [ ] Added logic for arbitrary callback data in `tg.ext.Bot` for new methods that either accept a `reply_markup` in some form or have a return type that is/contains `telegram.Message`
9 changes: 6 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ repos:
- --diff
- --check
- repo: https://gitlab.com/pycqa/flake8
rev: 3.9.1
rev: 3.9.2
hooks:
- id: flake8
- repo: https://github.com/PyCQA/pylint
rev: v2.8.2
rev: v2.8.3
hooks:
- id: pylint
files: ^(telegram|examples)/.*\.py$
Expand All @@ -24,6 +24,7 @@ repos:
- certifi
- tornado>=6.1
- APScheduler==3.6.3
- cachetools==4.2.2
- . # this basically does `pip install -e .`
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.812
Expand All @@ -35,6 +36,7 @@ repos:
- certifi
- tornado>=6.1
- APScheduler==3.6.3
- cachetools==4.2.2
- . # this basically does `pip install -e .`
- id: mypy
name: mypy-examples
Expand All @@ -46,9 +48,10 @@ repos:
- certifi
- tornado>=6.1
- APScheduler==3.6.3
- cachetools==4.2.2
- . # this basically does `pip install -e .`
- repo: https://github.com/asottile/pyupgrade
rev: v2.13.0
rev: v2.19.1
hooks:
- id: pyupgrade
files: ^(telegram|examples|tests)/.*\.py$
Expand Down
8 changes: 8 additions & 0 deletions docs/source/telegram.ext.callbackdatacache.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/callbackdatacache.py

telegram.ext.CallbackDataCache
==============================

.. autoclass:: telegram.ext.CallbackDataCache
:members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/source/telegram.ext.extbot.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/extbot.py

telegram.ext.ExtBot
===================

.. autoclass:: telegram.ext.ExtBot
:show-inheritance:
8 changes: 8 additions & 0 deletions docs/source/telegram.ext.invalidcallbackdata.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
:github_url: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/callbackdatacache.py

telegram.ext.InvalidCallbackData
================================

.. autoclass:: telegram.ext.InvalidCallbackData
:members:
:show-inheritance:
9 changes: 9 additions & 0 deletions docs/source/telegram.ext.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ telegram.ext package

.. toctree::

telegram.ext.extbot
telegram.ext.updater
telegram.ext.dispatcher
telegram.ext.dispatcherhandlerstop
Expand Down Expand Up @@ -47,6 +48,14 @@ Persistence
telegram.ext.picklepersistence
telegram.ext.dictpersistence

Arbitrary Callback Data
-----------------------

.. toctree::

telegram.ext.callbackdatacache
telegram.ext.invalidcallbackdata

utils
-----

Expand Down
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,8 @@ A basic example on how `(my_)chat_member` updates can be used.
### [`contexttypesbot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/contexttypesbot.py)
This example showcases how `telegram.ext.ContextTypes` can be used to customize the `context` argument of handler and job callbacks.

### [`arbitrarycallbackdatabot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/arbitrarycallbackdatabot.py)
This example showcases how PTBs "arbitrary callback data" feature can be used.

## Pure API
The [`rawapibot.py`](https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/rawapibot.py) example uses only the pure, "bare-metal" API wrapper.
110 changes: 110 additions & 0 deletions examples/arbitrarycallbackdatabot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env python
# pylint: disable=C0116,W0613
# This program is dedicated to the public domain under the CC0 license.

"""This example showcases how PTBs "arbitrary callback data" feature can be used.

For detailed info on arbitrary callback data, see the wiki page at https://git.io/JGBDI
"""
import logging
from typing import List, Tuple, cast

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
Updater,
CommandHandler,
CallbackQueryHandler,
CallbackContext,
InvalidCallbackData,
PicklePersistence,
)

logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)


def start(update: Update, context: CallbackContext) -> None:
"""Sends a message with 5 inline buttons attached."""
number_list: List[int] = []
update.message.reply_text('Please choose:', reply_markup=build_keyboard(number_list))


def help_command(update: Update, context: CallbackContext) -> None:
"""Displays info on how to use the bot."""
update.message.reply_text(
"Use /start to test this bot. Use /clear to clear the stored data so that you can see "
"what happens, if the button data is not available. "
)


def clear(update: Update, context: CallbackContext) -> None:
"""Clears the callback data cache"""
context.bot.callback_data_cache.clear_callback_data() # type: ignore[attr-defined]
context.bot.callback_data_cache.clear_callback_queries() # type: ignore[attr-defined]
update.effective_message.reply_text('All clear!')


def build_keyboard(current_list: List[int]) -> InlineKeyboardMarkup:
"""Helper function to build the next inline keyboard."""
return InlineKeyboardMarkup.from_column(
[InlineKeyboardButton(str(i), callback_data=(i, current_list)) for i in range(1, 6)]
)


def list_button(update: Update, context: CallbackContext) -> None:
"""Parses the CallbackQuery and updates the message text."""
query = update.callback_query
query.answer()
# Get the data from the callback_data.
# If you're using a type checker like MyPy, you'll have to use typing.cast
# to make the checker get the expected type of the callback_data
number, number_list = cast(Tuple[int, List[int]], query.data)
# append the number to the list
number_list.append(number)

query.edit_message_text(
text=f"So far you've selected {number_list}. Choose the next item:",
reply_markup=build_keyboard(number_list),
)

# we can delete the data stored for the query, because we've replaced the buttons
context.drop_callback_data(query)


def handle_invalid_button(update: Update, context: CallbackContext) -> None:
"""Informs the user that the button is no longer available."""
update.callback_query.answer()
update.effective_message.edit_text(
'Sorry, I could not process this button click 😕 Please send /start to get a new keyboard.'
)


def main() -> None:
"""Run the bot."""
# We use persistence to demonstrate how buttons can still work after the bot was restarted
persistence = PicklePersistence(
filename='arbitrarycallbackdatabot.pickle', store_callback_data=True
)
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN", persistence=persistence, arbitrary_callback_data=True)

updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CommandHandler('help', help_command))
updater.dispatcher.add_handler(CommandHandler('clear', clear))
updater.dispatcher.add_handler(
CallbackQueryHandler(handle_invalid_button, pattern=InvalidCallbackData)
)
updater.dispatcher.add_handler(CallbackQueryHandler(list_button))

# Start the Bot
updater.start_polling()

# Run the bot until the user presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT
updater.idle()


if __name__ == '__main__':
main()
8 changes: 4 additions & 4 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ cryptography!=3.4,!=3.4.1,!=3.4.2,!=3.4.3
pre-commit
# Make sure that the versions specified here match the pre-commit settings!
black==20.8b1
flake8==3.9.1
pylint==2.8.2
flake8==3.9.2
pylint==2.8.3
mypy==0.812
pyupgrade==2.13.0
pyupgrade==2.19.1

pytest==6.2.3
pytest==6.2.4

flaky
beautifulsoup4
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ certifi
tornado>=6.1
APScheduler==3.6.3
pytz>=2018.6
cachetools==4.2.2
Loading