Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
64 changes: 61 additions & 3 deletions telegram/ext/choseninlineresulthandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
"""This module contains the ChosenInlineResultHandler class."""

from typing import Optional, TypeVar, Union
import re
from typing import Optional, TypeVar, Union, Callable, TYPE_CHECKING, Pattern, Match, cast

from telegram import Update

from telegram.utils.helpers import DefaultValue, DEFAULT_FALSE
from .handler import Handler

RT = TypeVar('RT')

if TYPE_CHECKING:
from telegram.ext import CallbackContext, Dispatcher


class ChosenInlineResultHandler(Handler[Update]):
"""Handler class to handle Telegram updates that contain a chosen inline result.
Expand Down Expand Up @@ -70,6 +74,12 @@ class ChosenInlineResultHandler(Handler[Update]):
DEPRECATED: Please switch to context based callbacks.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
Defaults to :obj:`False`.
pattern (:obj:`str` | `Pattern`, optional): Regex pattern. If not :obj:`None`, ``re.match``
is used on :attr:`telegram.ChosenInlineResult.result_id` to determine if an update
should be handled by this handler. This is accessible in the callback as
:attr:`telegram.ext.CallbackContext.matches`.

.. versionadded:: 13.6

Attributes:
callback (:obj:`callable`): The callback function for this handler.
Expand All @@ -82,9 +92,37 @@ class ChosenInlineResultHandler(Handler[Update]):
pass_chat_data (:obj:`bool`): Determines whether ``chat_data`` will be passed to
the callback function.
run_async (:obj:`bool`): Determines whether the callback will run asynchronously.
pattern (`Pattern`): Optional. Regex pattern to test
:attr:`telegram.ChosenInlineResult.result_id` against.

.. versionadded:: 13.6

"""

def __init__(
self,
callback: Callable[[Update, 'CallbackContext'], RT],
pass_update_queue: bool = False,
pass_job_queue: bool = False,
pass_user_data: bool = False,
pass_chat_data: bool = False,
run_async: Union[bool, DefaultValue] = DEFAULT_FALSE,
pattern: Union[str, Pattern] = None,
):
super().__init__(
callback,
pass_update_queue=pass_update_queue,
pass_job_queue=pass_job_queue,
pass_user_data=pass_user_data,
pass_chat_data=pass_chat_data,
run_async=run_async,
)

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

self.pattern = pattern

def check_update(self, update: object) -> Optional[Union[bool, object]]:
"""Determines whether an update should be passed to this handlers :attr:`callback`.

Expand All @@ -95,4 +133,24 @@ def check_update(self, update: object) -> Optional[Union[bool, object]]:
:obj:`bool`

"""
return isinstance(update, Update) and update.chosen_inline_result
if isinstance(update, Update) and update.chosen_inline_result:
if self.pattern:
match = re.match(self.pattern, update.chosen_inline_result.result_id)
if match:
return match
else:
return True
return None

def collect_additional_context(
self,
context: 'CallbackContext',
update: Update,
dispatcher: 'Dispatcher',
check_result: Union[bool, Match],
) -> None:
"""This function adds the matched regex pattern result to
:attr:`telegram.ext.CallbackContext.matches`."""
if self.pattern:
Comment thread
Bibo-Joshi marked this conversation as resolved.
check_result = cast(Match, check_result)
context.matches = [check_result]
30 changes: 30 additions & 0 deletions tests/test_choseninlineresulthandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ def callback_context(self, update, context):
and isinstance(update.chosen_inline_result, ChosenInlineResult)
)

def callback_context_pattern(self, update, context):
if context.matches[0].groups():
self.test_flag = context.matches[0].groups() == ('res', '_id')
if context.matches[0].groupdict():
self.test_flag = context.matches[0].groupdict() == {'begin': 'res', 'end': '_id'}

def test_basic(self, dp, chosen_inline_result):
handler = ChosenInlineResultHandler(self.callback_basic)
dp.add_handler(handler)
Expand Down Expand Up @@ -179,3 +185,27 @@ def test_context(self, cdp, chosen_inline_result):

cdp.process_update(chosen_inline_result)
assert self.test_flag

def test_with_pattern(self, chosen_inline_result):
handler = ChosenInlineResultHandler(self.callback_basic, pattern='.*ult.*')

assert handler.check_update(chosen_inline_result)

chosen_inline_result.chosen_inline_result.result_id = 'nothing here'
assert not handler.check_update(chosen_inline_result)
chosen_inline_result.chosen_inline_result.result_id = 'result_id'

def test_context_pattern(self, cdp, chosen_inline_result):
handler = ChosenInlineResultHandler(
self.callback_context_pattern, pattern=r'(?P<begin>.*)ult(?P<end>.*)'
)
cdp.add_handler(handler)
cdp.process_update(chosen_inline_result)
assert self.test_flag

cdp.remove_handler(handler)
handler = ChosenInlineResultHandler(self.callback_context_pattern, pattern=r'(res)ult(.*)')
cdp.add_handler(handler)

cdp.process_update(chosen_inline_result)
assert self.test_flag