msgraph-mcp-server 0.3.0__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.
@@ -0,0 +1,351 @@
1
+ """Convert msgraph-sdk model objects into camelCase dicts.
2
+
3
+ The trimmers in graph.trimming consume dicts shaped like raw Graph JSON
4
+ (camelCase, nested objects). msgraph-sdk's deserialized models use
5
+ snake_case attrs and enum wrappers. These helpers bridge the two.
6
+
7
+ Pattern: each helper pulls the attrs we care about into a dict, then
8
+ merges with model.additional_data so include_raw=True returns whatever
9
+ Graph sent that the SDK didn't model.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import base64
15
+ from typing import Any
16
+
17
+
18
+ def _enum_value(x: Any) -> Any:
19
+ """Return .value if x looks like an enum-wrapper, else x."""
20
+ return getattr(x, "value", x)
21
+
22
+
23
+ def _additional(obj: Any) -> dict:
24
+ return getattr(obj, "additional_data", None) or {}
25
+
26
+
27
+ def user_to_dict(user: Any) -> dict:
28
+ base = {
29
+ "id": getattr(user, "id", None),
30
+ "displayName": getattr(user, "display_name", None),
31
+ "userPrincipalName": getattr(user, "user_principal_name", None),
32
+ "mail": getattr(user, "mail", None),
33
+ "jobTitle": getattr(user, "job_title", None),
34
+ }
35
+ return {**_additional(user), **base}
36
+
37
+
38
+ def email_address_to_dict(addr: Any) -> dict | None:
39
+ if addr is None:
40
+ return None
41
+ return {"name": getattr(addr, "name", None), "address": getattr(addr, "address", None)}
42
+
43
+
44
+ def recipient_to_dict(rec: Any) -> dict | None:
45
+ if rec is None:
46
+ return None
47
+ return {"emailAddress": email_address_to_dict(getattr(rec, "email_address", None))}
48
+
49
+
50
+ def _recipients(recs: list[Any] | None) -> list[dict]:
51
+ return [r for r in (recipient_to_dict(rec) for rec in (recs or [])) if r is not None]
52
+
53
+
54
+ def _body_to_dict(body: Any) -> dict | None:
55
+ if body is None:
56
+ return None
57
+ return {
58
+ "contentType": _enum_value(getattr(body, "content_type", None)),
59
+ "content": getattr(body, "content", None),
60
+ }
61
+
62
+
63
+ def _flag_to_dict(flag: Any) -> dict | None:
64
+ if flag is None:
65
+ return None
66
+ return {"flagStatus": _enum_value(getattr(flag, "flag_status", None))}
67
+
68
+
69
+ def message_to_dict(msg: Any) -> dict:
70
+ base = {
71
+ "id": getattr(msg, "id", None),
72
+ "subject": getattr(msg, "subject", None),
73
+ "from": recipient_to_dict(getattr(msg, "from_", None) or getattr(msg, "sender", None)),
74
+ "toRecipients": _recipients(getattr(msg, "to_recipients", None)),
75
+ "ccRecipients": _recipients(getattr(msg, "cc_recipients", None)),
76
+ "bccRecipients": _recipients(getattr(msg, "bcc_recipients", None)),
77
+ "receivedDateTime": getattr(msg, "received_date_time", None),
78
+ "sentDateTime": getattr(msg, "sent_date_time", None),
79
+ "bodyPreview": getattr(msg, "body_preview", None),
80
+ "body": _body_to_dict(getattr(msg, "body", None)),
81
+ "isRead": bool(getattr(msg, "is_read", False)),
82
+ "isDraft": bool(getattr(msg, "is_draft", False)),
83
+ "hasAttachments": bool(getattr(msg, "has_attachments", False)),
84
+ "importance": _enum_value(getattr(msg, "importance", None)),
85
+ "flag": _flag_to_dict(getattr(msg, "flag", None)),
86
+ "categories": list(getattr(msg, "categories", None) or []),
87
+ "conversationId": getattr(msg, "conversation_id", None),
88
+ "webLink": getattr(msg, "web_link", None),
89
+ "parentFolderId": getattr(msg, "parent_folder_id", None),
90
+ "inferenceClassification": _enum_value(getattr(msg, "inference_classification", None)),
91
+ }
92
+ return {**_additional(msg), **base}
93
+
94
+
95
+ def folder_to_dict(folder: Any) -> dict:
96
+ base = {
97
+ "id": getattr(folder, "id", None),
98
+ "displayName": getattr(folder, "display_name", None),
99
+ "parentFolderId": getattr(folder, "parent_folder_id", None),
100
+ "totalItemCount": getattr(folder, "total_item_count", None),
101
+ "unreadItemCount": getattr(folder, "unread_item_count", None),
102
+ "childFolderCount": getattr(folder, "child_folder_count", None),
103
+ }
104
+ return {**_additional(folder), **base}
105
+
106
+
107
+ def attachment_to_dict(att: Any, *, include_content: bool = False) -> dict:
108
+ base = {
109
+ "id": getattr(att, "id", None),
110
+ "name": getattr(att, "name", None),
111
+ "contentType": getattr(att, "content_type", None),
112
+ "size": getattr(att, "size", None),
113
+ "isInline": bool(getattr(att, "is_inline", False)),
114
+ }
115
+ if include_content:
116
+ raw = getattr(att, "content_bytes", None)
117
+ if isinstance(raw, (bytes, bytearray)):
118
+ base["contentBytes"] = base64.b64encode(raw).decode("ascii")
119
+ else:
120
+ base["contentBytes"] = raw # already a str
121
+ return {**_additional(att), **base}
122
+
123
+
124
+ def calendar_to_dict(cal: Any) -> dict:
125
+ owner = getattr(cal, "owner", None)
126
+ base = {
127
+ "id": getattr(cal, "id", None),
128
+ "name": getattr(cal, "name", None),
129
+ "owner": email_address_to_dict(owner) if owner is not None else None,
130
+ "canEdit": bool(getattr(cal, "can_edit", False)),
131
+ "isDefaultCalendar": bool(getattr(cal, "is_default_calendar", False)),
132
+ }
133
+ return {**_additional(cal), **base}
134
+
135
+
136
+ def event_to_dict(evt: Any) -> dict:
137
+ start = getattr(evt, "start", None)
138
+ end = getattr(evt, "end", None)
139
+ location = getattr(evt, "location", None)
140
+ online = getattr(evt, "online_meeting", None)
141
+ attendees_raw = getattr(evt, "attendees", None) or []
142
+ attendees = []
143
+ for a in attendees_raw:
144
+ status = getattr(a, "status", None)
145
+ attendees.append(
146
+ {
147
+ "emailAddress": email_address_to_dict(getattr(a, "email_address", None)),
148
+ "type": _enum_value(getattr(a, "type", None)),
149
+ "status": {"response": _enum_value(getattr(status, "response", None))}
150
+ if status is not None
151
+ else None,
152
+ }
153
+ )
154
+ base = {
155
+ "id": getattr(evt, "id", None),
156
+ "subject": getattr(evt, "subject", None),
157
+ "organizer": recipient_to_dict(getattr(evt, "organizer", None)),
158
+ "start": {
159
+ "dateTime": getattr(start, "date_time", None) if start else None,
160
+ "timeZone": getattr(start, "time_zone", None) if start else None,
161
+ },
162
+ "end": {
163
+ "dateTime": getattr(end, "date_time", None) if end else None,
164
+ "timeZone": getattr(end, "time_zone", None) if end else None,
165
+ },
166
+ "location": {"displayName": getattr(location, "display_name", None)} if location else {"displayName": None},
167
+ "isAllDay": bool(getattr(evt, "is_all_day", False)),
168
+ "isCancelled": bool(getattr(evt, "is_cancelled", False)),
169
+ "isOnlineMeeting": bool(getattr(evt, "is_online_meeting", False)),
170
+ "onlineMeeting": {"joinUrl": getattr(online, "join_url", None)} if online else None,
171
+ "attendees": attendees,
172
+ "bodyPreview": getattr(evt, "body_preview", None),
173
+ "body": _body_to_dict(getattr(evt, "body", None)),
174
+ "showAs": _enum_value(getattr(evt, "show_as", None)),
175
+ "sensitivity": _enum_value(getattr(evt, "sensitivity", None)),
176
+ "recurrence": getattr(evt, "recurrence", None),
177
+ "webLink": getattr(evt, "web_link", None),
178
+ }
179
+ return {**_additional(evt), **base}
180
+
181
+
182
+ def message_rule_predicates_to_dict(pred: Any) -> dict | None:
183
+ if pred is None:
184
+ return None
185
+ base = {
186
+ "bodyContains": list(getattr(pred, "body_contains", None) or []) or None,
187
+ "bodyOrSubjectContains": list(getattr(pred, "body_or_subject_contains", None) or []) or None,
188
+ "categories": list(getattr(pred, "categories", None) or []) or None,
189
+ "fromAddresses": _recipients(getattr(pred, "from_addresses", None)),
190
+ "hasAttachments": getattr(pred, "has_attachments", None),
191
+ "headerContains": list(getattr(pred, "header_contains", None) or []) or None,
192
+ "senderContains": list(getattr(pred, "sender_contains", None) or []) or None,
193
+ "subjectContains": list(getattr(pred, "subject_contains", None) or []) or None,
194
+ "sentToAddresses": _recipients(getattr(pred, "sent_to_addresses", None)),
195
+ "sentToMe": getattr(pred, "sent_to_me", None),
196
+ "sentOnlyToMe": getattr(pred, "sent_only_to_me", None),
197
+ "importance": _enum_value(getattr(pred, "importance", None)),
198
+ "messageActionFlag": _enum_value(getattr(pred, "message_action_flag", None)),
199
+ "sensitivity": _enum_value(getattr(pred, "sensitivity", None)),
200
+ }
201
+ return {**_additional(pred), **base}
202
+
203
+
204
+ def message_rule_actions_to_dict(actions: Any) -> dict | None:
205
+ if actions is None:
206
+ return None
207
+ base = {
208
+ "assignCategories": list(getattr(actions, "assign_categories", None) or []) or None,
209
+ "copyToFolder": getattr(actions, "copy_to_folder", None),
210
+ "delete": getattr(actions, "delete", None),
211
+ "forwardAsAttachmentTo": _recipients(getattr(actions, "forward_as_attachment_to", None)),
212
+ "forwardTo": _recipients(getattr(actions, "forward_to", None)),
213
+ "markAsRead": getattr(actions, "mark_as_read", None),
214
+ "markImportance": _enum_value(getattr(actions, "mark_importance", None)),
215
+ "moveToFolder": getattr(actions, "move_to_folder", None),
216
+ "permanentDelete": getattr(actions, "permanent_delete", None),
217
+ "redirectTo": _recipients(getattr(actions, "redirect_to", None)),
218
+ "stopProcessingRules": getattr(actions, "stop_processing_rules", None),
219
+ }
220
+ return {**_additional(actions), **base}
221
+
222
+
223
+ def message_rule_to_dict(rule: Any) -> dict:
224
+ base = {
225
+ "id": getattr(rule, "id", None),
226
+ "displayName": getattr(rule, "display_name", None),
227
+ "sequence": getattr(rule, "sequence", None),
228
+ "isEnabled": bool(getattr(rule, "is_enabled", False)),
229
+ "hasError": bool(getattr(rule, "has_error", False)),
230
+ "isReadOnly": bool(getattr(rule, "is_read_only", False)),
231
+ "conditions": message_rule_predicates_to_dict(getattr(rule, "conditions", None)),
232
+ "exceptions": message_rule_predicates_to_dict(getattr(rule, "exceptions", None)),
233
+ "actions": message_rule_actions_to_dict(getattr(rule, "actions", None)),
234
+ }
235
+ return {**_additional(rule), **base}
236
+
237
+
238
+ def _identity_to_dict(identity: Any) -> dict | None:
239
+ if identity is None:
240
+ return None
241
+ return {
242
+ "id": getattr(identity, "id", None),
243
+ "displayName": getattr(identity, "display_name", None),
244
+ }
245
+
246
+
247
+ def _identity_set_user(idset: Any) -> dict | None:
248
+ if idset is None:
249
+ return None
250
+ return _identity_to_dict(getattr(idset, "user", None))
251
+
252
+
253
+ def _chat_attachment_to_dict(att: Any) -> dict:
254
+ return {
255
+ "id": getattr(att, "id", None),
256
+ "contentType": getattr(att, "content_type", None),
257
+ "contentUrl": getattr(att, "content_url", None),
258
+ "name": getattr(att, "name", None),
259
+ # For card attachments (e.g. application/vnd.microsoft.card.adaptive)
260
+ # this carries the card payload as a JSON string — often the entire
261
+ # message content for app/bot posts.
262
+ "content": getattr(att, "content", None),
263
+ }
264
+
265
+
266
+ def _chat_mention_to_dict(m: Any) -> dict:
267
+ return {
268
+ "id": getattr(m, "id", None),
269
+ "mentionText": getattr(m, "mention_text", None),
270
+ }
271
+
272
+
273
+ def _chat_reaction_to_dict(r: Any) -> dict:
274
+ return {
275
+ "reactionType": getattr(r, "reaction_type", None),
276
+ "createdDateTime": getattr(r, "created_date_time", None),
277
+ "user": _identity_set_user(getattr(r, "user", None)),
278
+ }
279
+
280
+
281
+ def chat_message_to_dict(msg: Any) -> dict:
282
+ base = {
283
+ "id": getattr(msg, "id", None),
284
+ "messageType": _enum_value(getattr(msg, "message_type", None)),
285
+ "createdDateTime": getattr(msg, "created_date_time", None),
286
+ "lastModifiedDateTime": getattr(msg, "last_modified_date_time", None),
287
+ "deletedDateTime": getattr(msg, "deleted_date_time", None),
288
+ "importance": _enum_value(getattr(msg, "importance", None)),
289
+ "subject": getattr(msg, "subject", None),
290
+ "from": _identity_set_user(getattr(msg, "from_", None)),
291
+ "body": _body_to_dict(getattr(msg, "body", None)),
292
+ "attachments": [_chat_attachment_to_dict(a) for a in (getattr(msg, "attachments", None) or [])],
293
+ "mentions": [_chat_mention_to_dict(m) for m in (getattr(msg, "mentions", None) or [])],
294
+ "reactions": [_chat_reaction_to_dict(r) for r in (getattr(msg, "reactions", None) or [])],
295
+ "webUrl": getattr(msg, "web_url", None),
296
+ "etag": getattr(msg, "etag", None),
297
+ }
298
+ return {**_additional(msg), **base}
299
+
300
+
301
+ def _member_display_names(members: Any) -> list[str]:
302
+ return [
303
+ getattr(m, "display_name", None)
304
+ for m in (members or [])
305
+ if getattr(m, "display_name", None)
306
+ ]
307
+
308
+
309
+ def _chat_message_info_to_dict(preview: Any) -> dict | None:
310
+ """Serialize a chat's lastMessagePreview (a chatMessageInfo).
311
+
312
+ Only createdDateTime is surfaced; it is the true "last activity" time,
313
+ unlike chat.lastUpdatedDateTime which only tracks rename/membership
314
+ changes.
315
+ """
316
+ if preview is None:
317
+ return None
318
+ return {"createdDateTime": getattr(preview, "created_date_time", None)}
319
+
320
+
321
+ def chat_to_dict(chat: Any) -> dict:
322
+ base = {
323
+ "id": getattr(chat, "id", None),
324
+ "chatType": _enum_value(getattr(chat, "chat_type", None)),
325
+ "topic": getattr(chat, "topic", None),
326
+ "lastUpdatedDateTime": getattr(chat, "last_updated_date_time", None),
327
+ "lastMessagePreview": _chat_message_info_to_dict(getattr(chat, "last_message_preview", None)),
328
+ "members": _member_display_names(getattr(chat, "members", None)),
329
+ "webUrl": getattr(chat, "web_url", None),
330
+ }
331
+ return {**_additional(chat), **base}
332
+
333
+
334
+ def team_to_dict(team: Any) -> dict:
335
+ base = {
336
+ "id": getattr(team, "id", None),
337
+ "displayName": getattr(team, "display_name", None),
338
+ "description": getattr(team, "description", None),
339
+ }
340
+ return {**_additional(team), **base}
341
+
342
+
343
+ def channel_to_dict(ch: Any) -> dict:
344
+ base = {
345
+ "id": getattr(ch, "id", None),
346
+ "displayName": getattr(ch, "display_name", None),
347
+ "description": getattr(ch, "description", None),
348
+ "membershipType": _enum_value(getattr(ch, "membership_type", None)),
349
+ "webUrl": getattr(ch, "web_url", None),
350
+ }
351
+ return {**_additional(ch), **base}