8000 Implement game_pattern support in CQH by jainamoswal · Pull Request #4353 · python-telegram-bot/python-telegram-bot · GitHub
[go: up one dir, main page]

Skip to content

Implement game_pattern support in CQH #4353

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 28 commits into from
Jul 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
55dba23
Added game_pattern to CQH
jainamoswal Jul 7, 2024
d78e1d5
Added myself in AUTHORS.rst
jainamoswal Jul 7, 2024
b3869a5
Fixed a typo in Docstring
jainamoswal Jul 7, 2024
f897e3a
Updated handling logic
jainamoswal Jul 7, 2024
5bfe727
Added ".. versionadded:: NEXT.VERSION" directive
jainamoswal Jul 7, 2024
413823f
Update callbackqueryhandler.py
jainamoswal Jul 7, 2024
5cac778
Fixed for tests failing.
jainamoswal Jul 7, 2024
2253883
Updated according to pylint recommendations
jainamoswal Jul 7, 2024
4193b41
Merge branch 'python-telegram-bot:master' into jainamoswal-patch-1
jainamoswal Jul 7, 2024
034f623
Removed callable from game_pattern
Jul 9, 2024
f524f3c
Fix type hinting
jainamoswal Jul 9, 2024
b0910dc
Updated file
jainamoswal Jul 9, 2024
39e1b37
Merge branch 'python-telegram-bot:master' into jainamoswal-patch-1
jainamoswal Jul 9, 2024
05e9fd0
Added CSI-style comments & reduced indent
jainamoswal Jul 9, 2024
21f4b3b
Merge branch 'jainamoswal-patch-1' of github.com:jainamoswal/python-t…
jainamoswal Jul 9, 2024
7759df7
Added tests for game_short_name
jainamoswal Jul 10, 2024
a60f8a0
pylint fixes
jainamoswal Jul 10, 2024
a17b042
Merge branch 'master' into jainamoswal-patch-1
jainamoswal Jul 10, 2024
1f781cb
Refine tests, update docs & some refactor to code
jainamoswal Jul 10, 2024
a821f82
Refined tests
jainamoswal Jul 11, 2024
bbc9864
Refactor
Jul 11, 2024
e96042e
pylint fixes
jainamoswal Jul 11, 2024
c19eb0a
ahh, again pylint fixes
jainamoswal Jul 11, 2024
1deaff1
pylint pylint pylint
jainamoswal Jul 11, 2024
6fd56b5
fixed E121
jainamoswal Jul 11, 2024
51b3f82
pylint
jainamoswal Jul 12, 2024
dc8db09
Merge branch 'master' into jainamoswal-patch-1
jainamoswal Jul 12, 2024
57db295
Fixed tests
jainamoswal Jul 13, 2024
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 AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ The following wonderful people contributed directly or indirectly to this projec
- `Hugo Damer <https://github.com/HakimusGIT>`_
- `ihoru <https://github.com/ihoru>`_
- `Iulian Onofrei <https://github.com/revolter>`_
- `Jainam Oswal <https://github.com/jainamoswal>`_
- `Jasmin Bom <https://github.com/jsmnbom>`_
- `JASON0916 <https://github.com/JASON0916>`_
- `jeffffc <https://github.com/jeffffc>`_
Expand Down
72 changes: 54 additions & 18 deletions telegram/ext/_handlers/callbackqueryhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ class CallbackQueryHandler(BaseHandler[Update, CCT]):

.. versionadded:: 13.6

* If neither :paramref:`pattern` nor :paramref:`game_pattern` is set, `any`
``CallbackQuery`` will be handled. If only :paramref:`pattern` is set, queries with
:attr:`~telegram.CallbackQuery.game_short_name` will `not` be considered and vice versa.
If both patterns are set, queries with either :attr:
`~telegram.CallbackQuery.game_short_name` or :attr:`~telegram.CallbackQuery.data`
matching the defined pattern will be handled

.. versionadded:: NEXT.VERSION

Warning:
When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom
attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.
Expand Down Expand Up @@ -85,6 +94,13 @@ async def callback(update: Update, context: CallbackContext)

.. versionchanged:: 13.6
Added support for arbitrary callback data.
game_pattern (:obj:`str` | :func:`re.Pattern <re.compile>` | optional)
Pattern to test :attr:`telegram.CallbackQuery.game_short_name` against. If a string or
a regex pattern is passed, :func:`re.match` is used on
:attr:`telegram.CallbackQuery.game_short_name` to determine if an update should be
handled by this handler.

.. versionadded:: NEXT.VERSION
block (:obj:`bool`, optional): Determines whether the return value of the callback should
be awaited before processing the next handler in
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
Expand All @@ -98,20 +114,23 @@ async def callback(update: Update, context: CallbackContext)

