示例#1
0
    def _get_or_fetch_conversation(self, conv_id):
        """Get a cached conversation or fetch a missing conversation.

        Args:
            conv_id: string, conversation identifier

        Raises:
            NetworkError: If the request to fetch the conversation fails.

        Returns:
            :class:`.Conversation` with matching ID.
        """
        conv = self._conv_dict.get(conv_id, None)
        if conv is None:
            logger.info('Fetching unknown conversation %s', conv_id)
            res = yield from self._client.get_conversation(
                hangouts_pb2.GetConversationRequest(
                    request_header=self._client.get_request_header(),
                    conversation_spec=hangouts_pb2.ConversationSpec(
                        conversation_id=hangouts_pb2.ConversationId(
                            id=conv_id)),
                    include_event=False))
            return self._add_conversation(res.conversation_state.conversation)
        else:
            return conv
    def get_events(self, event_id=None, max_events=50):
        """Return list of ConversationEvents ordered newest-first.

        If event_id is specified, return events preceding this event.

        This method will make an API request to load historical events if
        necessary. If the beginning of the conversation is reached, an empty
        list will be returned.

        Raises KeyError if event_id does not correspond to a known event.

        Raises hangups.NetworkError if the events could not be requested.
        """
        if event_id is None:
            # If no event_id is provided, return the newest events in this
            # conversation.
            conv_events = self._events[-1 * max_events:]
        else:
            # If event_id is provided, return the events we have that are
            # older, or request older events if event_id corresponds to the
            # oldest event we have.
            conv_event = self.get_event(event_id)
            if self._events[0].id_ != event_id:
                conv_events = self._events[self._events.index(conv_event) + 1:]
            else:
                logger.info(
                    'Loading events for conversation {} before {}'.format(
                        self.id_, conv_event.timestamp))
                res = yield from self._client.get_conversation(
                    hangouts_pb2.GetConversationRequest(
                        request_header=self._client.get_request_header(),
                        conversation_spec=hangouts_pb2.ConversationSpec(
                            conversation_id=hangouts_pb2.ConversationId(
                                id=self.id_)),
                        include_event=True,
                        max_events_per_conversation=max_events,
                        event_continuation_token=(
                            hangouts_pb2.EventContinuationToken(
                                event_timestamp=parsers.to_timestamp(
                                    conv_event.timestamp)))))
                conv_events = [
                    self._wrap_event(event)
                    for event in res.conversation_state.event
                ]
                logger.info('Loaded {} events for conversation {}'.format(
                    len(conv_events), self.id_))
                # Iterate though the events newest to oldest.
                for conv_event in reversed(conv_events):
                    # Add event as the new oldest event, unless we already have
                    # it.
                    if conv_event.id_ not in self._events_dict:
                        self._events.insert(0, conv_event)
                        self._events_dict[conv_event.id_] = conv_event
                    else:
                        # If this happens, there's probably a bug.
                        logger.info(
                            'Conversation %s ignoring duplicate event %s',
                            self.id_, conv_event.id_)
        return conv_events
示例#3
0
 async def _load_messages(self, source: 'u.User', limit: int = 100,
                          token: Optional[hangouts.EventContinuationToken] = None
                          ) -> Tuple[List[ChatMessageEvent], hangouts.EventContinuationToken]:
     resp = await source.client.get_conversation(hangouts.GetConversationRequest(
         request_header=source.client.get_request_header(),
         conversation_spec=hangouts.ConversationSpec(
             conversation_id=hangouts.ConversationId(id=self.gid),
         ),
         include_conversation_metadata=False,
         include_event=True,
         max_events_per_conversation=limit,
         event_continuation_token=token
     ))
     return ([HangoutsChat._wrap_event(evt) for evt in resp.conversation_state.event],
             resp.conversation_state.event_continuation_token)
示例#4
0
    def getconversation(self, conversation_id, event_timestamp, max_events=50):
        """Return conversation events.

        This is mainly used for retrieving conversation scrollback. Events
        occurring before event_timestamp are returned, in order from oldest to
        newest.

        Raises hangups.NetworkError if the request fails.
        """
        request = hangouts_pb2.GetConversationRequest(
            request_header=self._get_request_header_pb(),
            conversation_spec=hangouts_pb2.ConversationSpec(
                conversation_id=hangouts_pb2.ConversationId(id=conversation_id)
            ),
            include_event=True,
            max_events_per_conversation=max_events,
            event_continuation_token=hangouts_pb2.EventContinuationToken(
                event_timestamp=parsers.to_timestamp(event_timestamp)
            ),
        )
        response = hangouts_pb2.GetConversationResponse()
        yield from self._pb_request('conversations/getconversation', request,
                                    response)
        return response
