Skip to content

Commit

Permalink
Send messages with correct delivery medium
Browse files Browse the repository at this point in the history
Read the default delivery medium from conversations and use it when
sending messages. This allows sending messages correctly to
conversations using alternate delivery mediums, such as Google Voice.

Fixes #53.
  • Loading branch information
tdryer committed Sep 11, 2015
1 parent 0a0c931 commit cfc0db1
Show file tree
Hide file tree
Showing 5 changed files with 346 additions and 302 deletions.
11 changes: 6 additions & 5 deletions docs/proto.rst
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,12 @@ Field Number Type Label Description
DeliveryMedium
--------------

=================== ====== ===================== ======== ===========
Field Number Type Label Description
=================== ====== ===================== ======== ===========
:code:`medium_type` 1 `DeliveryMediumType`_ optional
=================== ====== ===================== ======== ===========
=================== ====== ===================== ======== ======================================================
Field Number Type Label Description
=================== ====== ===================== ======== ======================================================
:code:`medium_type` 1 `DeliveryMediumType`_ optional
:code:`phone` 2 `Phone`_ optional Phone number to use for sending Google Voice messages.
=================== ====== ===================== ======== ======================================================

DeliveryMediumOption
--------------------
Expand Down
11 changes: 7 additions & 4 deletions hangups/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,8 @@ def syncallnewevents(self, timestamp):
@asyncio.coroutine
def sendchatmessage(
self, conversation_id, segments, image_id=None,
otr_status=hangouts_pb2.OFF_THE_RECORD_STATUS_ON_THE_RECORD):
otr_status=hangouts_pb2.OFF_THE_RECORD_STATUS_ON_THE_RECORD,
delivery_medium=None):
"""Send a chat message to a conversation.
conversation_id must be a valid conversation ID. segments must be a
Expand All @@ -501,6 +502,10 @@ def sendchatmessage(
segment_pb = hangouts_pb2.Segment()
pblite.decode(segment_pb, segment_pblite)
segments_pb.append(segment_pb)
if delivery_medium is None:
delivery_medium = hangouts_pb2.DeliveryMedium(
medium_type=hangouts_pb2.DELIVERY_MEDIUM_BABEL,
)

request = hangouts_pb2.SendChatMessageRequest(
request_header=self._get_request_header_pb(),
Expand All @@ -513,9 +518,7 @@ def sendchatmessage(
),
client_generated_id=self.get_client_generated_id(),
expected_otr=otr_status,
delivery_medium=hangouts_pb2.DeliveryMedium(
medium_type=hangouts_pb2.DELIVERY_MEDIUM_BABEL,
),
delivery_medium=delivery_medium,
event_type=hangouts_pb2.EVENT_TYPE_REGULAR_CHAT_MESSAGE,
),
)
Expand Down
41 changes: 37 additions & 4 deletions hangups/conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,20 @@ def _on_watermark_notification(self, notif):

def update_conversation(self, conversation):
"""Update the internal Conversation."""
# When latest_read_timestamp is 0, this seems to indicate no change
# from the previous value. Word around this by saving and restoring the
# previous value.
# StateUpdate.conversation is actually a delta; fields that aren't
# specified are assumed to be unchanged. Until this class is
# refactored, hide this by saving and restoring previous values where
# necessary.

# delivery_medium_option
new_state = conversation.self_conversation_state
if len(new_state.delivery_medium_option) == 0:
old_state = self._conversation.self_conversation_state
new_state.delivery_medium_option.extend(
old_state.delivery_medium_option
)

# latest_read_timestamp
old_timestamp = self.latest_read_timestamp
self._conversation = conversation
if parsers.to_timestamp(self.latest_read_timestamp) == 0:
Expand Down Expand Up @@ -98,6 +109,27 @@ def get_user(self, user_id):
"""Return the User instance with the given UserID."""
return self._user_list.get_user(user_id)

def _get_default_delivery_medium(self):
"""Return default DeliveryMedium to use for sending messages.
Use the first option, or an option that's marked as the current
default.
"""
medium_options = (
self._conversation.self_conversation_state.delivery_medium_option
)
try:
default_medium = medium_options[0].delivery_medium
except IndexError:
logger.warning('Conversation %r has no delivery medium')
default_medium = hangouts_pb2.DeliveryMedium(
medium_type=hangouts_pb2.DELIVERY_MEDIUM_BABEL
)
for medium_option in medium_options:
if medium_option.current_default:
default_medium = medium_option.delivery_medium
return default_medium

@asyncio.coroutine
def send_message(self, segments, image_file=None, image_id=None):
"""Send a message to this conversation.
Expand Down Expand Up @@ -131,7 +163,8 @@ def send_message(self, segments, image_file=None, image_id=None):
try:
yield from self._client.sendchatmessage(
self.id_, [seg.serialize() for seg in segments],
image_id=image_id, otr_status=otr_status
image_id=image_id, otr_status=otr_status,
delivery_medium=self._get_default_delivery_medium()
)
except exceptions.NetworkError as e:
logger.warning('Failed to send message: {}'.format(e))
Expand Down
5 changes: 2 additions & 3 deletions hangups/hangouts.proto
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,8 @@ enum DeliveryMediumType {

message DeliveryMedium {
optional DeliveryMediumType medium_type = 1;

// TODO: add this for sending google voice messages?
//optional Phone phone = 2;
// Phone number to use for sending Google Voice messages.
optional Phone phone = 2;
}

message DeliveryMediumOption {
Expand Down
580 changes: 294 additions & 286 deletions hangups/hangouts_pb2.py

Large diffs are not rendered by default.

0 comments on commit cfc0db1

Please sign in to comment.