Skip to content

Commit

Permalink
Message now recognizes EventMessages.
Browse files Browse the repository at this point in the history
An EventMessage can retrieve the related Event
As requested by googleapis#197
  • Loading branch information
Alejandro Casanovas committed Mar 4, 2019
1 parent b7f9bbe commit 290b7c6
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 11 deletions.
2 changes: 1 addition & 1 deletion O365/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,7 @@ def __init__(self, *, parent=None, con=None, **kwargs):
""" Create a calendar event representation
:param parent: parent for this operation
:type parent: Calendar or Schedule
:type parent: Calendar or Schedule or ApiComponent
:param Connection con: connection to use if no parent specified
:param Protocol protocol: protocol to use if no parent specified
(kwargs)
Expand Down
3 changes: 3 additions & 0 deletions O365/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ def __init__(self, api_version='v1.0', default_resource=ME_RESOURCE,
**kwargs)

self.keyword_data_store['message_type'] = 'microsoft.graph.message'
self.keyword_data_store['event_message_type'] = 'microsoft.graph.eventMessage'
self.keyword_data_store[
'file_attachment_type'] = '#microsoft.graph.fileAttachment'
self.keyword_data_store[
Expand Down Expand Up @@ -241,6 +242,8 @@ def __init__(self, api_version='v2.0', default_resource=ME_RESOURCE,

self.keyword_data_store[
'message_type'] = 'Microsoft.OutlookServices.Message'
self.keyword_data_store[
'event_message_type'] = 'Microsoft.OutlookServices.EventMessage'
self.keyword_data_store[
'file_attachment_type'] = '#Microsoft.OutlookServices.' \
'FileAttachment'
Expand Down
59 changes: 54 additions & 5 deletions O365/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@
from .utils import OutlookWellKnowFolderNames, ApiComponent, \
BaseAttachments, BaseAttachment, AttachableMixin, ImportanceLevel, \
TrackerSet, Recipient, HandleRecipientsMixin
from .calendar import Event

log = logging.getLogger(__name__)


class MeetingMessageType(Enum):
NoneMessageType = 'none'
MeetingRequest = 'meetingRequest'
MeetingCancelled = 'meetingCancelled'
MeetingAccepted = 'meetingAccepted'
MeetingTentativelyAccepted = 'meetingTentativelyAccepted'
MeetingDeclined = 'meetingDeclined'


class MessageAttachment(BaseAttachment):
_endpoints = {
'attach': '/messages/{id}/attachments',
Expand Down Expand Up @@ -247,7 +257,10 @@ def __init__(self, *, parent=None, con=None, **kwargs):
self.__is_read_receipt_requested = cloud_data.get(cc('isReadReceiptRequested'), False)
self.__is_delivery_receipt_requested = cloud_data.get(cc('isDeliveryReceiptRequested'), False)

# A message is a draft by default
# if this message is an EventMessage:
self.__meeting_message_type = MeetingMessageType(cloud_data.get(cc('meetingMessageType'), 'none'))

# a message is a draft by default
self.__is_draft = cloud_data.get(cc('isDraft'), kwargs.get('is_draft',
True))
self.conversation_id = cloud_data.get(cc('conversationId'), None)
Expand All @@ -256,6 +269,12 @@ def __init__(self, *, parent=None, con=None, **kwargs):
flag_data = cloud_data.get(cc('flag'), {})
self.__flag = MessageFlag(parent=self, flag_data=flag_data)

def __str__(self):
return self.__repr__()

def __repr__(self):
return 'Subject: {}'.format(self.subject)

def _clear_tracker(self):
# reset the tracked changes. Usually after a server update
self._track_changes = TrackerSet(casing=self._cc)
Expand Down Expand Up @@ -460,6 +479,21 @@ def is_delivery_receipt_requested(self, value):
self.__is_delivery_receipt_requested = bool(value)
self._track_changes.add('isDeliveryReceiptRequested')

@property
def meeting_message_type(self):
""" If this message is a EventMessage, returns the
meeting type: meetingRequest, meetingCancelled, meetingAccepted,
meetingTentativelyAccepted, meetingDeclined
"""
return self.__meeting_message_type

@property
def is_event_message(self):
""" Returns if this message is of type EventMessage
and therefore can return the related event.
"""
return self.__meeting_message_type is not MeetingMessageType.NoneMessageType

@property
def flag(self):
""" The Message Flag instance """
Expand Down Expand Up @@ -868,8 +902,23 @@ def get_body_soup(self):
else:
return bs(self.body, 'html.parser')

def __str__(self):
return self.__repr__()
def get_event(self):
""" If this is a EventMessage it should return the related Event"""

def __repr__(self):
return 'Subject: {}'.format(self.subject)
if not self.is_event_message:
return None

# select a dummy field (eg. subject) to avoid pull unneccesary data
query = self.q().select('subject').expand('event')

url = self.build_url(self._endpoints.get('get_message').format(id=self.object_id))

response = self.con.get(url, params=query.as_params())

if not response:
return None

data = response.json()
event_data = data.get(self._cc('event'))

return Event(parent=self, **{self._cloud_data_key: event_data})
50 changes: 45 additions & 5 deletions O365/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,11 +547,13 @@ def __init__(self, attribute=None, *, protocol):
self._filters = [] # store all the filters
self._order_by = OrderedDict()
self._selects = set()
self._expands = set()

def __str__(self):
return 'Filter: {}\nOrder: {}\nSelect: {}'.format(self.get_filters(),
self.get_order(),
self.get_selects())
return 'Filter: {}\nOrder: {}\nSelect: {}\nExpand: {}'.format(self.get_filters(),
self.get_order(),
self.get_selects(),
self.get_expands())

def __repr__(self):
return self.__str__()
Expand Down Expand Up @@ -580,6 +582,24 @@ def select(self, *attributes):

return self

@fluent
def expand(self, *relationships):
""" Adds the relationships (e.g. "event" or "attachments")
that should be expanded with the $expand parameter
Important: The ApiComponent using this should know how to handle this relationships.
eg: Message knows how to handle attachments, and event (if it's an EventMessage).
Important: When using expand on multi-value relationships a max of 20 items will be returned.
:param str relationships: the relationships tuple to expand.
:rtype: Query
"""

for relationship in relationships:
if relationship == 'event':
relationship = '{}/event'.format(self.protocol.get_service_keyword('event_message_type'))
self._expands.add(relationship)

return self

def as_params(self):
""" Returns the filters and orders as query parameters
Expand All @@ -592,6 +612,8 @@ def as_params(self):
params['$orderby'] = self.get_order()
if self.has_selects:
params['$select'] = self.get_selects()
if self.has_expands:
params['$expand'] = self.get_expands()
return params

@property
Expand All @@ -618,6 +640,14 @@ def has_selects(self):
"""
return bool(self._selects)

@property
def has_expands(self):
""" Whether the query has relationships that should be expanded or not
:rtype: bool
"""
return bool(self._expands)

def get_filters(self):
""" Returns the result filters
Expand Down Expand Up @@ -674,6 +704,16 @@ def get_selects(self):
else:
return None

def get_expands(self):
""" Returns the result expand clause
:rtype: str or None
"""
if self._expands:
return ','.join(self._expands)
else:
return None

def _get_mapping(self, attribute):
if attribute:
mapping = self._mapping.get(attribute)
Expand Down Expand Up @@ -830,7 +870,7 @@ def logical_operator(self, operation, word):
word = self._parse_filter_word(word)
self._add_filter(
*self._prepare_sentence(self._attribute, operation, word,
self._negation))
self._negation))
return self

@fluent
Expand Down Expand Up @@ -905,7 +945,7 @@ def function(self, function_name, word):

self._add_filter(
*self._prepare_function(function_name, self._attribute, word,
self._negation))
self._negation))
return self

@fluent
Expand Down

0 comments on commit 290b7c6

Please sign in to comment.