prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [Suggestion] Add chat(s) parameter to ChatJoinRequestHandler
  This param should allow to filter out chats which will be handled by the ChatJoinRequestHandler, much like the pattern argument of the CallbackQueryHandler. It should allow "username" strings as well as ids and if set, the handler should check if the incoming update is from that chat.
  
  For first time contributors, check how CallbackQueryHandler implements the pattern argument in check_update: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/_callbackqueryhandler.py#L123
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `telegram/ext/_chatjoinrequesthandler.py`
  Content:
  ```
  1 #!/usr/bin/env python
  2 #
  3 # A library that provides a Python interface to the Telegram Bot API
  4 # Copyright (C) 2015-2022
  5 # Leandro Toledo de Souza <devs@python-telegram-bot.org>
  6 #
  7 # This program is free software: you can redistribute it and/or modify
  8 # it under the terms of the GNU Lesser Public License as published by
  9 # the Free Software Foundation, either version 3 of the License, or
  10 # (at your option) any later version.
  11 #
  12 # This program is distributed in the hope that it will be useful,
  13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 # GNU Lesser Public License for more details.
  16 #
  17 # You should have received a copy of the GNU Lesser Public License
  18 # along with this program.  If not, see [http://www.gnu.org/licenses/].
  19 """This module contains the ChatJoinRequestHandler class."""
  20 
  21 
  22 from telegram import Update
  23 from telegram.ext._handler import BaseHandler
  24 from telegram.ext._utils.types import CCT
  25 
  26 
  27 class ChatJoinRequestHandler(BaseHandler[Update, CCT]):
  28     """BaseHandler class to handle Telegram updates that contain
  29     :attr:`telegram.Update.chat_join_request`.
  30 
  31     Warning:
  32         When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom
  33         attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.
  34 
  35     .. versionadded:: 13.8
  36 
  37     Args:
  38         callback (:term:`coroutine function`): The callback function for this handler. Will be
  39             called when :meth:`check_update` has determined that an update should be processed by
  40             this handler. Callback signature::
  41 
  42                 async def callback(update: Update, context: CallbackContext)
  43 
  44             The return value of the callback is usually ignored except for the special case of
  45             :class:`telegram.ext.ConversationHandler`.
  46         block (:obj:`bool`, optional): Determines whether the return value of the callback should
  47             be awaited before processing the next handler in
  48             :meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.
  49 
  50     Attributes:
  51         callback (:term:`coroutine function`): The callback function for this handler.
  52         block (:obj:`bool`): Determines whether the callback will run in a blocking way..
  53 
  54     """
  55 
  56     __slots__ = ()
  57 
  58     def check_update(self, update: object) -> bool:
  59         """Determines whether an update should be passed to this handler's :attr:`callback`.
  60 
  61         Args:
  62             update (:class:`telegram.Update` | :obj:`object`): Incoming update.
  63 
  64         Returns:
  65             :obj:`bool`
  66 
  67         """
  68         return isinstance(update, Update) and bool(update.chat_join_request)
  69
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/telegram/ext/_chatjoinrequesthandler.py b/telegram/ext/_chatjoinrequesthandler.py
  --- a/telegram/ext/_chatjoinrequesthandler.py
  +++ b/telegram/ext/_chatjoinrequesthandler.py
  @@ -18,16 +18,27 @@
   # along with this program.  If not, see [http://www.gnu.org/licenses/].
   """This module contains the ChatJoinRequestHandler class."""
   
  +from typing import FrozenSet, Optional
   
   from telegram import Update
  +from telegram._utils.defaultvalue import DEFAULT_TRUE
  +from telegram._utils.types import RT, SCT, DVInput
   from telegram.ext._handler import BaseHandler
  -from telegram.ext._utils.types import CCT
  +from telegram.ext._utils.types import CCT, HandlerCallback
   
   
   class ChatJoinRequestHandler(BaseHandler[Update, CCT]):
       """BaseHandler class to handle Telegram updates that contain
       :attr:`telegram.Update.chat_join_request`.
   
  +    Note:
  +        If neither of :paramref:`username` and the :paramref:`chat_id` are passed, this handler
  +        accepts *any* join request. Otherwise, this handler accepts all requests to join chats
  +        for which the chat ID is listed in :paramref:`chat_id` or the username is listed in
  +        :paramref:`username`, or both.
  +
  +        .. versionadded:: 20.0
  +
       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.
  @@ -43,6 +54,14 @@
   
               The return value of the callback is usually ignored except for the special case of
               :class:`telegram.ext.ConversationHandler`.
  +        chat_id (:obj:`int` | Collection[:obj:`int`], optional): Filters requests to allow only
  +            those which are asking to join the specified chat ID(s).
  +
  +            .. versionadded:: 20.0
  +        username (:obj:`str` | Collection[:obj:`str`], optional): Filters requests to allow only
  +            those which are asking to join the specified username(s).
  +
  +            .. versionadded:: 20.0
           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`.
  @@ -53,7 +72,38 @@
   
       """
   
  -    __slots__ = ()
  +    __slots__ = (
  +        "_chat_ids",
  +        "_usernames",
  +    )
  +
  +    def __init__(
  +        self,
  +        callback: HandlerCallback[Update, CCT, RT],
  +        chat_id: SCT[int] = None,
  +        username: SCT[str] = None,
  +        block: DVInput[bool] = DEFAULT_TRUE,
  +    ):
  +        super().__init__(callback, block=block)
  +
  +        self._chat_ids = self._parse_chat_id(chat_id)
  +        self._usernames = self._parse_username(username)
  +
  +    @staticmethod
  +    def _parse_chat_id(chat_id: Optional[SCT[int]]) -> FrozenSet[int]:
  +        if chat_id is None:
  +            return frozenset()
  +        if isinstance(chat_id, int):
  +            return frozenset({chat_id})
  +        return frozenset(chat_id)
  +
  +    @staticmethod
  +    def _parse_username(username: Optional[SCT[str]]) -> FrozenSet[str]:
  +        if username is None:
  +            return frozenset()
  +        if isinstance(username, str):
  +            return frozenset({username[1:] if username.startswith("@") else username})
  +        return frozenset({usr[1:] if usr.startswith("@") else usr for usr in username})
   
       def check_update(self, update: object) -> bool:
           """Determines whether an update should be passed to this handler's :attr:`callback`.
  @@ -65,4 +115,12 @@
               :obj:`bool`
   
           """
  -        return isinstance(update, Update) and bool(update.chat_join_request)
  +        if isinstance(update, Update) and update.chat_join_request:
  +            if not self._chat_ids and not self._usernames:
  +                return True
  +            if update.chat_join_request.chat.id in self._chat_ids:
  +                return True
  +            if update.chat_join_request.from_user.username in self._usernames:
  +                return True
  +            return False
  +        return False
  
verification_info: {"golden_diff": "diff --git a/telegram/ext/_chatjoinrequesthandler.py b/telegram/ext/_chatjoinrequesthandler.py\n--- a/telegram/ext/_chatjoinrequesthandler.py\n+++ b/telegram/ext/_chatjoinrequesthandler.py\n@@ -18,16 +18,27 @@\n # along with this program.  If not, see [http://www.gnu.org/licenses/].\n \"\"\"This module contains the ChatJoinRequestHandler class.\"\"\"\n \n+from typing import FrozenSet, Optional\n \n from telegram import Update\n+from telegram._utils.defaultvalue import DEFAULT_TRUE\n+from telegram._utils.types import RT, SCT, DVInput\n from telegram.ext._handler import BaseHandler\n-from telegram.ext._utils.types import CCT\n+from telegram.ext._utils.types import CCT, HandlerCallback\n \n \n class ChatJoinRequestHandler(BaseHandler[Update, CCT]):\n     \"\"\"BaseHandler class to handle Telegram updates that contain\n     :attr:`telegram.Update.chat_join_request`.\n \n+    Note:\n+        If neither of :paramref:`username` and the :paramref:`chat_id` are passed, this handler\n+        accepts *any* join request. Otherwise, this handler accepts all requests to join chats\n+        for which the chat ID is listed in :paramref:`chat_id` or the username is listed in\n+        :paramref:`username`, or both.\n+\n+        .. versionadded:: 20.0\n+\n     Warning:\n         When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom\n         attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.\n@@ -43,6 +54,14 @@\n \n             The return value of the callback is usually ignored except for the special case of\n             :class:`telegram.ext.ConversationHandler`.\n+        chat_id (:obj:`int` | Collection[:obj:`int`], optional): Filters requests to allow only\n+            those which are asking to join the specified chat ID(s).\n+\n+            .. versionadded:: 20.0\n+        username (:obj:`str` | Collection[:obj:`str`], optional): Filters requests to allow only\n+            those which are asking to join the specified username(s).\n+\n+            .. versionadded:: 20.0\n         block (:obj:`bool`, optional): Determines whether the return value of the callback should\n             be awaited before processing the next handler in\n             :meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.\n@@ -53,7 +72,38 @@\n \n     \"\"\"\n \n-    __slots__ = ()\n+    __slots__ = (\n+        \"_chat_ids\",\n+        \"_usernames\",\n+    )\n+\n+    def __init__(\n+        self,\n+        callback: HandlerCallback[Update, CCT, RT],\n+        chat_id: SCT[int] = None,\n+        username: SCT[str] = None,\n+        block: DVInput[bool] = DEFAULT_TRUE,\n+    ):\n+        super().__init__(callback, block=block)\n+\n+        self._chat_ids = self._parse_chat_id(chat_id)\n+        self._usernames = self._parse_username(username)\n+\n+    @staticmethod\n+    def _parse_chat_id(chat_id: Optional[SCT[int]]) -> FrozenSet[int]:\n+        if chat_id is None:\n+            return frozenset()\n+        if isinstance(chat_id, int):\n+            return frozenset({chat_id})\n+        return frozenset(chat_id)\n+\n+    @staticmethod\n+    def _parse_username(username: Optional[SCT[str]]) -> FrozenSet[str]:\n+        if username is None:\n+            return frozenset()\n+        if isinstance(username, str):\n+            return frozenset({username[1:] if username.startswith(\"@\") else username})\n+        return frozenset({usr[1:] if usr.startswith(\"@\") else usr for usr in username})\n \n     def check_update(self, update: object) -> bool:\n         \"\"\"Determines whether an update should be passed to this handler's :attr:`callback`.\n@@ -65,4 +115,12 @@\n             :obj:`bool`\n \n         \"\"\"\n-        return isinstance(update, Update) and bool(update.chat_join_request)\n+        if isinstance(update, Update) and update.chat_join_request:\n+            if not self._chat_ids and not self._usernames:\n+                return True\n+            if update.chat_join_request.chat.id in self._chat_ids:\n+                return True\n+            if update.chat_join_request.from_user.username in self._usernames:\n+                return True\n+            return False\n+        return False\n", "issue": "[Suggestion] Add chat(s) parameter to ChatJoinRequestHandler\nThis param should allow to filter out chats which will be handled by the ChatJoinRequestHandler, much like the pattern argument of the CallbackQueryHandler. It should allow \"username\" strings as well as ids and if set, the handler should check if the incoming update is from that chat.\r\n\r\nFor first time contributors, check how CallbackQueryHandler implements the pattern argument in check_update: https://github.com/python-telegram-bot/python-telegram-bot/blob/master/telegram/ext/_callbackqueryhandler.py#L123\n", "before_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2022\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains the ChatJoinRequestHandler class.\"\"\"\n\n\nfrom telegram import Update\nfrom telegram.ext._handler import BaseHandler\nfrom telegram.ext._utils.types import CCT\n\n\nclass ChatJoinRequestHandler(BaseHandler[Update, CCT]):\n    \"\"\"BaseHandler class to handle Telegram updates that contain\n    :attr:`telegram.Update.chat_join_request`.\n\n    Warning:\n        When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom\n        attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.\n\n    .. versionadded:: 13.8\n\n    Args:\n        callback (:term:`coroutine function`): The callback function for this handler. Will be\n            called when :meth:`check_update` has determined that an update should be processed by\n            this handler. Callback signature::\n\n                async def callback(update: Update, context: CallbackContext)\n\n            The return value of the callback is usually ignored except for the special case of\n            :class:`telegram.ext.ConversationHandler`.\n        block (:obj:`bool`, optional): Determines whether the return value of the callback should\n            be awaited before processing the next handler in\n            :meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.\n\n    Attributes:\n        callback (:term:`coroutine function`): The callback function for this handler.\n        block (:obj:`bool`): Determines whether the callback will run in a blocking way..\n\n    \"\"\"\n\n    __slots__ = ()\n\n    def check_update(self, update: object) -> bool:\n        \"\"\"Determines whether an update should be passed to this handler's :attr:`callback`.\n\n        Args:\n            update (:class:`telegram.Update` | :obj:`object`): Incoming update.\n\n        Returns:\n            :obj:`bool`\n\n        \"\"\"\n        return isinstance(update, Update) and bool(update.chat_join_request)\n", "path": "telegram/ext/_chatjoinrequesthandler.py"}], "after_files": [{"content": "#!/usr/bin/env python\n#\n# A library that provides a Python interface to the Telegram Bot API\n# Copyright (C) 2015-2022\n# Leandro Toledo de Souza <devs@python-telegram-bot.org>\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# This program is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU Lesser Public License for more details.\n#\n# You should have received a copy of the GNU Lesser Public License\n# along with this program.  If not, see [http://www.gnu.org/licenses/].\n\"\"\"This module contains the ChatJoinRequestHandler class.\"\"\"\n\nfrom typing import FrozenSet, Optional\n\nfrom telegram import Update\nfrom telegram._utils.defaultvalue import DEFAULT_TRUE\nfrom telegram._utils.types import RT, SCT, DVInput\nfrom telegram.ext._handler import BaseHandler\nfrom telegram.ext._utils.types import CCT, HandlerCallback\n\n\nclass ChatJoinRequestHandler(BaseHandler[Update, CCT]):\n    \"\"\"BaseHandler class to handle Telegram updates that contain\n    :attr:`telegram.Update.chat_join_request`.\n\n    Note:\n        If neither of :paramref:`username` and the :paramref:`chat_id` are passed, this handler\n        accepts *any* join request. Otherwise, this handler accepts all requests to join chats\n        for which the chat ID is listed in :paramref:`chat_id` or the username is listed in\n        :paramref:`username`, or both.\n\n        .. versionadded:: 20.0\n\n    Warning:\n        When setting :paramref:`block` to :obj:`False`, you cannot rely on adding custom\n        attributes to :class:`telegram.ext.CallbackContext`. See its docs for more info.\n\n    .. versionadded:: 13.8\n\n    Args:\n        callback (:term:`coroutine function`): The callback function for this handler. Will be\n            called when :meth:`check_update` has determined that an update should be processed by\n            this handler. Callback signature::\n\n                async def callback(update: Update, context: CallbackContext)\n\n            The return value of the callback is usually ignored except for the special case of\n            :class:`telegram.ext.ConversationHandler`.\n        chat_id (:obj:`int` | Collection[:obj:`int`], optional): Filters requests to allow only\n            those which are asking to join the specified chat ID(s).\n\n            .. versionadded:: 20.0\n        username (:obj:`str` | Collection[:obj:`str`], optional): Filters requests to allow only\n            those which are asking to join the specified username(s).\n\n            .. versionadded:: 20.0\n        block (:obj:`bool`, optional): Determines whether the return value of the callback should\n            be awaited before processing the next handler in\n            :meth:`telegram.ext.Application.process_update`. Defaults to :obj:`True`.\n\n    Attributes:\n        callback (:term:`coroutine function`): The callback function for this handler.\n        block (:obj:`bool`): Determines whether the callback will run in a blocking way..\n\n    \"\"\"\n\n    __slots__ = (\n        \"_chat_ids\",\n        \"_usernames\",\n    )\n\n    def __init__(\n        self,\n        callback: HandlerCallback[Update, CCT, RT],\n        chat_id: SCT[int] = None,\n        username: SCT[str] = None,\n        block: DVInput[bool] = DEFAULT_TRUE,\n    ):\n        super().__init__(callback, block=block)\n\n        self._chat_ids = self._parse_chat_id(chat_id)\n        self._usernames = self._parse_username(username)\n\n    @staticmethod\n    def _parse_chat_id(chat_id: Optional[SCT[int]]) -> FrozenSet[int]:\n        if chat_id is None:\n            return frozenset()\n        if isinstance(chat_id, int):\n            return frozenset({chat_id})\n        return frozenset(chat_id)\n\n    @staticmethod\n    def _parse_username(username: Optional[SCT[str]]) -> FrozenSet[str]:\n        if username is None:\n            return frozenset()\n        if isinstance(username, str):\n            return frozenset({username[1:] if username.startswith(\"@\") else username})\n        return frozenset({usr[1:] if usr.startswith(\"@\") else usr for usr in username})\n\n    def check_update(self, update: object) -> bool:\n        \"\"\"Determines whether an update should be passed to this handler's :attr:`callback`.\n\n        Args:\n            update (:class:`telegram.Update` | :obj:`object`): Incoming update.\n\n        Returns:\n            :obj:`bool`\n\n        \"\"\"\n        if isinstance(update, Update) and update.chat_join_request:\n            if not self._chat_ids and not self._usernames:\n                return True\n            if update.chat_join_request.chat.id in self._chat_ids:\n                return True\n            if update.chat_join_request.from_user.username in self._usernames:\n                return True\n            return False\n        return False\n", "path": "telegram/ext/_chatjoinrequesthandler.py"}]}