Ejemplo n.º 1
0
    def get_recurring_timeline(self, selected, spiked=False, rescheduled=False, cancelled=False, postponed=False):
        """Utility method to get all events in the series

        This splits up the series of events into 3 separate arrays.
        Historic: event.dates.start < utcnow()
        Past: utcnow() < event.dates.start < selected.dates.start
        Future: event.dates.start > selected.dates.start
        """
        excluded_states = []

        if not spiked:
            excluded_states.append(WORKFLOW_STATE.SPIKED)
        if not rescheduled:
            excluded_states.append(WORKFLOW_STATE.RESCHEDULED)
        if not cancelled:
            excluded_states.append(WORKFLOW_STATE.CANCELLED)
        if not postponed:
            excluded_states.append(WORKFLOW_STATE.POSTPONED)

        query = {
            '$and': [
                {'recurrence_id': selected['recurrence_id']},
                {'_id': {'$ne': selected[config.ID_FIELD]}}
            ]
        }

        if excluded_states:
            query['$and'].append({'state': {'$nin': excluded_states}})

        sort = '[("dates.start", 1)]'
        max_results = get_max_recurrent_events()
        selected_start = selected.get('dates', {}).get('start', utcnow())

        # Make sure we are working with a datetime instance
        if not isinstance(selected_start, datetime):
            selected_start = datetime.strptime(selected_start, '%Y-%m-%dT%H:%M:%S%z')

        historic = []
        past = []
        future = []

        for event in self.get_series(query, sort, max_results):
            event['dates']['end'] = event['dates']['end']
            event['dates']['start'] = event['dates']['start']
            for sched in event.get('_planning_schedule', []):
                sched['scheduled'] = sched['scheduled']
            end = event['dates']['end']
            start = event['dates']['start']
            if end < utcnow():
                historic.append(event)
            elif start < selected_start:
                past.append(event)
            elif start > selected_start:
                future.append(event)

        return historic, past, future
    def _get_series(self, original):
        query = {'$and': [{'recurrence_id': original['recurrence_id']}]}
        sort = '[("dates.start", 1)]'
        max_results = get_max_recurrent_events()

        events = []
        for event in self.get_series(query, sort, max_results):
            event['dates']['start'] = event['dates']['start']
            event['dates']['end'] = event['dates']['end']
            events.append(event)

        return events
Ejemplo n.º 3
0
    def get_expired_items(self, expiry_datetime):
        """Get the expired items

        Where end date is in the past
        """
        query = {
            'query': {
                'bool': {
                    'must_not': [{
                        'term': {
                            'expired': True
                        }
                    }]
                }
            },
            'filter': {
                'range': {
                    'dates.end': {
                        'lte': date_to_str(expiry_datetime)
                    }
                }
            },
            'sort': [{
                'dates.start': 'asc'
            }],
            'size': get_max_recurrent_events()
        }

        total_received = 0
        total_events = -1

        while True:
            query["from"] = total_received

            results = self.search(query)

            # If the total_events has not been set, then this is the first query
            # In which case we need to store the total hits from the search
            if total_events < 0:
                total_events = results.count()

                # If the search doesn't contain any results, return here
                if total_events < 1:
                    break

            # If the last query doesn't contain any results, return here
            if not len(results.docs):
                break

            total_received += len(results.docs)

            # Yield the results for iteration by the callee
            yield list(results.docs)
Ejemplo n.º 4
0
    def parse_recurring_rules(self, item, component):
        """Extracts ICS RRULE into the Event item

        :param item: The Event item
        :param component: An ICS VEVENT component
        """

        # parse ics RRULE to fit eventsML recurring_rule
        r_rule = component.get('rrule')
        if not isinstance(r_rule, vRecur):
            return

        r_rule_dict = vRecur.from_ical(r_rule)
        recurring_rule: Dict[str, Union[str, int, datetime.date,
                                        datetime.datetime]] = {}

        if r_rule.get('FREQ'):
            recurring_rule['frequency'] = ''.join(r_rule_dict['FREQ'])
        if len(r_rule.get('INTERVAL') or []):
            recurring_rule['interval'] = r_rule_dict['INTERVAL'][0]
        if len(r_rule.get('UNTIL') or []):
            recurring_rule['until'] = r_rule_dict['UNTIL'][0]
        if r_rule.get('COUNT'):
            recurring_rule['count'] = r_rule_dict['COUNT']
        if r_rule.get('BYMONTH'):
            recurring_rule['bymonth'] = ' '.join(r_rule_dict['BYMONTH'])
        if r_rule.get('BYDAY'):
            recurring_rule['byday'] = ' '.join(r_rule_dict['BYDAY'])
        if r_rule.get('BYHOUR'):
            recurring_rule['byhour'] = ' '.join(r_rule_dict['BYHOUR'])
        if r_rule.get('BYMIN'):
            recurring_rule['bymin'] = ' '.join(r_rule_dict['BYMIN'])

        if recurring_rule.get('count'):
            recurring_rule['endRepeatMode'] = 'count'
        elif recurring_rule.get('until'):
            recurring_rule['endRepeatMode'] = 'until'

            # If the `until` attribute is just a date
            # then copy the time/tzinfo from `dates.end` attribute
            if isinstance(recurring_rule['until'], datetime.date):
                end_date = item['dates']['end']
                recurring_rule['until'] = datetime.datetime.combine(
                    recurring_rule['until'], end_date.time(), end_date.tzinfo)
        else:
            # If the calendar does not provide an end date
            # then set `count` to MAX_RECURRENT_EVENTS settings
            recurring_rule['count'] = get_max_recurrent_events()
            recurring_rule['endRepeatMode'] = 'count'

        item['dates']['recurring_rule'] = recurring_rule
Ejemplo n.º 5
0
def generate_recurring_events(event):
    generated_events = []
    setRecurringMode(event)

    # Get the recurrence_id, or generate one if it doesn't exist
    recurrence_id = event.get('recurrence_id', generate_guid(type=GUID_NEWSML))

    # compute the difference between start and end in the original event
    time_delta = event['dates']['end'] - event['dates']['start']
    # for all the dates based on the recurring rules:
    for date in itertools.islice(
            generate_recurring_dates(
                start=event['dates']['start'],
                tz=event['dates'].get('tz')
                and pytz.timezone(event['dates']['tz'] or None),
                **event['dates']['recurring_rule']), 0,
            get_max_recurrent_events()
    ):  # set a limit to prevent too many events to be created
        # create event with the new dates
        new_event = copy.deepcopy(event)

        # Remove fields not required by the new events
        for key in list(new_event.keys()):
            if key.startswith('_'):
                new_event.pop(key)
            elif key.startswith('lock_'):
                new_event.pop(key)
        new_event.pop('pubstatus', None)
        new_event.pop('reschedule_from', None)

        new_event['dates']['start'] = date
        new_event['dates']['end'] = date + time_delta
        # set a unique guid
        new_event['guid'] = generate_guid(type=GUID_NEWSML)
        new_event['_id'] = new_event['guid']
        # set the recurrence id
        new_event['recurrence_id'] = recurrence_id

        # set expiry date
        overwrite_event_expiry_date(new_event)
        # the _planning_schedule
        set_planning_schedule(new_event)
        generated_events.append(new_event)

    return generated_events