<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def get_chat_members( self, chat_id: Union[int, str], offset: int = 0, limit: int = 200, query: str = "", filter: str = Filters.ALL ) -> "pyrogram.ChatMembers": """Use this method to get a chunk of the members list of a chat. You can get up to 200 chat members at once. A chat can be either a basic group, a supergroup or a channel. You must be admin to retrieve the members list of a channel (also known as "subscribers"). For a more convenient way of getting chat members see :meth:`iter_chat_members`. Args: chat_id (``int`` | ``str``):
 Unique identifier (int) or username (str) of the target chat. offset (``int``, *optional*):
 Sequential number of the first member to be returned. Defaults to 0 [1]_. limit (``int``, *optional*):
 Limits the number of members to be retrieved. Defaults to 200, which is also the maximum server limit allowed per method call. query (``str``, *optional*):
 Query string to filter members based on their display names and usernames. Defaults to "" (empty string) [2]_. filter (``str``, *optional*):
 Filter used to select the kind of members you want to retrieve. Only applicable for supergroups and channels. It can be any of the followings: *"all"* - all kind of members, *"kicked"* - kicked (banned) members only, *"restricted"* - restricted members only, *"bots"* - bots only, *"recent"* - recent members only, *"administrators"* - chat administrators only. Defaults to *"all"*. .. [1] Server limit: on supergroups, you can get up to 10,000 members for a single query and up to 200 members on channels. .. [2] A query string is applicable only for *"all"*, *"kicked"* and *"restricted"* filters only. Returns: On success, a :obj:`ChatMembers` object is returned. Raises: :class:`RPCError <pyrogram.RPCError>` in case of a Telegram RPC error. ``ValueError`` if you used an invalid filter or a chat_id that belongs to a user. """

        peer = self.resolve_peer(chat_id)

        if isinstance(peer, types.InputPeerChat):
            return pyrogram.ChatMembers._parse(
                self,
                self.send(
                    functions.messages.GetFullChat(
                        chat_id=peer.chat_id
                    )
                )
            )
        elif isinstance(peer, types.InputPeerChannel):
            filter = filter.lower()

            if filter == Filters.ALL:
                filter = types.ChannelParticipantsSearch(q=query)
            elif filter == Filters.KICKED:
                filter = types.ChannelParticipantsKicked(q=query)
            elif filter == Filters.RESTRICTED:
                filter = types.ChannelParticipantsBanned(q=query)
            elif filter == Filters.BOTS:
                filter = types.ChannelParticipantsBots()
            elif filter == Filters.RECENT:
                filter = types.ChannelParticipantsRecent()
            elif filter == Filters.ADMINISTRATORS:
                filter = types.ChannelParticipantsAdmins()
            else:
                raise ValueError("Invalid filter \"{}\"".format(filter))

            while True:
                try:
                    return pyrogram.ChatMembers._parse(
                        self,
                        self.send(
                            functions.channels.GetParticipants(
                                channel=peer,
                                filter=filter,
                                offset=offset,
                                limit=limit,
                                hash=0
                            )
                        )
                    )
                except FloodWait as e:
                    log.warning("Sleeping for {}s".format(e.x))
                    time.sleep(e.x)
        else:
            raise ValueError("The chat_id \"{}\" belongs to a user".format(chat_id))