diff --git a/hangupsbot/hangups_conversation.py b/hangupsbot/hangups_conversation.py index 4bb715b77..1757e3dba 100644 --- a/hangupsbot/hangups_conversation.py +++ b/hangupsbot/hangups_conversation.py @@ -1,160 +1,118 @@ -import asyncio, logging, time - -from collections import namedtuple +"""enhanced hangups conversation that supports a fallback to cached data""" +# pylint: disable=W0212 +import logging +import time import hangups - -import hangups_shim - -from utils import ( simple_parse_to_segments, - segment_to_html ) - +from hangups import hangouts_pb2 logger = logging.getLogger(__name__) -ConversationID = namedtuple('conversation_id', ['id', 'id_']) - -ClientConversation = namedtuple( 'client_conversation', - [ 'conversation_id', - 'current_participant', - 'name', - 'otr_status', - 'participant_data', - 'read_state', - 'self_conversation_state', - 'type_' ]) - -ParticipantData = namedtuple( 'participant_data', - [ 'fallback_name', - 'id_' ]) - -LastRead = namedtuple( "read_state", - [ 'last_read_timestamp', - 'participant_id' ]) - -LatestRead = namedtuple( "self_read_state", - [ "latest_read_timestamp", - "participant_id" ]) - -SelfConversationState = namedtuple( 'self_conversation_state', - [ 'active_timestamp', - 'invite_timestamp', - 'inviter_id', - 'notification_level', - 'self_read_state', - 'sort_timestamp', - 'status', - 'view' ]) - - class HangupsConversation(hangups.conversation.Conversation): - bot = None + """Conversation with fallback to permamem + Args: + bot: HangupsBot instance + conv_id: string, Hangouts conversation identifier + """ def __init__(self, bot, conv_id): self.bot = bot self._client = bot._client + self._user_list = bot._user_list + # retrieve the conversation record from hangups, if available + try: + conversation = bot._conv_list.get(conv_id)._conversation + super().__init__(self._client, self._user_list, conversation, []) + return + except KeyError: + logger.debug("%s not found in conv list", conv_id) # retrieve the conversation record from permamem - permamem_conv = bot.conversations.catalog[conv_id] - - # retrieve the conversation record from hangups, if available - hangups_conv = False - if conv_id in bot._conv_list._conv_dict: - hangups_conv = bot._conv_list._conv_dict[conv_id]._conversation + try: + permamem_conv = bot.conversations[conv_id] + except KeyError: + logger.warning("%s not found in permamem", conv_id) + permamem_conv = { + "title": "I GOT KICKED", + "type": "GROUP", + "history": False, + "status": "DEFAULT", + "link_sharing": False, + "participants": [], + + } # set some basic variables - bot_user = bot.user_self() - timestamp_now = int(time.time() * 1000000) + bot_chat_id = bot.user_self()["chat_id"] - if permamem_conv["history"]: - otr_status = hangups_shim.schemas.OffTheRecordStatus.ON_THE_RECORD - else: - otr_status = hangups_shim.schemas.OffTheRecordStatus.OFF_THE_RECORD + otr_status = (hangouts_pb2.OFF_THE_RECORD_STATUS_ON_THE_RECORD + if permamem_conv["history"] else + hangouts_pb2.OFF_THE_RECORD_STATUS_OFF_THE_RECORD) - if permamem_conv["type"] == "GROUP": - type_ = hangups_shim.schemas.ConversationType.GROUP - else: - type_ = hangups_shim.schemas.ConversationType.STICKY_ONE_TO_ONE + status = (hangouts_pb2.CONVERSATION_STATUS_INVITED + if permamem_conv["status"] == "INVITED" else + hangouts_pb2.CONVERSATION_STATUS_ACTIVE) current_participant = [] participant_data = [] read_state = [] - - participants = permamem_conv["participants"][:] # use a clone - participants.append(bot_user["chat_id"]) - participants = set(participants) - for chat_id in participants: - hangups_user = bot.get_hangups_user(chat_id) - - UserID = hangups.user.UserID(chat_id=hangups_user.id_.chat_id, gaia_id=hangups_user.id_.gaia_id) - current_participant.append(UserID) - - ParticipantInfo = ParticipantData( fallback_name=hangups_user.full_name, - id_=UserID ) - - participant_data.append(ParticipantInfo) - - if not hangups_conv: - read_state.append( LastRead( last_read_timestamp=0, - participant_id=UserID )) - - active_timestamp = timestamp_now - invite_timestamp = timestamp_now - inviter_id = hangups.user.UserID( chat_id=bot_user["chat_id"], - gaia_id=bot_user["chat_id"] ) - latest_read_timestamp = timestamp_now - sort_timestamp = timestamp_now - - if hangups_conv: - read_state = hangups_conv.read_state[:] - active_timestamp = hangups_conv.self_conversation_state.active_timestamp - invite_timestamp = hangups_conv.self_conversation_state.invite_timestamp - inviter_id = hangups_conv.self_conversation_state.inviter_id - latest_read_timestamp = hangups_conv.self_conversation_state.self_read_state.latest_read_timestamp - sort_timestamp = hangups_conv.self_conversation_state.sort_timestamp - logger.debug("properties cloned from hangups conversation") - - conversation_id = ConversationID( id = conv_id, - id_ = conv_id ) - - self_conversation_state = SelfConversationState( active_timestamp=timestamp_now, - invite_timestamp=timestamp_now, - inviter_id=hangups.user.UserID( chat_id=bot_user["chat_id"], - gaia_id=bot_user["chat_id"] ), - notification_level=hangups_shim.schemas.ClientNotificationLevel.RING, - self_read_state=LatestRead( latest_read_timestamp=latest_read_timestamp, - participant_id=hangups.user.UserID( chat_id=bot_user["chat_id"], - gaia_id=bot_user["chat_id"] )), - sort_timestamp=sort_timestamp, - status=hangups_shim.schemas.ClientConversationStatus.ACTIVE, - view=hangups_shim.schemas.ClientConversationView.INBOX_VIEW ) - - self._conversation = ClientConversation( conversation_id=conversation_id, - current_participant=current_participant, - name=permamem_conv["title"], - otr_status=otr_status, - participant_data=participant_data, - read_state=read_state, - self_conversation_state=self_conversation_state, - type_=type_ ) - - # initialise blank - self._user_list = [] - self._events = [] - self._events_dict = {} - self._send_message_lock = asyncio.Lock() - - @property - def users(self): - return [ self.bot.get_hangups_user(part.id_.chat_id) for part in self._conversation.participant_data ] - - -class FakeConversation(object): - def __init__(self, bot, id_): - self.bot = bot - self._client = self.bot._client - self.id_ = id_ + now = int(time.time() * 1000000) + + for chat_id in set(permamem_conv["participants"] + [bot_chat_id]): + part_id = hangouts_pb2.ParticipantId(chat_id=chat_id, + gaia_id=chat_id) + + current_participant.append(part_id) + + participant_data.append(hangouts_pb2.ConversationParticipantData( + fallback_name=bot.get_hangups_user(chat_id).full_name, + id=part_id)) + + read_state.append(hangouts_pb2.UserReadState( + latest_read_timestamp=now, participant_id=part_id)) + + conversation = hangouts_pb2.Conversation( + conversation_id=hangouts_pb2.ConversationId(id=conv_id), + + type=(hangouts_pb2.CONVERSATION_TYPE_GROUP + if permamem_conv["type"] == "GROUP" else + hangouts_pb2.CONVERSATION_TYPE_ONE_TO_ONE), + + has_active_hangout=True, + name=permamem_conv["title"], + + current_participant=current_participant, + participant_data=participant_data, + read_state=read_state, + + self_conversation_state=hangouts_pb2.UserConversationState( + client_generated_id=str(self._client.get_client_generated_id()), + self_read_state=hangouts_pb2.UserReadState( + latest_read_timestamp=now, + participant_id=hangouts_pb2.ParticipantId( + chat_id=bot_chat_id, gaia_id=bot_chat_id)), + status=status, + notification_level=hangouts_pb2.NOTIFICATION_LEVEL_RING, + view=[hangouts_pb2.CONVERSATION_VIEW_INBOX], + delivery_medium_option=[hangouts_pb2.DeliveryMediumOption( + delivery_medium=hangouts_pb2.DeliveryMedium( + medium_type=hangouts_pb2.DELIVERY_MEDIUM_BABEL))]), + + conversation_history_supported=True, + otr_status=otr_status, + otr_toggle=(hangouts_pb2.OFF_THE_RECORD_TOGGLE_ENABLED + if status == hangouts_pb2.CONVERSATION_STATUS_ACTIVE + else hangouts_pb2.OFF_THE_RECORD_TOGGLE_DISABLED), + + network_type=[hangouts_pb2.NETWORK_TYPE_BABEL], + force_history_state=hangouts_pb2.FORCE_HISTORY_NO, + group_link_sharing_status=( + hangouts_pb2.GROUP_LINK_SHARING_STATUS_ON + if permamem_conv['link_sharing'] else + hangouts_pb2.GROUP_LINK_SHARING_STATUS_OFF)) + + super().__init__(self._client, self._user_list, conversation, []) @asyncio.coroutine def send_message(self, message, image_id=None, otr_status=None, context=None):