Skip to content
This repository has been archived by the owner on Sep 16, 2021. It is now read-only.

Commit

Permalink
full refactor of hangups_conversation
Browse files Browse the repository at this point in the history
move from incomplete namedtuple entities to hangups.hangouts_pb2 and introduce therewith full compatibility to hangups
merge ```FakeConversation``` and ```HangupsConversation```
add documentation
apply style
use hangups as source for the base conv, with fallback to permamem, and then a fallback to a basic convmem entry; it is only possible to get the basic entry on an invalid convid or a conv from which the bot got kicked and the permamem was already updated
use the new permamem entrys ```status``` and ```link_sharing``` introduced in a66e75c
  • Loading branch information
das7pad committed Jun 3, 2017
1 parent a66e75c commit 6378d0e
Showing 1 changed file with 94 additions and 136 deletions.
230 changes: 94 additions & 136 deletions hangupsbot/hangups_conversation.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down

0 comments on commit 6378d0e

Please sign in to comment.