def create_event(self, event): """Creates the event in Google Calendar. :param event: The event to create. :type event: :class:`Event` :raises: :class:`EventumError.GCalAPI.BadStatusLine`, :class:`EventumError.GCalAPI.NotFound` :returns: The Google Calendar API response. :rtype: dict """ self.before_request() resource = None resource = GoogleCalendarResourceBuilder.event_resource(event) calendar_id = self._calendar_id_for_event(event) current_app.logger.info('[GOOGLE_CALENDAR]: Create Event') request = self.service.events().insert(calendarId=calendar_id, body=resource) # Execute the request created_event = self._execute_request(request) # Update the Event with the latest info from the response. self._update_event_from_response(event, created_event) # Return the Google Calendar response dict return created_event
def _instance_resource_for_event_in_series(self, event): """Searches through the instances of ``event``'s parent series, returning the Google Calendar instance resource for with ``start_time`` that matches ``event``'s. :param event: The event to find the instance resource for. :type event: :class:`Event` :returns: The instance resource that represents ``event``. :rtype: dict """ calendar_id = self._calendar_id_for_event(event) event_start_date = (GoogleCalendarResourceBuilder.rfc3339( event.start_datetime)) page_token = None while True: # Find more instances request = self.service.events().instances(calendarId=calendar_id, eventId=event.gcal_id, pageToken=page_token) instances = self._execute_request(request) # Look for instances with matching start date for instance in instances['items']: if instance['start']['dateTime'] == event_start_date: return instance # Get the next page of events page_token = instances.get('nextPageToken') # Quit if there are no more pages if not page_token: break return None
def delete_event(self, event, as_exception=False): """Delete an event or series from Google Calendar, or cancel a single event from a series. :param event: The event to delete. :type event: :class:`Event` :param bool as_exception: Whether or not to cancel this event as an exception in a series. Otherwise, series' will be deleted in their entirety. :raises: :class:`EventumError.GCalAPI.BadStatusLine`, :class:`EventumError.GCalAPI.NotFound`, :class:`EventumError.GCalAPI.MissingID` :returns: The Google Calendar API response. :rtype: dict """ self.before_request() if not event.gcal_id: raise EventumError.GCalAPI.MissingID() calendar_id = self._calendar_id_for_event(event) # Create the request if as_exception: current_app.logger.info( '[GOOGLE_CALENDAR]: Delete Event (as exception)') resource = GoogleCalendarResourceBuilder.event_resource(event) instance = self._instance_resource_for_event_in_series(event) instance.update(resource) instance['status'] = u'cancelled' request = self.service.events().update(calendarId=calendar_id, eventId=instance['id'], body=instance) else: current_app.logger.info('[GOOGLE_CALENDAR]: Delete Event') request = self.service.events().delete(calendarId=calendar_id, eventId=event.gcal_id) # Execute the request, failing silently if the event has already been # deleted from Google Calendar. try: return self._execute_request(request) except EventumError.GCalAPI.NotFound as e: # If the resource has already been deleted, fail quietly. raise EventumError.GCalAPI.EventAlreadyDeleted(e=e)
def update_event(self, stale_event, as_exception=False): """Updates the event in Google Calendar. The first argument is called ``stale_event`` because it might have outdated fields. The first thing we do is find a fresh event with it's id in mongo. This method will fall back to creating a new event if we don't have reference to a ``gcal_id`` for the event, or if the update otherwise fails. :param stale_event: The event to update. :type stale_event: :class:`Event` :param bool as_exception: Whether or not this update should happen as an exception in a series. Otherwise, series' will be updated in their entirety. :raises: :class:`EventumError.GCalAPI.BadStatusLine`, :class:`EventumError.GCalAPI.NotFound`, :class:`EventumError.GCalAPI.MissingID` :returns: The Google Calendar API response. :rtype: dict """ self.before_request() # Freshen up stale_event event = Event.objects().get(id=stale_event.id) if not event.gcal_id: # If we don't have a reference if it's associate Google Calendar # ID, then create it fresh. This raises still because it # *shouldn't* ever happen, but it does. self.create_event(stale_event) raise EventumError.GCalAPI.MissingID.UpdateFellBackToCreate() resource = None resource = GoogleCalendarResourceBuilder.event_resource( event, for_update=True) calendar_id = self._calendar_id_for_event(event) # If this update should be an exception to a series of events, then # we only want to update the instance id. Otherwise, using the # ``event.gcal_id`` will update the entire series. event_id_for_update = event.gcal_id if as_exception: instance = self._instance_resource_for_event_in_series(event) instance.update(resource) resource = instance event_id_for_update = instance['id'] current_app.logger.info('[GOOGLE_CALENDAR]: Update Event') request = self.service.events().update(calendarId=calendar_id, eventId=event_id_for_update, body=resource) # Send the request, falling back to update if it fails. try: updated_event = self._execute_request(request) except EventumError.GCalAPI.NotFound as e: self.create_event(event) raise EventumError.GCalAPI.NotFound.UpdateFellBackToCreate(e=e) # Update the Event with the latest info from the response. self._update_event_from_response(event, updated_event) # Return the Google Calendar response dict return updated_event