Skip to content

Add chat_id in ChatMemberHandler to Filter Specific Chat(s) #4287 #4290

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
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
37 changes: 26 additions & 11 deletions telegram/ext/_handlers/chatmemberhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@

from telegram import Update
from telegram._utils.defaultvalue import DEFAULT_TRUE
from telegram._utils.types import DVType
from telegram._utils.types import SCT, DVType
from telegram.ext._handlers.basehandler import BaseHandler
from telegram.ext._utils._update_parsing import parse_chat_id
from telegram.ext._utils.types import CCT, HandlerCallback

RT = TypeVar("RT")
Expand Down Expand Up @@ -58,6 +59,9 @@ async def callback(update: Update, context: CallbackContext)
:meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.

.. seealso:: :wiki:`Concurrency`
chat_id (:obj:`int` | Collection[:obj:`int`], optional): Filters chat member updates from
specified chat ID(s) only.
.. versionadded:: NEXT.VERSION

Attributes:
callback (:term:`coroutine function`): The callback function for this handler.
Expand All @@ -70,7 +74,10 @@ async def callback(update: Update, context: CallbackContext)

"""

__slots__ = ("chat_member_types",)
__slots__ = (
"_chat_ids",
"chat_member_types",
)
MY_CHAT_MEMBER: Final[int] = -1
""":obj:`int`: Used as a constant to handle only :attr:`telegram.Update.my_chat_member`."""
CHAT_MEMBER: Final[int] = 0
Expand All @@ -84,10 +91,12 @@ def __init__(
callback: HandlerCallback[Update, CCT, RT],
chat_member_types: int = MY_CHAT_MEMBER,
block: DVType[bool] = DEFAULT_TRUE,
chat_id: Optional[SCT[int]] = None,
):
super().__init__(callback, block=block)

self.chat_member_types: Optional[int] = chat_member_types
self._chat_ids = parse_chat_id(chat_id)

def check_update(self, update: object) -> bool:
"""Determines whether an update should be passed to this handler's :attr:`callback`.
Expand All @@ -99,12 +108,18 @@ def check_update(self, update: object) -> bool:
:obj:`bool`

"""
if isinstance(update, Update):
if not (update.my_chat_member or update.chat_member):
return False
if self.chat_member_types == self.ANY_CHAT_MEMBER:
return True
if self.chat_member_types == self.CHAT_MEMBER:
return bool(update.chat_member)
return bool(update.my_chat_member)
return False
if not isinstance(update, Update):
return False
if not (update.my_chat_member or update.chat_member):
return False
if (
self._chat_ids
and update.effective_chat
and update.effective_chat.id not in self._chat_ids
):
return False
if self.chat_member_types == self.ANY_CHAT_MEMBER:
return True
if self.chat_member_types == self.CHAT_MEMBER:
return bool(update.chat_member)
return bool(update.my_chat_member)
60 changes: 60 additions & 0 deletions tests/ext/test_chatmemberhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,66 @@ async def test_chat_member_types(
await app.process_update(chat_member)
assert self.test_flag == result_2

@pytest.mark.parametrize(
argnames=["allowed_types", "chat_id", "expected"],
argvalues=[
(ChatMemberHandler.MY_CHAT_MEMBER, None, (True, False)),
(ChatMemberHandler.CHAT_MEMBER, None, (False, True)),
(ChatMemberHandler.ANY_CHAT_MEMBER, None, (True, True)),
(ChatMemberHandler.MY_CHAT_MEMBER, 1, (True, False)),
(ChatMemberHandler.CHAT_MEMBER, 1, (False, True)),
(ChatMemberHandler.ANY_CHAT_MEMBER, 1, (True, True)),
(ChatMemberHandler.MY_CHAT_MEMBER, [1], (True, False)),
(ChatMemberHandler.CHAT_MEMBER, [1], (False, True)),
(ChatMemberHandler.ANY_CHAT_MEMBER, [1], (True, True)),
(ChatMemberHandler.MY_CHAT_MEMBER, 2, (False, False)),
(ChatMemberHandler.CHAT_MEMBER, 2, (False, False)),
(ChatMemberHandler.ANY_CHAT_MEMBER, 2, (False, False)),
(ChatMemberHandler.MY_CHAT_MEMBER, [2], (False, False)),
(ChatMemberHandler.CHAT_MEMBER, [2], (False, False)),
(ChatMemberHandler.ANY_CHAT_MEMBER, [2], (False, False)),
],
ids=[
"MY_CHAT_MEMBER",
"CHAT_MEMBER",
"ANY_CHAT_MEMBER",
"MY_CHAT_MEMBER, CHAT=1 ",
"CHAT_MEMBER, CHAT=1",
"ANY_CHAT_MEMBER, CHAT=1",
"MY_CHAT_MEMBER, CHAT=[1] ",
"CHAT_MEMBER, CHAT=[1]",
"ANY_CHAT_MEMBER, CHAT=[1]",
"MY_CHAT_MEMBER, CHAT=2 ",
"CHAT_MEMBER, CHAT=2",
"ANY_CHAT_MEMBER, CHAT=2",
"MY_CHAT_MEMBER, CHAT=[2] ",
"CHAT_MEMBER, CHAT=[2]",
"ANY_CHAT_MEMBER, CHAT=[2]",
],
)
async def test_chat_member_types_with_chat_id(
self, app, chat_member_updated, chat_member, expected, allowed_types, chat_id
):
result_1, result_2 = expected

handler = ChatMemberHandler(
self.callback, chat_member_types=allowed_types, chat_id=chat_id
)
app.add_handler(handler)

async with app:
assert handler.check_update(chat_member) == result_1
await app.process_update(chat_member)
assert self.test_flag == result_1

self.test_flag = False
chat_member.my_chat_member = None
chat_member.chat_member = chat_member_updated

assert handler.check_update(chat_member) == result_2
await app.process_update(chat_member)
assert self.test_flag == result_2

def test_other_update_types(self, false_update):
handler = ChatMemberHandler(self.callback)
assert not handler.check_update(false_update)
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy