예제 #1
0
    async def resolve_and_set_join_as(self, join_as):
        my_peer = await self.get_and_set_self_peer()

        if join_as is None:
            self.join_as = self.full_chat.groupcall_default_join_as
            if self.join_as:
                # convert Peer to InputPeer
                self.join_as = await self.client.resolve_peer(get_peer_id(self.join_as))
            else:
                self.join_as = my_peer
        elif isinstance(join_as, str) or isinstance(join_as, int):
            self.join_as = await self.client.resolve_peer(join_as)
        else:
            self.join_as = join_as
예제 #2
0
    async def get_dialogs(
        self,
        offset_date: int = 0,
        limit: int = 100,
        pinned_only: bool = False
    ) -> List["types.Dialog"]:
        """Get a chunk of the user's dialogs.

        You can get up to 100 dialogs at once.
        For a more convenient way of getting a user's dialogs see :meth:`~pyrogram.Client.iter_dialogs`.

        Parameters:
            offset_date (``int``):
                The offset date in Unix time taken from the top message of a :obj:`~pyrogram.types.Dialog`.
                Defaults to 0. Valid for non-pinned dialogs only.

            limit (``str``, *optional*):
                Limits the number of dialogs to be retrieved.
                Defaults to 100. Valid for non-pinned dialogs only.

            pinned_only (``bool``, *optional*):
                Pass True if you want to get only pinned dialogs.
                Defaults to False.

        Returns:
            List of :obj:`~pyrogram.types.Dialog`: On success, a list of dialogs is returned.

        Example:
            .. code-block:: python

                # Get first 100 dialogs
                app.get_dialogs()

                # Get pinned dialogs
                app.get_dialogs(pinned_only=True)
        """

        if pinned_only:
            r = await self.send(
                raw.functions.messages.GetPinnedDialogs(folder_id=0),
                sleep_threshold=60
            )
        else:
            r = await self.send(
                raw.functions.messages.GetDialogs(
                    offset_date=offset_date,
                    offset_id=0,
                    offset_peer=raw.types.InputPeerEmpty(),
                    limit=limit,
                    hash=0,
                    exclude_pinned=True
                ),
                sleep_threshold=60
            )

        users = {i.id: i for i in r.users}
        chats = {i.id: i for i in r.chats}

        messages = {}

        for message in r.messages:
            to_id = message.to_id

            if isinstance(to_id, raw.types.PeerUser):
                if message.out:
                    chat_id = to_id.user_id
                else:
                    chat_id = message.from_id
            else:
                chat_id = utils.get_peer_id(to_id)

            messages[chat_id] = await types.Message._parse(self, message, users, chats)

        parsed_dialogs = []

        for dialog in r.dialogs:
            if not isinstance(dialog, raw.types.Dialog):
                continue

            parsed_dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats))

        return types.List(parsed_dialogs)
예제 #3
0
    async def _stream_handler(self,
                              request: Request) -> typing.Optional[Response]:
        _message_id: str = request.match_info["message_id"]

        if not _message_id.isdigit():
            return Response(status=401)

        _token: str = request.match_info["token"]

        if not _token.isdigit():
            return Response(status=401)

        token = int(_token)
        del _token
        message_id = int(_message_id)
        del _message_id

        local_token = serialize_token(message_id, token)

        if not self._check_local_token(local_token):
            return Response(status=403)

        range_header = request.headers.get("Range")

        if range_header is None:
            offset = 0
            data_to_skip = False
            max_size = None

        else:
            try:
                offset, data_to_skip, max_size = parse_http_range(
                    range_header, self._config.block_size)
            except ValueError:
                return Response(status=400)

        if data_to_skip > self._config.block_size:
            return Response(status=500)

        try:
            message = await self._mtproto.get_message(int(message_id))
        except ValueError:
            return Response(status=404)

        if not isinstance(message.media, MessageMediaDocument):
            return Response(status=404)

        if not isinstance(message.media.document, Document):
            return Response(status=404)

        size = message.media.document.size
        read_after = offset + data_to_skip

        if read_after > size:
            return Response(status=400)

        if (max_size is not None) and (size < max_size):
            return Response(status=400)

        if max_size is None:
            max_size = size

        stream = StreamResponse(
            status=206 if (read_after or (max_size != size)) else 200)
        self._write_http_range_headers(stream, read_after, size, max_size)

        try:
            filename = mtproto_filename(message)
        except TypeError:
            filename = f"file_{message.media.document.id}"

        self._write_filename_header(stream, filename)
        self._write_access_control_headers(stream)

        await stream.prepare(request)

        while offset < max_size:
            self._feed_timeout(message_id, get_peer_id(message.peer_id),
                               local_token, size)
            block = await self._mtproto.get_block(message, offset,
                                                  self._config.block_size)
            new_offset = offset + len(block)

            if data_to_skip:
                block = block[data_to_skip:]
                data_to_skip = False

            if new_offset > max_size:
                block = block[:-(new_offset - max_size)]

            if request.transport is None:
                break

            self._feed_stream_transport(local_token, request.transport)

            if request.transport.is_closing():
                break

            await stream.write(block)
            self._feed_downloaded_blocks(offset, local_token)
            offset = new_offset

        await stream.write_eof()
