1 | |
2 |
|
3 | export type DynSelect_calendar = string |
4 |
|
5 | export async function calendar(auth: RT.MsOutlook) { |
6 | const r = await fetch( |
7 | "https://graph.microsoft.com/v1.0/me/calendars?$top=100&$select=id,name", |
8 | { |
9 | headers: { |
10 | Authorization: `Bearer ${auth.token}`, |
11 | Accept: "application/json", |
12 | }, |
13 | } |
14 | ) |
15 | if (!r.ok) throw new Error(`${r.status} ${await r.text()}`) |
16 | const { value } = (await r.json()) as { |
17 | value: { id: string; name: string }[] |
18 | } |
19 | return value.map((c) => ({ value: c.id, label: c.name })) |
20 | } |
21 |
|
22 | |
23 | * List Events |
24 | * List events from the default calendar or a chosen one. With both `start_date_time` and `end_date_time` (ISO 8601, e.g. `2026-01-01T00:00:00Z`) it returns every occurrence in that window, recurring ones expanded; without them it returns single events and series masters. `filter` takes OData (e.g. `contains(subject,'standup')`). Pass the returned `@odata.nextLink` as `next_link` for the next page. Requires Calendars.Read (covered by the default Calendars.ReadWrite). |
25 | */ |
26 | export async function main( |
27 | auth: RT.MsOutlook, |
28 | start_date_time: string | undefined, |
29 | end_date_time: string | undefined, |
30 | calendar: DynSelect_calendar | undefined, |
31 | filter: string | undefined, |
32 | order_by: string | undefined, |
33 | select: string | undefined, |
34 | top: number = 25, |
35 | next_link: string | undefined, |
36 | time_zone: string = "UTC" |
37 | ) { |
38 | const base = `https://graph.microsoft.com/v1.0/me${ |
39 | calendar != null && calendar !== "" |
40 | ? `/calendars/${encodeURIComponent(calendar)}` |
41 | : "" |
42 | }` |
43 | if ( |
44 | next_link != null && |
45 | next_link !== "" && |
46 | !next_link.startsWith("https://graph.microsoft.com/") |
47 | ) { |
48 | throw new Error( |
49 | "next_link must be an @odata.nextLink returned by Microsoft Graph" |
50 | ) |
51 | } |
52 | let url: URL |
53 | if (next_link != null && next_link !== "") { |
54 | url = new URL(next_link) |
55 | } else { |
56 | const windowed = |
57 | start_date_time != null && |
58 | start_date_time !== "" && |
59 | end_date_time != null && |
60 | end_date_time !== "" |
61 | url = new URL(`${base}/${windowed ? "calendarView" : "events"}`) |
62 | if (windowed) { |
63 | url.searchParams.append("startDateTime", start_date_time!) |
64 | url.searchParams.append("endDateTime", end_date_time!) |
65 | } |
66 | url.searchParams.append("$top", String(top)) |
67 | if (filter != null && filter !== "") { |
68 | url.searchParams.append("$filter", filter) |
69 | } |
70 | if (order_by != null && order_by !== "") { |
71 | url.searchParams.append("$orderby", order_by) |
72 | } |
73 | if (select != null && select !== "") { |
74 | url.searchParams.append("$select", select) |
75 | } |
76 | } |
77 |
|
78 | const response = await fetch(url, { |
79 | headers: { |
80 | Authorization: `Bearer ${auth.token}`, |
81 | Accept: "application/json", |
82 | Prefer: `outlook.timezone="${time_zone}"`, |
83 | }, |
84 | }) |
85 |
|
86 | if (!response.ok) { |
87 | throw new Error(`${response.status} ${await response.text()}`) |
88 | } |
89 |
|
90 | return await response.json() |
91 | } |
92 |
|