.. versionchanged:: 13.6
Added support for arbitrary callback data.
game_pattern (:func:`re.Pattern <re.compile>`): Optional.
Regex pattern to test :attr:`telegram.CallbackQuery.game_short_name`
block (:obj:`bool`): Determines whether the return value of the callback should be
awaited before processing the next handler in
:meth:`telegram.ext.Application.process_update`.

"""

__slots__ = ("pattern",)
__slots__ = ("game_pattern", "pattern")

def __init__(
self,
callback: HandlerCallback[Update, CCT, RT],
pattern: Optional[
Union[str, Pattern[str], type, Callable[[object], Optional[bool]]]
] = None,
game_pattern: Optional[Union[str, Pattern[str]]] = None,
block: DVType[bool] = DEFAULT_TRUE,
):
super().__init__(callback, block=block)
Expand All @@ -120,13 +139,15 @@ def __init__(
raise TypeError(
"The `pattern` must not be a coroutine function! Use an ordinary function instead."
)

if isinstance(pattern, str):
pattern = re.compile(pattern)

if isinstance(game_pattern, str):
game_pattern = re.compile(game_pattern)
self.pattern: Optional[
Union[str, Pattern[str], type, Callable[[object], Optional[bool]]]
] = pattern
self.game_pattern: Optional[Union[str, Pattern[str]]] = game_pattern

def check_update(self, update: object) -> Optional[Union[bool, object]]:
"""Determines whether an update should be passed to this handler's :attr:`callback`.
Expand All @@ -139,22 +160,37 @@ def check_update(self, update: object) -> Optional[Union[bool, object]]:

"""
# pylint: disable=too-many-return-statements
if isinstance(update, Update) and update.callback_query:
callback_data = update.callback_query.data
if self.pattern:
if callback_data is None:
return False
if isinstance(self.pattern, type):
return isinstance(callback_data, self.pattern)
if callable(self.pattern):
return self.pattern(callback_data)
if not isinstance(callback_data, str):
return False
if match := re.match(self.pattern, callback_data):
return match
else:
return True
return None
if not (isinstance(update, Update) and update.callback_query):
return None

callback_data = update.callback_query.data
game_short_name = update.callback_query.game_short_name

if not any([self.pattern, self.game_pattern]):
return True

# we check for .data or .game_short_name from update to filter based on whats coming
# this gives xor-like behavior
if callback_data:
if not self.pattern:
return False
if isinstance(self.pattern, type):
return isinstance(callback_data, self.pattern)
if callable(self.pattern):
return self.pattern(callback_data)
if not isinstance(callback_data, str):
return False
if match := re.match(self.pattern, callback_data):
return match

elif game_short_name:
if not self.game_pattern:
return False
if match := re.match(self.game_pattern, game_short_name):
return match
else:
return True
return False

def collect_additional_context(
self,
Expand Down
44 changes: 44 additions & 0 deletions tests/ext/test_callbackqueryhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,47 @@ async def pattern():

with pytest.raises(TypeError, match="must not be a coroutine function"):
CallbackQueryHandler(self.callback, pattern=pattern)

def test_game_pattern(self, callback_query):
callback_query.callback_query.data = None

callback_query.callback_query.game_short_name = "test data"
handler = CallbackQueryHandler(self.callback_basic, game_pattern=".*est.*")
assert handler.check_update(callback_query)

callback_query.callback_query.game_short_name = "nothing here"
assert not handler.check_update(callback_query)

callback_query.callback_query.game_short_name = "this is a short game name"
assert not handler.check_update(callback_query)

callback_query.callback_query.data = "something"
handler = CallbackQueryHandler(self.callback_basic, game_pattern="")
assert not handler.check_update(callback_query)

@pytest.mark.parametrize(
("data", "pattern", "game_short_name", "game_pattern", "expected_result"),
[
(None, None, None, None, True),
(None, ".*data", None, None, True),
(None, None, None, ".*game", True),
(None, ".*data", None, ".*game", True),
("some_data", None, None, None, True),
("some_data", ".*data", None, None, True),
("some_data", None, None, ".*game", False),
("some_data", ".*data", None, ".*game", True),
(None, None, "some_game", None, True),
(None, ".*data", "some_game", None, False),
(None, None, "some_game", ".*game", True),
(None, ".*data", "some_game", ".*game", True),
],
)
def test_pattern_and_game_pattern_interaction(
self, callback_query, data, pattern, game_short_name, game_pattern, expected_result
):
callback_query.callback_query.data = data
callback_query.callback_query.game_short_name = game_short_name
handler = CallbackQueryHandler(
callback=self.callback, pattern=pattern, game_pattern=game_pattern
)
assert bool(handler.check_update(callback_query)) == expected_result
Loading
0