예제 #4
0
    async def iter_dialogs(
            self,
            limit: int = 0) -> Optional[AsyncGenerator["types.Dialog", None]]:
        """Iterate through a user's dialogs sequentially.

        This convenience method does the same as repeatedly calling :meth:`~pyrogram.Client.get_dialogs` in a loop,
        thus saving you from the hassle of setting up boilerplate code. It is useful for getting the whole dialogs list
        with a single call.

        Parameters:
            limit (``int``, *optional*):
                Limits the number of dialogs to be retrieved.
                By default, no limit is applied and all dialogs are returned.

        Returns:
            ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects.

        Example:
            .. code-block:: python

                # Iterate through all dialogs
                for dialog in app.iter_dialogs():
                    print(dialog.chat.first_name or dialog.chat.title)
        """
        current = 0
        total = limit or (1 << 31) - 1
        limit = min(100, total)

        offset_date = 0
        offset_id = 0
        offset_peer = raw.types.InputPeerEmpty()

        while True:
            r = (await self.send(raw.functions.messages.GetDialogs(
                offset_date=offset_date,
                offset_id=offset_id,
                offset_peer=offset_peer,
                limit=limit,
                hash=0),
                                 sleep_threshold=60))

            users = {i.id: i for i in r.users}
            chats = {i.id: i for i in r.chats}

            messages = {}

            for message in r.messages:
                if isinstance(message, raw.types.MessageEmpty):
                    continue

                chat_id = utils.get_peer_id(message.peer_id)
                messages[chat_id] = await types.Message._parse(
                    self, message, users, chats)

            dialogs = []

            for dialog in r.dialogs:
                if not isinstance(dialog, raw.types.Dialog):
                    continue

                dialogs.append(
                    types.Dialog._parse(self, dialog, messages, users, chats))

            if not dialogs:
                return

            last = dialogs[-1]

            offset_id = last.top_message.message_id
            offset_date = last.top_message.date
            offset_peer = await self.resolve_peer(last.chat.id)

            for dialog in dialogs:
                yield dialog

                current += 1

                if current >= total:
                    return
예제 #5
0
    async def get_dialogs(
        self: "pyrogram.Client",
        limit: int = 0
    ) -> Optional[AsyncGenerator["types.Dialog", None]]:
        """Get a user's dialogs sequentially.

        Parameters:
            limit (``int``, *optional*):
                Limits the number of dialogs to be retrieved.
                By default, no limit is applied and all dialogs are returned.

        Returns:
            ``Generator``: A generator yielding :obj:`~pyrogram.types.Dialog` objects.

        Example:
            .. code-block:: python

                # Iterate through all dialogs
                async for dialog in app.get_dialogs():
                    print(dialog.chat.first_name or dialog.chat.title)
        """
        current = 0
        total = limit or (1 << 31) - 1
        limit = min(100, total)

        offset_date = 0
        offset_id = 0
        offset_peer = raw.types.InputPeerEmpty()

        while True:
            r = await self.invoke(
                raw.functions.messages.GetDialogs(
                    offset_date=offset_date,
                    offset_id=offset_id,
                    offset_peer=offset_peer,
                    limit=limit,
                    hash=0
                ),
                sleep_threshold=60
            )

            users = {i.id: i for i in r.users}
            chats = {i.id: i for i in r.chats}

            messages = {}

            for message in r.messages:
                if isinstance(message, raw.types.MessageEmpty):
                    continue

                chat_id = utils.get_peer_id(message.peer_id)
                messages[chat_id] = await types.Message._parse(self, message, users, chats)

            dialogs = []

            for dialog in r.dialogs:
                if not isinstance(dialog, raw.types.Dialog):
                    continue

                dialogs.append(types.Dialog._parse(self, dialog, messages, users, chats))

            if not dialogs:
                return

            last = dialogs[-1]

            offset_id = last.top_message.id
            offset_date = utils.datetime_to_timestamp(last.top_message.date)
            offset_peer = await self.resolve_peer(last.chat.id)

            for dialog in dialogs:
                yield dialog

                current += 1

                if current >= total:
                    return