universal-mcp-applications 0.1.33__py3-none-any.whl → 0.1.39rc16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of universal-mcp-applications might be problematic. Click here for more details.
- universal_mcp/applications/BEST_PRACTICES.md +1 -1
- universal_mcp/applications/ahrefs/app.py +92 -238
- universal_mcp/applications/airtable/app.py +36 -135
- universal_mcp/applications/apollo/app.py +124 -477
- universal_mcp/applications/asana/app.py +605 -1755
- universal_mcp/applications/aws_s3/app.py +63 -119
- universal_mcp/applications/bill/app.py +644 -2055
- universal_mcp/applications/box/app.py +1246 -4159
- universal_mcp/applications/braze/app.py +410 -1476
- universal_mcp/applications/browser_use/README.md +15 -1
- universal_mcp/applications/browser_use/__init__.py +1 -0
- universal_mcp/applications/browser_use/app.py +91 -26
- universal_mcp/applications/cal_com_v2/app.py +207 -625
- universal_mcp/applications/calendly/app.py +103 -242
- universal_mcp/applications/canva/app.py +75 -140
- universal_mcp/applications/clickup/app.py +331 -798
- universal_mcp/applications/coda/app.py +240 -520
- universal_mcp/applications/confluence/app.py +497 -1285
- universal_mcp/applications/contentful/app.py +40 -155
- universal_mcp/applications/crustdata/app.py +44 -123
- universal_mcp/applications/dialpad/app.py +451 -924
- universal_mcp/applications/digitalocean/app.py +2071 -6082
- universal_mcp/applications/domain_checker/app.py +3 -54
- universal_mcp/applications/e2b/app.py +17 -68
- universal_mcp/applications/elevenlabs/README.md +27 -3
- universal_mcp/applications/elevenlabs/app.py +741 -74
- universal_mcp/applications/exa/README.md +8 -4
- universal_mcp/applications/exa/app.py +415 -186
- universal_mcp/applications/falai/README.md +5 -7
- universal_mcp/applications/falai/app.py +156 -232
- universal_mcp/applications/figma/app.py +91 -175
- universal_mcp/applications/file_system/app.py +2 -13
- universal_mcp/applications/firecrawl/app.py +198 -176
- universal_mcp/applications/fireflies/app.py +59 -281
- universal_mcp/applications/fpl/app.py +92 -529
- universal_mcp/applications/fpl/utils/fixtures.py +15 -49
- universal_mcp/applications/fpl/utils/helper.py +25 -89
- universal_mcp/applications/fpl/utils/league_utils.py +20 -64
- universal_mcp/applications/ghost_content/app.py +70 -179
- universal_mcp/applications/github/app.py +30 -67
- universal_mcp/applications/gong/app.py +142 -302
- universal_mcp/applications/google_calendar/app.py +26 -78
- universal_mcp/applications/google_docs/README.md +15 -14
- universal_mcp/applications/google_docs/app.py +103 -206
- universal_mcp/applications/google_drive/app.py +194 -793
- universal_mcp/applications/google_gemini/app.py +68 -59
- universal_mcp/applications/google_mail/README.md +1 -0
- universal_mcp/applications/google_mail/app.py +93 -214
- universal_mcp/applications/google_searchconsole/app.py +25 -58
- universal_mcp/applications/google_sheet/README.md +2 -1
- universal_mcp/applications/google_sheet/app.py +226 -624
- universal_mcp/applications/google_sheet/helper.py +26 -53
- universal_mcp/applications/hashnode/app.py +57 -269
- universal_mcp/applications/heygen/README.md +10 -32
- universal_mcp/applications/heygen/app.py +339 -811
- universal_mcp/applications/http_tools/app.py +10 -32
- universal_mcp/applications/hubspot/README.md +1 -1
- universal_mcp/applications/hubspot/app.py +7508 -99
- universal_mcp/applications/jira/app.py +2419 -8334
- universal_mcp/applications/klaviyo/app.py +739 -1621
- universal_mcp/applications/linkedin/README.md +18 -1
- universal_mcp/applications/linkedin/app.py +729 -251
- universal_mcp/applications/mailchimp/app.py +696 -1851
- universal_mcp/applications/markitdown/app.py +8 -20
- universal_mcp/applications/miro/app.py +333 -815
- universal_mcp/applications/ms_teams/app.py +420 -1407
- universal_mcp/applications/neon/app.py +144 -250
- universal_mcp/applications/notion/app.py +38 -53
- universal_mcp/applications/onedrive/app.py +26 -48
- universal_mcp/applications/openai/app.py +43 -166
- universal_mcp/applications/outlook/README.md +22 -9
- universal_mcp/applications/outlook/app.py +403 -141
- universal_mcp/applications/perplexity/README.md +2 -1
- universal_mcp/applications/perplexity/app.py +161 -20
- universal_mcp/applications/pipedrive/app.py +1021 -3331
- universal_mcp/applications/posthog/app.py +272 -541
- universal_mcp/applications/reddit/app.py +65 -164
- universal_mcp/applications/resend/app.py +72 -139
- universal_mcp/applications/retell/app.py +23 -50
- universal_mcp/applications/rocketlane/app.py +252 -965
- universal_mcp/applications/scraper/app.py +114 -142
- universal_mcp/applications/semanticscholar/app.py +36 -78
- universal_mcp/applications/semrush/app.py +44 -78
- universal_mcp/applications/sendgrid/app.py +826 -1576
- universal_mcp/applications/sentry/app.py +444 -1079
- universal_mcp/applications/serpapi/app.py +44 -146
- universal_mcp/applications/sharepoint/app.py +27 -49
- universal_mcp/applications/shopify/app.py +1748 -4486
- universal_mcp/applications/shortcut/app.py +275 -536
- universal_mcp/applications/slack/app.py +43 -125
- universal_mcp/applications/spotify/app.py +206 -405
- universal_mcp/applications/supabase/app.py +174 -283
- universal_mcp/applications/tavily/app.py +2 -2
- universal_mcp/applications/trello/app.py +853 -2816
- universal_mcp/applications/twilio/app.py +27 -62
- universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
- universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
- universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
- universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
- universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
- universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
- universal_mcp/applications/whatsapp/app.py +35 -186
- universal_mcp/applications/whatsapp/audio.py +2 -6
- universal_mcp/applications/whatsapp/whatsapp.py +17 -51
- universal_mcp/applications/whatsapp_business/app.py +86 -299
- universal_mcp/applications/wrike/app.py +80 -153
- universal_mcp/applications/yahoo_finance/app.py +19 -65
- universal_mcp/applications/youtube/app.py +120 -306
- universal_mcp/applications/zenquotes/app.py +3 -3
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/METADATA +4 -2
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/RECORD +115 -119
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/WHEEL +1 -1
- universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
- universal_mcp/applications/hubspot/api_segments/api_segment_base.py +0 -54
- universal_mcp/applications/hubspot/api_segments/crm_api.py +0 -7337
- universal_mcp/applications/hubspot/api_segments/marketing_api.py +0 -1467
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
from urllib.parse import parse_qs, urlparse
|
|
3
|
-
|
|
4
3
|
from universal_mcp.applications.application import APIApplication
|
|
5
4
|
from universal_mcp.integrations import Integration
|
|
6
5
|
|
|
@@ -10,12 +9,16 @@ class OutlookApp(APIApplication):
|
|
|
10
9
|
super().__init__(name="outlook", integration=integration, **kwargs)
|
|
11
10
|
self.base_url = "https://graph.microsoft.com/v1.0"
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
user_id:
|
|
18
|
-
|
|
12
|
+
async def _get_user_id(self) -> str:
|
|
13
|
+
"""Helper to get the userPrincipalName from the profile."""
|
|
14
|
+
user_info = await self.get_my_profile()
|
|
15
|
+
user_id = user_info.get("userPrincipalName")
|
|
16
|
+
if not user_id:
|
|
17
|
+
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
18
|
+
return user_id
|
|
19
|
+
|
|
20
|
+
async def reply_to_email(
|
|
21
|
+
self, message_id: str, comment: str, attachments: list[dict[str, Any]] | None = None
|
|
19
22
|
) -> dict[str, Any]:
|
|
20
23
|
"""
|
|
21
24
|
Replies to a specific email message.
|
|
@@ -23,7 +26,6 @@ class OutlookApp(APIApplication):
|
|
|
23
26
|
Args:
|
|
24
27
|
message_id (str): The ID of the email message to reply to.
|
|
25
28
|
comment (str): The body of the reply.
|
|
26
|
-
user_id (str, optional): The ID of the user to send the reply from. Defaults to the authenticated user.
|
|
27
29
|
attachments (list[dict[str, Any]], optional): A list of attachment objects to include in the reply.
|
|
28
30
|
Each attachment dictionary should conform to the Microsoft Graph API specification.
|
|
29
31
|
Example:
|
|
@@ -41,39 +43,26 @@ class OutlookApp(APIApplication):
|
|
|
41
43
|
|
|
42
44
|
Raises:
|
|
43
45
|
HTTPStatusError: If the API request fails.
|
|
44
|
-
ValueError: If
|
|
46
|
+
ValueError: If message_id is missing.
|
|
45
47
|
|
|
46
48
|
Tags:
|
|
47
49
|
important
|
|
48
50
|
"""
|
|
49
|
-
|
|
50
|
-
user_info = self.get_my_profile()
|
|
51
|
-
user_id = user_info.get("userPrincipalName")
|
|
52
|
-
if not user_id:
|
|
53
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
51
|
+
user_id = await self._get_user_id()
|
|
54
52
|
if not message_id:
|
|
55
53
|
raise ValueError("Missing required parameter 'message_id'.")
|
|
56
|
-
|
|
57
54
|
request_body_data = {"comment": comment}
|
|
58
55
|
if attachments:
|
|
59
56
|
request_body_data["message"] = {"attachments": attachments}
|
|
60
|
-
|
|
61
57
|
url = f"{self.base_url}/users/{user_id}/messages/{message_id}/reply"
|
|
62
|
-
|
|
63
|
-
response = self._post(
|
|
64
|
-
url,
|
|
65
|
-
data=request_body_data,
|
|
66
|
-
params={},
|
|
67
|
-
content_type="application/json",
|
|
68
|
-
)
|
|
58
|
+
response = await self._apost(url, data=request_body_data, params={}, content_type="application/json")
|
|
69
59
|
return self._handle_response(response)
|
|
70
60
|
|
|
71
|
-
def send_email(
|
|
61
|
+
async def send_email(
|
|
72
62
|
self,
|
|
73
63
|
subject: str,
|
|
74
64
|
body: str,
|
|
75
65
|
to_recipients: list[str],
|
|
76
|
-
user_id: str | None = None,
|
|
77
66
|
cc_recipients: list[str] | None = None,
|
|
78
67
|
bcc_recipients: list[str] | None = None,
|
|
79
68
|
attachments: list[dict[str, Any]] | None = None,
|
|
@@ -87,7 +76,6 @@ class OutlookApp(APIApplication):
|
|
|
87
76
|
subject (str): The subject of the email.
|
|
88
77
|
body (str): The body of the email.
|
|
89
78
|
to_recipients (list[str]): A list of email addresses for the 'To' recipients.
|
|
90
|
-
user_id (str, optional): The ID of the user to send the email from. Defaults to the authenticated user.
|
|
91
79
|
cc_recipients (list[str], optional): A list of email addresses for the 'Cc' recipients.
|
|
92
80
|
bcc_recipients (list[str], optional): A list of email addresses for the 'Bcc' recipients.
|
|
93
81
|
attachments (list[dict[str, Any]], optional): A list of attachment objects. See `reply_to_email` for an example.
|
|
@@ -99,17 +87,11 @@ class OutlookApp(APIApplication):
|
|
|
99
87
|
|
|
100
88
|
Raises:
|
|
101
89
|
HTTPStatusError: If the API request fails.
|
|
102
|
-
ValueError: If the user_id cannot be retrieved.
|
|
103
90
|
|
|
104
91
|
Tags:
|
|
105
92
|
important
|
|
106
93
|
"""
|
|
107
|
-
|
|
108
|
-
user_info = self.get_my_profile()
|
|
109
|
-
user_id = user_info.get("userPrincipalName")
|
|
110
|
-
if not user_id:
|
|
111
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
112
|
-
|
|
94
|
+
user_id = await self._get_user_id()
|
|
113
95
|
message = {
|
|
114
96
|
"subject": subject,
|
|
115
97
|
"body": {"contentType": body_content_type, "content": body},
|
|
@@ -121,26 +103,14 @@ class OutlookApp(APIApplication):
|
|
|
121
103
|
message["bccRecipients"] = [{"emailAddress": {"address": email}} for email in bcc_recipients]
|
|
122
104
|
if attachments:
|
|
123
105
|
message["attachments"] = attachments
|
|
124
|
-
|
|
125
|
-
request_body_data = {
|
|
126
|
-
"message": message,
|
|
127
|
-
"saveToSentItems": save_to_sent_items,
|
|
128
|
-
}
|
|
129
|
-
|
|
106
|
+
request_body_data = {"message": message, "saveToSentItems": save_to_sent_items}
|
|
130
107
|
url = f"{self.base_url}/users/{user_id}/sendMail"
|
|
131
|
-
|
|
132
|
-
response = self._post(
|
|
133
|
-
url,
|
|
134
|
-
data=request_body_data,
|
|
135
|
-
params={},
|
|
136
|
-
content_type="application/json",
|
|
137
|
-
)
|
|
108
|
+
response = await self._apost(url, data=request_body_data, params={}, content_type="application/json")
|
|
138
109
|
return self._handle_response(response)
|
|
139
110
|
|
|
140
|
-
def get_email_folder(
|
|
111
|
+
async def get_email_folder(
|
|
141
112
|
self,
|
|
142
113
|
folder_id: str,
|
|
143
|
-
user_id: str | None = None,
|
|
144
114
|
include_hidden: bool | None = None,
|
|
145
115
|
select: list[str] | None = None,
|
|
146
116
|
expand: list[str] | None = None,
|
|
@@ -150,7 +120,6 @@ class OutlookApp(APIApplication):
|
|
|
150
120
|
|
|
151
121
|
Args:
|
|
152
122
|
folder_id (str): The unique identifier for the mail folder.
|
|
153
|
-
user_id (str, optional): The ID of the user who owns the folder. Defaults to the authenticated user.
|
|
154
123
|
include_hidden (bool, optional): If true, includes hidden folders in the results.
|
|
155
124
|
select (list[str], optional): A list of properties to return.
|
|
156
125
|
expand (list[str], optional): A list of related entities to expand.
|
|
@@ -160,37 +129,24 @@ class OutlookApp(APIApplication):
|
|
|
160
129
|
|
|
161
130
|
Raises:
|
|
162
131
|
HTTPStatusError: If the API request fails.
|
|
163
|
-
ValueError: If
|
|
132
|
+
ValueError: If folder_id is missing.
|
|
164
133
|
Tags:
|
|
165
134
|
important
|
|
166
135
|
"""
|
|
167
|
-
|
|
168
|
-
user_info = self.get_my_profile()
|
|
169
|
-
user_id = user_info.get("userPrincipalName")
|
|
170
|
-
if not user_id:
|
|
171
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
136
|
+
user_id = await self._get_user_id()
|
|
172
137
|
if not folder_id:
|
|
173
138
|
raise ValueError("Missing required parameter 'folder_id'.")
|
|
174
|
-
|
|
175
139
|
url = f"{self.base_url}/users/{user_id}/mailFolders/{folder_id}"
|
|
176
140
|
select_str = ",".join(select) if select else None
|
|
177
141
|
expand_str = ",".join(expand) if expand else None
|
|
178
|
-
|
|
179
142
|
query_params = {
|
|
180
|
-
k: v
|
|
181
|
-
for k, v in [
|
|
182
|
-
("includeHiddenFolders", include_hidden),
|
|
183
|
-
("$select", select_str),
|
|
184
|
-
("$expand", expand_str),
|
|
185
|
-
]
|
|
186
|
-
if v is not None
|
|
143
|
+
k: v for k, v in [("includeHiddenFolders", include_hidden), ("$select", select_str), ("$expand", expand_str)] if v is not None
|
|
187
144
|
}
|
|
188
|
-
response = self.
|
|
145
|
+
response = await self._aget(url, params=query_params)
|
|
189
146
|
return self._handle_response(response)
|
|
190
147
|
|
|
191
|
-
def list_emails(
|
|
148
|
+
async def list_emails(
|
|
192
149
|
self,
|
|
193
|
-
user_id: str | None = None,
|
|
194
150
|
select: list[str] = ["bodyPreview"],
|
|
195
151
|
include_hidden: bool | None = None,
|
|
196
152
|
top: int | None = None,
|
|
@@ -205,7 +161,6 @@ class OutlookApp(APIApplication):
|
|
|
205
161
|
Retrieves a list of emails from a user's mailbox.
|
|
206
162
|
|
|
207
163
|
Args:
|
|
208
|
-
user_id (str, optional): The ID of the user. Defaults to the authenticated user.
|
|
209
164
|
select (list[str], optional): A list of properties to return for each email. Defaults to ['bodyPreview'].
|
|
210
165
|
include_hidden (bool, optional): If true, includes hidden messages.
|
|
211
166
|
top (int, optional): The maximum number of emails to return.
|
|
@@ -232,18 +187,11 @@ class OutlookApp(APIApplication):
|
|
|
232
187
|
raise ValueError("The 'search' parameter cannot be used with 'orderby'.")
|
|
233
188
|
if skip:
|
|
234
189
|
raise ValueError("The 'search' parameter cannot be used with 'skip'. Use pagination via @odata.nextLink instead.")
|
|
235
|
-
|
|
236
|
-
if user_id is None:
|
|
237
|
-
user_info = self.get_my_profile()
|
|
238
|
-
user_id = user_info.get("userPrincipalName")
|
|
239
|
-
if not user_id:
|
|
240
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
241
|
-
|
|
190
|
+
user_id = await self._get_user_id()
|
|
242
191
|
url = f"{self.base_url}/users/{user_id}/messages"
|
|
243
192
|
select_str = ",".join(select) if select else None
|
|
244
193
|
orderby_str = ",".join(orderby) if orderby else None
|
|
245
194
|
expand_str = ",".join(expand) if expand else None
|
|
246
|
-
|
|
247
195
|
query_params = {
|
|
248
196
|
k: v
|
|
249
197
|
for k, v in [
|
|
@@ -259,14 +207,12 @@ class OutlookApp(APIApplication):
|
|
|
259
207
|
]
|
|
260
208
|
if v is not None
|
|
261
209
|
}
|
|
262
|
-
|
|
263
|
-
response = self._get(url, params=query_params)
|
|
210
|
+
response = await self._aget(url, params=query_params)
|
|
264
211
|
return self._handle_response(response)
|
|
265
212
|
|
|
266
|
-
def get_email(
|
|
213
|
+
async def get_email(
|
|
267
214
|
self,
|
|
268
215
|
message_id: str,
|
|
269
|
-
user_id: str | None = None,
|
|
270
216
|
include_hidden: bool | None = None,
|
|
271
217
|
select: list[str] | None = None,
|
|
272
218
|
expand: list[str] | None = None,
|
|
@@ -276,7 +222,6 @@ class OutlookApp(APIApplication):
|
|
|
276
222
|
|
|
277
223
|
Args:
|
|
278
224
|
message_id (str): The unique identifier for the email.
|
|
279
|
-
user_id (str, optional): The ID of the user who owns the email. Defaults to the authenticated user.
|
|
280
225
|
include_hidden (bool, optional): If true, includes hidden messages.
|
|
281
226
|
select (list[str], optional): A list of properties to return.
|
|
282
227
|
expand (list[str], optional): A list of related entities to expand.
|
|
@@ -290,63 +235,44 @@ class OutlookApp(APIApplication):
|
|
|
290
235
|
Tags:
|
|
291
236
|
important
|
|
292
237
|
"""
|
|
293
|
-
|
|
294
|
-
user_info = self.get_my_profile()
|
|
295
|
-
user_id = user_info.get("userPrincipalName")
|
|
296
|
-
if not user_id:
|
|
297
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
238
|
+
user_id = await self._get_user_id()
|
|
298
239
|
if not message_id:
|
|
299
240
|
raise ValueError("Missing required parameter 'message_id'.")
|
|
300
|
-
|
|
301
241
|
url = f"{self.base_url}/users/{user_id}/messages/{message_id}"
|
|
302
242
|
select_str = ",".join(select) if select else None
|
|
303
243
|
expand_str = ",".join(expand) if expand else None
|
|
304
|
-
|
|
305
244
|
query_params = {
|
|
306
|
-
k: v
|
|
307
|
-
for k, v in [
|
|
308
|
-
("includeHiddenMessages", include_hidden),
|
|
309
|
-
("$select", select_str),
|
|
310
|
-
("$expand", expand_str),
|
|
311
|
-
]
|
|
312
|
-
if v is not None
|
|
245
|
+
k: v for k, v in [("includeHiddenMessages", include_hidden), ("$select", select_str), ("$expand", expand_str)] if v is not None
|
|
313
246
|
}
|
|
314
|
-
response = self.
|
|
247
|
+
response = await self._aget(url, params=query_params)
|
|
315
248
|
return self._handle_response(response)
|
|
316
249
|
|
|
317
|
-
def delete_email(self, message_id: str
|
|
250
|
+
async def delete_email(self, message_id: str) -> dict[str, Any]:
|
|
318
251
|
"""
|
|
319
252
|
Permanently deletes a specific email by its ID.
|
|
320
253
|
|
|
321
254
|
Args:
|
|
322
255
|
message_id (str): The unique identifier for the email to be deleted.
|
|
323
|
-
user_id (str, optional): The ID of the user who owns the email. Defaults to the authenticated user.
|
|
324
256
|
|
|
325
257
|
Returns:
|
|
326
258
|
dict[str, Any]: A dictionary confirming the deletion.
|
|
327
259
|
|
|
328
260
|
Raises:
|
|
329
261
|
HTTPStatusError: If the API request fails.
|
|
330
|
-
ValueError: If
|
|
262
|
+
ValueError: If message_id is missing.
|
|
331
263
|
Tags:
|
|
332
264
|
important
|
|
333
265
|
"""
|
|
334
|
-
|
|
335
|
-
user_info = self.get_my_profile()
|
|
336
|
-
user_id = user_info.get("userPrincipalName")
|
|
337
|
-
if not user_id:
|
|
338
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
266
|
+
user_id = await self._get_user_id()
|
|
339
267
|
if not message_id:
|
|
340
268
|
raise ValueError("Missing required parameter 'message_id'.")
|
|
341
|
-
|
|
342
269
|
url = f"{self.base_url}/users/{user_id}/messages/{message_id}"
|
|
343
|
-
response = self.
|
|
270
|
+
response = await self._adelete(url, params={})
|
|
344
271
|
return self._handle_response(response)
|
|
345
272
|
|
|
346
|
-
def list_email_attachments(
|
|
273
|
+
async def list_email_attachments(
|
|
347
274
|
self,
|
|
348
275
|
message_id: str,
|
|
349
|
-
user_id: str | None = None,
|
|
350
276
|
top: int | None = None,
|
|
351
277
|
skip: int | None = None,
|
|
352
278
|
search: str | None = None,
|
|
@@ -361,7 +287,6 @@ class OutlookApp(APIApplication):
|
|
|
361
287
|
|
|
362
288
|
Args:
|
|
363
289
|
message_id (str): The unique identifier for the email.
|
|
364
|
-
user_id (str, optional): The ID of the user who owns the email. Defaults to the authenticated user.
|
|
365
290
|
top (int, optional): The maximum number of attachments to return.
|
|
366
291
|
skip (int, optional): The number of attachments to skip. Cannot be used with 'search'.
|
|
367
292
|
search (str, optional): A search query. Cannot be used with 'filter', 'orderby', or 'skip'.
|
|
@@ -387,20 +312,13 @@ class OutlookApp(APIApplication):
|
|
|
387
312
|
raise ValueError("The 'search' parameter cannot be used with 'orderby'.")
|
|
388
313
|
if skip:
|
|
389
314
|
raise ValueError("The 'search' parameter cannot be used with 'skip'. Use pagination via @odata.nextLink instead.")
|
|
390
|
-
|
|
391
|
-
if user_id is None:
|
|
392
|
-
user_info = self.get_my_profile()
|
|
393
|
-
user_id = user_info.get("userPrincipalName")
|
|
394
|
-
if not user_id:
|
|
395
|
-
raise ValueError("Could not retrieve user ID from get_my_profile response.")
|
|
315
|
+
user_id = await self._get_user_id()
|
|
396
316
|
if not message_id:
|
|
397
317
|
raise ValueError("Missing required parameter 'message_id'.")
|
|
398
|
-
|
|
399
318
|
url = f"{self.base_url}/users/{user_id}/messages/{message_id}/attachments"
|
|
400
319
|
orderby_str = ",".join(orderby) if orderby else None
|
|
401
320
|
select_str = ",".join(select) if select else None
|
|
402
321
|
expand_str = ",".join(expand) if expand else None
|
|
403
|
-
|
|
404
322
|
query_params = {
|
|
405
323
|
k: v
|
|
406
324
|
for k, v in [
|
|
@@ -415,22 +333,16 @@ class OutlookApp(APIApplication):
|
|
|
415
333
|
]
|
|
416
334
|
if v is not None
|
|
417
335
|
}
|
|
418
|
-
response = self.
|
|
336
|
+
response = await self._aget(url, params=query_params)
|
|
419
337
|
return self._handle_response(response)
|
|
420
338
|
|
|
421
|
-
def get_attachment(
|
|
422
|
-
self,
|
|
423
|
-
message_id: str,
|
|
424
|
-
attachment_id: str,
|
|
425
|
-
user_id: str | None = None,
|
|
426
|
-
) -> dict[str, Any]:
|
|
339
|
+
async def get_attachment(self, message_id: str, attachment_id: str) -> dict[str, Any]:
|
|
427
340
|
"""
|
|
428
341
|
Retrieves a specific attachment from an email message and formats it as a dictionary.
|
|
429
342
|
|
|
430
343
|
Args:
|
|
431
344
|
message_id (str): The ID of the email message.
|
|
432
345
|
attachment_id (str): The ID of the attachment.
|
|
433
|
-
user_id (str, optional): The ID of the user. Defaults to the authenticated user.
|
|
434
346
|
|
|
435
347
|
Returns:
|
|
436
348
|
dict[str, Any]: A dictionary containing the attachment details:
|
|
@@ -441,24 +353,16 @@ class OutlookApp(APIApplication):
|
|
|
441
353
|
Tags:
|
|
442
354
|
important
|
|
443
355
|
"""
|
|
444
|
-
|
|
445
|
-
user_info = self.get_my_profile()
|
|
446
|
-
user_id = user_info.get("userPrincipalName")
|
|
447
|
-
if not user_id:
|
|
448
|
-
raise ValueError("Could not retrieve user ID.")
|
|
356
|
+
user_id = await self._get_user_id()
|
|
449
357
|
if not message_id or not attachment_id:
|
|
450
358
|
raise ValueError("Missing required parameter 'message_id' or 'attachment_id'.")
|
|
451
|
-
|
|
452
359
|
url = f"{self.base_url}/users/{user_id}/messages/{message_id}/attachments/{attachment_id}"
|
|
453
|
-
|
|
454
|
-
response = self._get(url, params={})
|
|
360
|
+
response = await self._aget(url, params={})
|
|
455
361
|
attachment_data = self._handle_response(response)
|
|
456
|
-
|
|
457
362
|
content_type = attachment_data.get("contentType", "application/octet-stream")
|
|
458
363
|
attachment_type = content_type.split("/")[0] if "/" in content_type else "file"
|
|
459
364
|
if attachment_type not in ["image", "audio", "video", "text"]:
|
|
460
365
|
attachment_type = "file"
|
|
461
|
-
|
|
462
366
|
return {
|
|
463
367
|
"type": attachment_type,
|
|
464
368
|
"data": attachment_data.get("contentBytes"),
|
|
@@ -466,7 +370,7 @@ class OutlookApp(APIApplication):
|
|
|
466
370
|
"file_name": attachment_data.get("name"),
|
|
467
371
|
}
|
|
468
372
|
|
|
469
|
-
def get_my_profile(self) -> dict[str, Any]:
|
|
373
|
+
async def get_my_profile(self) -> dict[str, Any]:
|
|
470
374
|
"""
|
|
471
375
|
Fetches the userPrincipalName for the currently authenticated user.
|
|
472
376
|
|
|
@@ -478,10 +382,358 @@ class OutlookApp(APIApplication):
|
|
|
478
382
|
"""
|
|
479
383
|
url = f"{self.base_url}/me"
|
|
480
384
|
query_params = {"$select": "userPrincipalName"}
|
|
481
|
-
response = self.
|
|
385
|
+
response = await self._aget(url, params=query_params)
|
|
482
386
|
return self._handle_response(response)
|
|
483
387
|
|
|
484
|
-
def
|
|
388
|
+
async def list_calendars(
|
|
389
|
+
self,
|
|
390
|
+
top: int | None = None,
|
|
391
|
+
skip: int | None = None,
|
|
392
|
+
select: list[str] | None = None,
|
|
393
|
+
) -> dict[str, Any]:
|
|
394
|
+
"""
|
|
395
|
+
Retrieves a list of calendars for the user.
|
|
396
|
+
|
|
397
|
+
Args:
|
|
398
|
+
top (int, optional): The maximum number of calendars to return.
|
|
399
|
+
skip (int, optional): The number of calendars to skip.
|
|
400
|
+
select (list[str], optional): A list of properties to return for each calendar.
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
dict[str, Any]: A dictionary containing a list of calendars.
|
|
404
|
+
|
|
405
|
+
Tags:
|
|
406
|
+
important
|
|
407
|
+
"""
|
|
408
|
+
user_id = await self._get_user_id()
|
|
409
|
+
url = f"{self.base_url}/users/{user_id}/calendars"
|
|
410
|
+
select_str = ",".join(select) if select else None
|
|
411
|
+
query_params = {k: v for k, v in [("$top", top), ("$skip", skip), ("$select", select_str)] if v is not None}
|
|
412
|
+
response = await self._aget(url, params=query_params)
|
|
413
|
+
return self._handle_response(response)
|
|
414
|
+
|
|
415
|
+
async def get_calendar(
|
|
416
|
+
self, calendar_id: str, select: list[str] | None = None
|
|
417
|
+
) -> dict[str, Any]:
|
|
418
|
+
"""
|
|
419
|
+
Retrieves a specific calendar by its ID.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
calendar_id (str): The unique identifier for the calendar.
|
|
423
|
+
select (list[str], optional): A list of properties to return.
|
|
424
|
+
|
|
425
|
+
Returns:
|
|
426
|
+
dict[str, Any]: A dictionary containing the calendar's details.
|
|
427
|
+
|
|
428
|
+
Tags:
|
|
429
|
+
important
|
|
430
|
+
"""
|
|
431
|
+
user_id = await self._get_user_id()
|
|
432
|
+
url = f"{self.base_url}/users/{user_id}/calendars/{calendar_id}"
|
|
433
|
+
select_str = ",".join(select) if select else None
|
|
434
|
+
query_params = {"$select": select_str} if select_str else {}
|
|
435
|
+
response = await self._aget(url, params=query_params)
|
|
436
|
+
return self._handle_response(response)
|
|
437
|
+
|
|
438
|
+
async def create_calendar(self, name: str) -> dict[str, Any]:
|
|
439
|
+
"""
|
|
440
|
+
Creates a new calendar for the user.
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
name (str): The name of the new calendar.
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
dict[str, Any]: A dictionary containing the created calendar's details.
|
|
447
|
+
|
|
448
|
+
Tags:
|
|
449
|
+
important
|
|
450
|
+
"""
|
|
451
|
+
user_id = await self._get_user_id()
|
|
452
|
+
url = f"{self.base_url}/users/{user_id}/calendars"
|
|
453
|
+
request_body = {"name": name}
|
|
454
|
+
response = await self._apost(url, data=request_body, params={}, content_type="application/json")
|
|
455
|
+
return self._handle_response(response)
|
|
456
|
+
|
|
457
|
+
async def update_calendar(self, calendar_id: str, name: str) -> dict[str, Any]:
|
|
458
|
+
"""
|
|
459
|
+
Updates an existing calendar's name.
|
|
460
|
+
|
|
461
|
+
Args:
|
|
462
|
+
calendar_id (str): The unique identifier for the calendar.
|
|
463
|
+
name (str): The new name for the calendar.
|
|
464
|
+
|
|
465
|
+
Returns:
|
|
466
|
+
dict[str, Any]: A dictionary containing the updated calendar's details.
|
|
467
|
+
|
|
468
|
+
Tags:
|
|
469
|
+
important
|
|
470
|
+
"""
|
|
471
|
+
user_id = await self._get_user_id()
|
|
472
|
+
url = f"{self.base_url}/users/{user_id}/calendars/{calendar_id}"
|
|
473
|
+
request_body = {"name": name}
|
|
474
|
+
response = await self._apatch(url, data=request_body, params={}, content_type="application/json")
|
|
475
|
+
return self._handle_response(response)
|
|
476
|
+
|
|
477
|
+
async def delete_calendar(self, calendar_id: str) -> dict[str, Any]:
|
|
478
|
+
"""
|
|
479
|
+
Deletes a specific calendar.
|
|
480
|
+
|
|
481
|
+
Args:
|
|
482
|
+
calendar_id (str): The unique identifier for the calendar to delete.
|
|
483
|
+
|
|
484
|
+
Returns:
|
|
485
|
+
dict[str, Any]: A dictionary confirming the deletion.
|
|
486
|
+
|
|
487
|
+
Tags:
|
|
488
|
+
important
|
|
489
|
+
"""
|
|
490
|
+
user_id = await self._get_user_id()
|
|
491
|
+
url = f"{self.base_url}/users/{user_id}/calendars/{calendar_id}"
|
|
492
|
+
response = await self._adelete(url, params={})
|
|
493
|
+
return self._handle_response(response)
|
|
494
|
+
|
|
495
|
+
async def list_events(
|
|
496
|
+
self,
|
|
497
|
+
calendar_id: str | None = None,
|
|
498
|
+
top: int | None = None,
|
|
499
|
+
skip: int | None = None,
|
|
500
|
+
filter: str | None = None,
|
|
501
|
+
select: list[str] | None = None,
|
|
502
|
+
orderby: list[str] | None = None,
|
|
503
|
+
) -> dict[str, Any]:
|
|
504
|
+
"""
|
|
505
|
+
Retrieves a list of events from a calendar or the user's default calendar.
|
|
506
|
+
|
|
507
|
+
Args:
|
|
508
|
+
calendar_id (str, optional): The ID of the calendar. If not provided, the default calendar is used.
|
|
509
|
+
top (int, optional): The maximum number of events to return.
|
|
510
|
+
skip (int, optional): The number of events to skip.
|
|
511
|
+
filter (str, optional): A filter query (e.g., "start/dateTime ge '2023-01-01T00:00:00Z'").
|
|
512
|
+
select (list[str], optional): A list of properties to return for each event.
|
|
513
|
+
orderby (list[str], optional): A list of properties to sort the results by.
|
|
514
|
+
|
|
515
|
+
Returns:
|
|
516
|
+
dict[str, Any]: A dictionary containing a list of events.
|
|
517
|
+
|
|
518
|
+
Tags:
|
|
519
|
+
important
|
|
520
|
+
"""
|
|
521
|
+
user_id = await self._get_user_id()
|
|
522
|
+
if calendar_id:
|
|
523
|
+
url = f"{self.base_url}/users/{user_id}/calendars/{calendar_id}/events"
|
|
524
|
+
else:
|
|
525
|
+
url = f"{self.base_url}/users/{user_id}/calendar/events"
|
|
526
|
+
select_str = ",".join(select) if select else None
|
|
527
|
+
orderby_str = ",".join(orderby) if orderby else None
|
|
528
|
+
query_params = {
|
|
529
|
+
k: v
|
|
530
|
+
for k, v in [("$top", top), ("$skip", skip), ("$filter", filter), ("$select", select_str), ("$orderby", orderby_str)]
|
|
531
|
+
if v is not None
|
|
532
|
+
}
|
|
533
|
+
response = await self._aget(url, params=query_params)
|
|
534
|
+
return self._handle_response(response)
|
|
535
|
+
|
|
536
|
+
async def get_event(
|
|
537
|
+
self, event_id: str, select: list[str] | None = None
|
|
538
|
+
) -> dict[str, Any]:
|
|
539
|
+
"""
|
|
540
|
+
Retrieves a specific event by its ID.
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
event_id (str): The unique identifier for the event.
|
|
544
|
+
select (list[str], optional): A list of properties to return.
|
|
545
|
+
|
|
546
|
+
Returns:
|
|
547
|
+
dict[str, Any]: A dictionary containing the event's details.
|
|
548
|
+
|
|
549
|
+
Tags:
|
|
550
|
+
important
|
|
551
|
+
"""
|
|
552
|
+
user_id = await self._get_user_id()
|
|
553
|
+
url = f"{self.base_url}/users/{user_id}/events/{event_id}"
|
|
554
|
+
select_str = ",".join(select) if select else None
|
|
555
|
+
query_params = {"$select": select_str} if select_str else {}
|
|
556
|
+
response = await self._aget(url, params=query_params)
|
|
557
|
+
return self._handle_response(response)
|
|
558
|
+
|
|
559
|
+
async def create_event(
|
|
560
|
+
self,
|
|
561
|
+
subject: str,
|
|
562
|
+
start_datetime: str,
|
|
563
|
+
end_datetime: str,
|
|
564
|
+
start_timezone: str = "UTC",
|
|
565
|
+
end_timezone: str = "UTC",
|
|
566
|
+
body: str | None = None,
|
|
567
|
+
body_content_type: str = "HTML",
|
|
568
|
+
location_display_name: str | None = None,
|
|
569
|
+
attendees: list[dict[str, Any]] | None = None,
|
|
570
|
+
calendar_id: str | None = None,
|
|
571
|
+
**kwargs,
|
|
572
|
+
) -> dict[str, Any]:
|
|
573
|
+
"""
|
|
574
|
+
Creates a new event in a calendar.
|
|
575
|
+
|
|
576
|
+
Args:
|
|
577
|
+
subject (str): The subject of the event.
|
|
578
|
+
start_datetime (str): The start time of the event (ISO 8601 string, e.g., '2023-12-25T09:00:00').
|
|
579
|
+
end_datetime (str): The end time of the event (ISO 8601 string, e.g., '2023-12-25T10:00:00').
|
|
580
|
+
start_timezone (str, optional): The timezone for the start time. Defaults to 'UTC'.
|
|
581
|
+
end_timezone (str, optional): The timezone for the end time. Defaults to 'UTC'.
|
|
582
|
+
body (str, optional): The body content of the event.
|
|
583
|
+
body_content_type (str, optional): The content type of the body (Text or HTML). Defaults to 'HTML'.
|
|
584
|
+
location_display_name (str, optional): The display name for the event location.
|
|
585
|
+
attendees (list[dict[str, Any]], optional): A list of attendee objects.
|
|
586
|
+
Example attendee: {"type": "required", "emailAddress": {"address": "bob@example.com", "name": "Bob"}}
|
|
587
|
+
calendar_id (str, optional): The ID of the calendar. If not provided, the default calendar is used.
|
|
588
|
+
**kwargs: Additional properties for the event (e.g., isOnlineMeeting, reminderMinutesBeforeStart).
|
|
589
|
+
|
|
590
|
+
Returns:
|
|
591
|
+
dict[str, Any]: A dictionary containing the created event's details.
|
|
592
|
+
|
|
593
|
+
Tags:
|
|
594
|
+
important
|
|
595
|
+
"""
|
|
596
|
+
user_id = await self._get_user_id()
|
|
597
|
+
if calendar_id:
|
|
598
|
+
url = f"{self.base_url}/users/{user_id}/calendars/{calendar_id}/events"
|
|
599
|
+
else:
|
|
600
|
+
url = f"{self.base_url}/users/{user_id}/calendar/events"
|
|
601
|
+
request_body = {
|
|
602
|
+
"subject": subject,
|
|
603
|
+
"start": {"dateTime": start_datetime, "timeZone": start_timezone},
|
|
604
|
+
"end": {"dateTime": end_datetime, "timeZone": end_timezone},
|
|
605
|
+
}
|
|
606
|
+
if body:
|
|
607
|
+
request_body["body"] = {"contentType": body_content_type, "content": body}
|
|
608
|
+
if location_display_name:
|
|
609
|
+
request_body["location"] = {"displayName": location_display_name}
|
|
610
|
+
if attendees:
|
|
611
|
+
request_body["attendees"] = attendees
|
|
612
|
+
request_body.update(kwargs)
|
|
613
|
+
response = await self._apost(url, data=request_body, params={}, content_type="application/json")
|
|
614
|
+
return self._handle_response(response)
|
|
615
|
+
|
|
616
|
+
async def update_event(
|
|
617
|
+
self,
|
|
618
|
+
event_id: str,
|
|
619
|
+
**kwargs,
|
|
620
|
+
) -> dict[str, Any]:
|
|
621
|
+
"""
|
|
622
|
+
Updates an existing event.
|
|
623
|
+
|
|
624
|
+
Args:
|
|
625
|
+
event_id (str): The unique identifier for the event.
|
|
626
|
+
**kwargs: Event properties to update (e.g., subject, start, end, body, attendees).
|
|
627
|
+
For start/end, use nested dictionaries: start={"dateTime": "...", "timeZone": "..."}.
|
|
628
|
+
|
|
629
|
+
Returns:
|
|
630
|
+
dict[str, Any]: A dictionary containing the updated event's details.
|
|
631
|
+
|
|
632
|
+
Tags:
|
|
633
|
+
important
|
|
634
|
+
"""
|
|
635
|
+
user_id = await self._get_user_id()
|
|
636
|
+
url = f"{self.base_url}/users/{user_id}/events/{event_id}"
|
|
637
|
+
response = await self._apatch(url, data=kwargs, params={}, content_type="application/json")
|
|
638
|
+
return self._handle_response(response)
|
|
639
|
+
|
|
640
|
+
async def delete_event(self, event_id: str) -> dict[str, Any]:
|
|
641
|
+
"""
|
|
642
|
+
Deletes a specific event.
|
|
643
|
+
|
|
644
|
+
Args:
|
|
645
|
+
event_id (str): The unique identifier for the event to delete.
|
|
646
|
+
|
|
647
|
+
Returns:
|
|
648
|
+
dict[str, Any]: A dictionary confirming the deletion.
|
|
649
|
+
|
|
650
|
+
Tags:
|
|
651
|
+
important
|
|
652
|
+
"""
|
|
653
|
+
user_id = await self._get_user_id()
|
|
654
|
+
url = f"{self.base_url}/users/{user_id}/events/{event_id}"
|
|
655
|
+
response = await self._adelete(url, params={})
|
|
656
|
+
return self._handle_response(response)
|
|
657
|
+
|
|
658
|
+
async def list_calendar_view(
|
|
659
|
+
self,
|
|
660
|
+
start_datetime: str,
|
|
661
|
+
end_datetime: str,
|
|
662
|
+
calendar_id: str | None = None,
|
|
663
|
+
top: int | None = None,
|
|
664
|
+
skip: int | None = None,
|
|
665
|
+
select: list[str] | None = None,
|
|
666
|
+
) -> dict[str, Any]:
|
|
667
|
+
"""
|
|
668
|
+
Retrieves events between a start and end time (includes expanded recurring events).
|
|
669
|
+
|
|
670
|
+
Args:
|
|
671
|
+
start_datetime (str): The start of the time range (ISO 8601, e.g., '2023-12-25T00:00:00Z').
|
|
672
|
+
end_datetime (str): The end of the time range (ISO 8601, e.g., '2023-12-26T00:00:00Z').
|
|
673
|
+
calendar_id (str, optional): The ID of the calendar. If not provided, the default calendar is used.
|
|
674
|
+
top (int, optional): The maximum number of events to return.
|
|
675
|
+
skip (int, optional): The number of events to skip.
|
|
676
|
+
select (list[str], optional): A list of properties to return for each event.
|
|
677
|
+
|
|
678
|
+
Returns:
|
|
679
|
+
dict[str, Any]: A dictionary containing a list of event instances.
|
|
680
|
+
|
|
681
|
+
Tags:
|
|
682
|
+
important
|
|
683
|
+
"""
|
|
684
|
+
user_id = await self._get_user_id()
|
|
685
|
+
if calendar_id:
|
|
686
|
+
url = f"{self.base_url}/users/{user_id}/calendars/{calendar_id}/calendarView"
|
|
687
|
+
else:
|
|
688
|
+
url = f"{self.base_url}/users/{user_id}/calendar/calendarView"
|
|
689
|
+
select_str = ",".join(select) if select else None
|
|
690
|
+
query_params = {
|
|
691
|
+
"startDateTime": start_datetime,
|
|
692
|
+
"endDateTime": end_datetime,
|
|
693
|
+
}
|
|
694
|
+
if top is not None:
|
|
695
|
+
query_params["$top"] = top
|
|
696
|
+
if skip is not None:
|
|
697
|
+
query_params["$skip"] = skip
|
|
698
|
+
if select_str:
|
|
699
|
+
query_params["$select"] = select_str
|
|
700
|
+
response = await self._aget(url, params=query_params)
|
|
701
|
+
return self._handle_response(response)
|
|
702
|
+
|
|
703
|
+
async def get_schedule(
|
|
704
|
+
self,
|
|
705
|
+
schedules: list[str],
|
|
706
|
+
start_datetime: str,
|
|
707
|
+
end_datetime: str,
|
|
708
|
+
availability_view_interval: int = 30,
|
|
709
|
+
) -> dict[str, Any]:
|
|
710
|
+
"""
|
|
711
|
+
Retrieves free/busy information for a set of users, groups, or resources.
|
|
712
|
+
|
|
713
|
+
Args:
|
|
714
|
+
schedules (list[str]): A list of SMTP addresses (emails) to get schedules for.
|
|
715
|
+
start_datetime (str): The start of the time range (ISO 8601 with 'Z', e.g., '2023-12-25T00:00:00Z').
|
|
716
|
+
end_datetime (str): The end of the time range (ISO 8601 with 'Z', e.g., '2023-12-26T00:00:00Z').
|
|
717
|
+
availability_view_interval (int, optional): The duration of each time slot in minutes. Defaults to 30.
|
|
718
|
+
|
|
719
|
+
Returns:
|
|
720
|
+
dict[str, Any]: A dictionary containing schedule information.
|
|
721
|
+
|
|
722
|
+
Tags:
|
|
723
|
+
important
|
|
724
|
+
"""
|
|
725
|
+
user_id = await self._get_user_id()
|
|
726
|
+
url = f"{self.base_url}/users/{user_id}/calendar/getSchedule"
|
|
727
|
+
request_body = {
|
|
728
|
+
"schedules": schedules,
|
|
729
|
+
"startTime": {"dateTime": start_datetime, "timeZone": "UTC"},
|
|
730
|
+
"endTime": {"dateTime": end_datetime, "timeZone": "UTC"},
|
|
731
|
+
"availabilityViewInterval": availability_view_interval,
|
|
732
|
+
}
|
|
733
|
+
response = await self._apost(url, data=request_body, params={}, content_type="application/json")
|
|
734
|
+
return self._handle_response(response)
|
|
735
|
+
|
|
736
|
+
async def get_next_page_results(self, url: str) -> dict[str, Any]:
|
|
485
737
|
"""
|
|
486
738
|
Retrieves the next page of results from a paginated API response.
|
|
487
739
|
|
|
@@ -500,13 +752,11 @@ class OutlookApp(APIApplication):
|
|
|
500
752
|
raise ValueError("Missing required parameter 'url'.")
|
|
501
753
|
if not url.startswith(self.base_url):
|
|
502
754
|
raise ValueError(f"The provided URL must start with '{self.base_url}'.")
|
|
503
|
-
|
|
504
755
|
relative_part = url[len(self.base_url) :]
|
|
505
756
|
parsed_relative = urlparse(relative_part)
|
|
506
757
|
path_only = parsed_relative.path
|
|
507
758
|
params = {k: v[0] for k, v in parse_qs(parsed_relative.query).items()}
|
|
508
|
-
|
|
509
|
-
response = self._get(path_only, params=params)
|
|
759
|
+
response = await self._aget(path_only, params=params)
|
|
510
760
|
return self._handle_response(response)
|
|
511
761
|
|
|
512
762
|
def list_tools(self):
|
|
@@ -521,4 +771,16 @@ class OutlookApp(APIApplication):
|
|
|
521
771
|
self.get_attachment,
|
|
522
772
|
self.get_my_profile,
|
|
523
773
|
self.get_next_page_results,
|
|
774
|
+
self.list_calendars,
|
|
775
|
+
self.get_calendar,
|
|
776
|
+
self.create_calendar,
|
|
777
|
+
self.update_calendar,
|
|
778
|
+
self.delete_calendar,
|
|
779
|
+
self.list_events,
|
|
780
|
+
self.get_event,
|
|
781
|
+
self.create_event,
|
|
782
|
+
self.update_event,
|
|
783
|
+
self.delete_event,
|
|
784
|
+
self.list_calendar_view,
|
|
785
|
+
self.get_schedule,
|
|
524
786
|
]
|