Skip to content

Commit

Permalink
Add rrule support to search api
Browse files Browse the repository at this point in the history
  • Loading branch information
OneBlue committed Nov 2, 2024
1 parent 4caf64f commit 806bfc4
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 4 deletions.
27 changes: 23 additions & 4 deletions events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,31 @@ def match(event) -> bool:
if (exact and not search_term == title) or (not exact and search_term.lower() not in title.lower()):
return False

if 'dtend' in event:
if datetime.timestamp(rationalize_time(event['dtend'].dt)) < after:
# Special case for repeating events
if 'rrule' in event:
if not 'dtstart' in event:
logging.warning(f'Event {event} has rrule but not dtstart')
return False # Invalid event, ignore

rule = rrulestr(event['rrule'].to_ical().decode(), dtstart=rationalize_time(event['dtstart'].dt))

begin = None
if 'dtstart' in event and before != inf:
begin = rule.after(rationalize_time(datetime.fromtimestamp(before)), inc=True)

end = None
if 'dtend' in event and after != 0:
end = rule.after(rationalize_time(datetime.fromtimestamp(after)), inc=True)
else:
begin = None if not 'dtstart' in event else event['dtstart'].dt
end = None if not 'dtend' in event else event['dtend'].dt

if end is not None:
if datetime.timestamp(rationalize_time(end)) < after:
return False

if 'dtstart' in event:
if datetime.timestamp(rationalize_time(event['dtstart'].dt)) > before:
if begin is not None:
if datetime.timestamp(rationalize_time(begin)) > before:
return False

return True
Expand Down
27 changes: 27 additions & 0 deletions events/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@
event_14.add('attendee', 'MAILTO:[email protected]')
event_14['sequence'] = 11

yearly_repeating_event = Event()
yearly_repeating_event.add('rrule', {'FREQ': 'YEARLY'})
yearly_repeating_event.add('dtstart', datetime(2013, 10, 10, 10, 0, 0))
yearly_repeating_event.add('dtend', datetime(2013, 10, 10, 10, 0, 0))
yearly_repeating_event['summary'] = 'yearly_repeating_event'
yearly_repeating_event.add('created', datetime(2013, 10, 10, 10, 0, 0))
yearly_repeating_event['uid'] = 'yearly_repeating_event'


save_event_override = None

Expand All @@ -146,6 +154,7 @@ def __init__(self, read_only):
'event_12': event_12,
'event_13': event_13,
'event_14': event_14,
'yearly_repeating_event': yearly_repeating_event,
}

def get_event_impl(self, name: str):
Expand Down Expand Up @@ -343,6 +352,24 @@ def test_search_api_strip(client):
order = [e['title'] for e in content]
assert order == ['event_1']

def test_search_rrule_exact_match(client):
after = datetime.timestamp(yearly_repeating_event['dtend'].dt)
before = datetime.timestamp(yearly_repeating_event['dtstart'].dt)
content = search_api(client, "yearly_repeating_event", before=before, after=after)
assert [e['title'] for e in content] == ['yearly_repeating_event']

def test_search_rrule_negative(client):
after = datetime.timestamp(yearly_repeating_event['dtend'].dt)
before = datetime.timestamp(yearly_repeating_event['dtstart'].dt - timedelta(hours=1))
content = search_api(client, "yearly_repeating_event", before=before, after=after)
assert content == []

def test_search_rrule_occurence(client):
after = datetime.timestamp(yearly_repeating_event['dtend'].dt + timedelta(days=365))
before = datetime.timestamp(yearly_repeating_event['dtstart'].dt + timedelta(days=365))
content = search_api(client, "yearly_repeating_event", before=before, after=after)
assert [e['title'] for e in content] == ['yearly_repeating_event']

def test_view_event_admin(client):
response = client.get('/1/event_1.ics', headers={'X-Admin': 'true'})

Expand Down

0 comments on commit 806bfc4

Please sign in to comment.