Skip to content

Commit

Permalink
Fix event list lookups returning incorrect events due to pagination
Browse files Browse the repository at this point in the history
Ensures that requests using pageToken preserve the same parameters as
the initial request to avoid returning non-matching items after the
first page.
  • Loading branch information
dbarnett committed Aug 26, 2024
1 parent cec6f25 commit 56c4fb7
Showing 1 changed file with 30 additions and 51 deletions.
81 changes: 30 additions & 51 deletions gcalcli/gcal.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
import sys
import textwrap
import time
from typing import List
from typing import Iterable, List
from unicodedata import east_asian_width

import googleapiclient.http
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
from dateutil.tz import tzlocal
Expand All @@ -22,7 +23,7 @@
from google.auth.transport.requests import Request # type: ignore

from . import actions, ics, utils
from ._types import Cache, CalendarListEntry
from ._types import Cache, CalendarListEntry, Event
from .actions import ACTIONS
from .conflicts import ShowConflicts
from .details import _valid_title, ACTION_DEFAULT, DETAILS_DEFAULT, HANDLERS
Expand Down Expand Up @@ -104,7 +105,7 @@ def _select_cals(self, selected_names):
# operate against
self.cals += matches

def _retry_with_backoff(self, method):
def _retry_with_backoff(self, method: googleapiclient.http.HttpRequest):
for n in range(self.max_retries):
try:
return method.execute()
Expand Down Expand Up @@ -199,21 +200,16 @@ def _get_cached(self):
pass
# fall through

cal_list = self._retry_with_backoff(
self.get_cal_service().calendarList().list()
)

pageToken = None
while True:
for cal in cal_list['items']:
self.all_cals.append(cal)
cal_list = self._retry_with_backoff(
self.get_cal_service().calendarList().list(
pageToken=pageToken)
)

self.all_cals.extend(cal_list['items'])
page_token = cal_list.get('nextPageToken')
if page_token:
cal_list = self._retry_with_backoff(
self.get_cal_service().calendarList().list(
pageToken=page_token
)
)
else:
if not page_token:
break

self.all_cals.sort(key=lambda x: x['accessRole'])
Expand Down Expand Up @@ -1025,15 +1021,20 @@ def _iterate_events(self, start_datetime, event_list, year_date=False,

return selected

def _GetAllEvents(self, cal, events, end):

event_list = []

while 1:
if 'items' not in events:
break

for event in events['items']:
def _GetAllEvents(self, cal, start, end, search_text) -> Iterable[Event]:
pageToken = None
while True:
events = self._retry_with_backoff(
self.get_events()
.list(
calendarId=cal['id'],
timeMin=start.isoformat() if start else None,
timeMax=end.isoformat() if end else None,
q=search_text if search_text else None,
singleEvents=True,
pageToken=pageToken)
)
for event in events.get('items', []):

event['gcalcli_cal'] = cal

Expand Down Expand Up @@ -1070,40 +1071,18 @@ def _GetAllEvents(self, cal, events, end):
if event['s'].year >= 2038 or event['e'].year >= 2038:
continue

event_list.append(event)
yield event

pageToken = events.get('nextPageToken')
if pageToken:
events = self._retry_with_backoff(
self.get_events()
.list(
calendarId=cal['id'],
pageToken=pageToken
)
)
else:
if not pageToken:
break

return event_list

def _search_for_events(self, start, end, search_text):

event_list = []
for cal in self.cals:
events = self._retry_with_backoff(
self.get_events()
.list(
calendarId=cal['id'],
timeMin=start.isoformat() if start else None,
timeMax=end.isoformat() if end else None,
q=search_text if search_text else None,
singleEvents=True
)
)
event_list.extend(self._GetAllEvents(cal, events, end))

event_list.extend(
self._GetAllEvents(cal, start, end, search_text=search_text))
event_list.sort(key=lambda x: x['s'])

return event_list

def _DeclinedEvent(self, event):
Expand Down

0 comments on commit 56c4fb7

Please sign in to comment.