示例#5
0
    def get_events(self, event_id=None, max_events=50):
        """Get events from this conversation.

        Makes a request to load historical events if necessary.

        Args:
            event_id (str): (optional) If provided, return events preceding
                this event, otherwise return the newest events.
            max_events (int): Maximum number of events to return. Defaults to
                50.

        Returns:
            List of :class:`.ConversationEvent` instances, ordered
            newest-first.

        Raises:
            KeyError: If ``event_id`` does not correspond to a known event.
            .NetworkError: If the events could not be requested.
        """
        if event_id is None:
            # If no event_id is provided, return the newest events in this
            # conversation.
            conv_events = self._events[-1 * max_events:]
        else:
            # If event_id is provided, return the events we have that are
            # older, or request older events if event_id corresponds to the
            # oldest event we have.
            conv_event = self.get_event(event_id)
            if self._events[0].id_ != event_id:
                conv_events = self._events[self._events.index(conv_event) + 1:]
            else:
                logger.info(
                    'Loading events for conversation {} before {}'.format(
                        self.id_, conv_event.timestamp))
                res = yield from self._client.get_conversation(
                    hangouts_pb2.GetConversationRequest(
                        request_header=self._client.get_request_header(),
                        conversation_spec=hangouts_pb2.ConversationSpec(
                            conversation_id=hangouts_pb2.ConversationId(
                                id=self.id_)),
                        include_event=True,
                        max_events_per_conversation=max_events,
                        event_continuation_token=(
                            hangouts_pb2.EventContinuationToken(
                                event_timestamp=parsers.to_timestamp(
                                    conv_event.timestamp)))))
                conv_events = [
                    self._wrap_event(event)
                    for event in res.conversation_state.event
                ]
                logger.info('Loaded {} events for conversation {}'.format(
                    len(conv_events), self.id_))
                # Iterate though the events newest to oldest.
                for conv_event in reversed(conv_events):
                    # Add event as the new oldest event, unless we already have
                    # it.
                    if conv_event.id_ not in self._events_dict:
                        self._events.insert(0, conv_event)
                        self._events_dict[conv_event.id_] = conv_event
                    else:
                        # If this happens, there's probably a bug.
                        logger.info(
                            'Conversation %s ignoring duplicate event %s',
                            self.id_, conv_event.id_)
        return conv_events
示例#6
0
    async def get_events(self, event_id=None, max_events=50):
        """Get events from this conversation.

        Makes a request to load historical events if necessary.

        Args:
            event_id (str): (optional) If provided, return events preceding
                this event, otherwise return the newest events.
            max_events (int): Maximum number of events to return. Defaults to
                50.

        Returns:
            List of :class:`.ConversationEvent` instances, ordered
            oldest-first.

        Raises:
            KeyError: If ``event_id`` does not correspond to a known event.
            .NetworkError: If the events could not be requested.
        """
        if event_id is None:
            # If no event_id is provided, return the newest events in this
            # conversation.
            conv_events = self._events[-1 * max_events:]
        else:
            # If event_id is provided, return the events we have that are
            # older, or request older events if event_id corresponds to the
            # oldest event we have.
            conv_event = self.get_event(event_id)
            if self._events[0].id_ != event_id:
                # Return at most max_events events preceding the event at this
                # index.
                index = self._events.index(conv_event)
                conv_events = self._events[max(index - max_events, 0):index]
            else:
                logger.info(
                    'Loading events for conversation {} before {}'.format(
                        self.id_, conv_event.timestamp))
                res = await self._client.get_conversation(
                    hangouts_pb2.GetConversationRequest(
                        request_header=self._client.get_request_header(),
                        conversation_spec=hangouts_pb2.ConversationSpec(
                            conversation_id=hangouts_pb2.ConversationId(
                                id=self.id_)),
                        include_event=True,
                        max_events_per_conversation=max_events,
                        event_continuation_token=self._event_cont_token))
                # Certain fields of conversation_state are not populated by
                # SyncRecentConversations. This is the case with the
                # user_read_state fields which are all set to 0 but for the
                # 'self' user. Update here so these fields get populated on the
                # first call to GetConversation.
                if res.conversation_state.HasField('conversation'):
                    self.update_conversation(
                        res.conversation_state.conversation)
                self._event_cont_token = (
                    res.conversation_state.event_continuation_token)
                conv_events = [
                    self._wrap_event(event)
                    for event in res.conversation_state.event
                ]
                logger.info('Loaded {} events for conversation {}'.format(
                    len(conv_events), self.id_))
                # Iterate though the events newest to oldest.
                for conv_event in reversed(conv_events):
                    # Add event as the new oldest event, unless we already have
                    # it.
                    if conv_event.id_ not in self._events_dict:
                        self._events.insert(0, conv_event)
                        self._events_dict[conv_event.id_] = conv_event
                    else:
                        # If this happens, there's probably a bug.
                        logger.info(
                            'Conversation %s ignoring duplicate event %s',
                            self.id_, conv_event.id_)
        return conv_events