Summary
gws calendar +agenda says that it shows events across all calendars, but it can silently omit calendars and events.
At commit a3768d0e82ad83cca2da97724e46bea4ff0e6dbd:
- The helper reads only the first
calendarList page and ignores nextPageToken:
|
// 1. List all calendars |
|
let list_url = "https://www.googleapis.com/calendar/v3/users/me/calendarList"; |
|
let list_resp = client |
|
.get(list_url) |
|
.bearer_auth(&token) |
|
.send() |
|
.await |
|
.map_err(|e| GwsError::Other(anyhow::anyhow!("Failed to list calendars: {e}")))?; |
|
|
|
if !list_resp.status().is_success() { |
|
let err = list_resp.text().await.unwrap_or_default(); |
|
return Err(GwsError::Api { |
|
code: 0, |
|
message: err, |
|
reason: "calendarList_failed".to_string(), |
|
enable_url: None, |
|
}); |
|
} |
|
|
|
let list_json: Value = list_resp |
|
.json() |
|
.await |
|
.map_err(|e| GwsError::Other(anyhow::anyhow!("Failed to parse calendar list: {e}")))?; |
|
|
|
let calendars = list_json |
|
.get("items") |
|
.and_then(|i| i.as_array()) |
|
.cloned() |
|
.unwrap_or_default(); |
- Each calendar request hard-codes
maxResults=50 and ignores the event nextPageToken:
|
let mut all_events: Vec<Value> = stream::iter(filtered_calendars) |
|
.map(|cal| { |
|
let client = &client; |
|
let token = &token; |
|
let time_min = &time_min; |
|
let time_max = &time_max; |
|
async move { |
|
let events_url = format!( |
|
"https://www.googleapis.com/calendar/v3/calendars/{}/events", |
|
crate::validate::encode_path_segment(&cal.id), |
|
); |
|
|
|
let resp = crate::client::send_with_retry(|| { |
|
client |
|
.get(&events_url) |
|
.query(&[ |
|
("timeMin", time_min.as_str()), |
|
("timeMax", time_max.as_str()), |
|
("singleEvents", "true"), |
|
("orderBy", "startTime"), |
|
("maxResults", "50"), |
|
]) |
|
.bearer_auth(token) |
|
}) |
|
.await; |
|
|
|
let resp = match resp { |
|
Ok(r) if r.status().is_success() => r, |
|
_ => return vec![], |
|
}; |
|
|
|
let events_json: Value = match resp.json().await { |
|
Ok(v) => v, |
|
Err(_) => return vec![], |
|
}; |
|
|
|
let mut events = Vec::new(); |
|
if let Some(items) = events_json.get("items").and_then(|i| i.as_array()) { |
- A request error, non-success response, or JSON decode error is converted to an empty event list:
|
let resp = crate::client::send_with_retry(|| { |
|
client |
|
.get(&events_url) |
|
.query(&[ |
|
("timeMin", time_min.as_str()), |
|
("timeMax", time_max.as_str()), |
|
("singleEvents", "true"), |
|
("orderBy", "startTime"), |
|
("maxResults", "50"), |
|
]) |
|
.bearer_auth(token) |
|
}) |
|
.await; |
|
|
|
let resp = match resp { |
|
Ok(r) if r.status().is_success() => r, |
|
_ => return vec![], |
|
}; |
|
|
|
let events_json: Value = match resp.json().await { |
|
Ok(v) => v, |
|
Err(_) => return vec![], |
|
}; |
This makes a partial result indistinguishable from a complete agenda with no events.
Reproduction
- Put more than 50 matching events in one calendar within the requested range.
- Run
gws calendar +agenda for that range.
- The output contains at most 50 events from that calendar and reports no truncation.
A provider error for one secondary calendar also produces a successful result that omits that calendar.
Expected behavior
- Follow
nextPageToken for calendarList.list and every events.list request until it is absent.
- Do not convert per-calendar failures into empty calendars. Return an error, or return an explicit partial-result status with the failed calendar and cause.
- If the command has an intentional caller limit, expose the limit and report that the result is truncated.
Summary
gws calendar +agendasays that it shows events across all calendars, but it can silently omit calendars and events.At commit
a3768d0e82ad83cca2da97724e46bea4ff0e6dbd:calendarListpage and ignoresnextPageToken:cli/crates/google-workspace-cli/src/helpers/calendar.rs
Lines 261 to 289 in a3768d0
maxResults=50and ignores the eventnextPageToken:cli/crates/google-workspace-cli/src/helpers/calendar.rs
Lines 322 to 359 in a3768d0
cli/crates/google-workspace-cli/src/helpers/calendar.rs
Lines 334 to 356 in a3768d0
This makes a partial result indistinguishable from a complete agenda with no events.
Reproduction
gws calendar +agendafor that range.A provider error for one secondary calendar also produces a successful result that omits that calendar.
Expected behavior
nextPageTokenforcalendarList.listand everyevents.listrequest until it is absent.