google-api-client-wrapper 1.0.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.
Files changed (39) hide show
  1. google_api_client_wrapper-1.0.0.dist-info/METADATA +103 -0
  2. google_api_client_wrapper-1.0.0.dist-info/RECORD +39 -0
  3. google_api_client_wrapper-1.0.0.dist-info/WHEEL +5 -0
  4. google_api_client_wrapper-1.0.0.dist-info/licenses/LICENSE +21 -0
  5. google_api_client_wrapper-1.0.0.dist-info/top_level.txt +1 -0
  6. google_client/__init__.py +6 -0
  7. google_client/services/__init__.py +13 -0
  8. google_client/services/calendar/__init__.py +14 -0
  9. google_client/services/calendar/api_service.py +454 -0
  10. google_client/services/calendar/constants.py +48 -0
  11. google_client/services/calendar/exceptions.py +35 -0
  12. google_client/services/calendar/query_builder.py +314 -0
  13. google_client/services/calendar/types.py +403 -0
  14. google_client/services/calendar/utils.py +338 -0
  15. google_client/services/drive/__init__.py +13 -0
  16. google_client/services/drive/api_service.py +1133 -0
  17. google_client/services/drive/constants.py +37 -0
  18. google_client/services/drive/exceptions.py +60 -0
  19. google_client/services/drive/query_builder.py +385 -0
  20. google_client/services/drive/types.py +242 -0
  21. google_client/services/drive/utils.py +392 -0
  22. google_client/services/gmail/__init__.py +16 -0
  23. google_client/services/gmail/api_service.py +715 -0
  24. google_client/services/gmail/constants.py +6 -0
  25. google_client/services/gmail/exceptions.py +45 -0
  26. google_client/services/gmail/query_builder.py +408 -0
  27. google_client/services/gmail/types.py +285 -0
  28. google_client/services/gmail/utils.py +426 -0
  29. google_client/services/tasks/__init__.py +12 -0
  30. google_client/services/tasks/api_service.py +561 -0
  31. google_client/services/tasks/constants.py +32 -0
  32. google_client/services/tasks/exceptions.py +35 -0
  33. google_client/services/tasks/query_builder.py +324 -0
  34. google_client/services/tasks/types.py +156 -0
  35. google_client/services/tasks/utils.py +224 -0
  36. google_client/user_client.py +208 -0
  37. google_client/utils/__init__.py +0 -0
  38. google_client/utils/datetime.py +144 -0
  39. google_client/utils/validation.py +71 -0
@@ -0,0 +1,285 @@
1
+
2
+ from typing import Optional, List
3
+ from datetime import datetime
4
+ from dataclasses import dataclass, field
5
+ from html2text import html2text
6
+
7
+ from google_client.utils.datetime import convert_datetime_to_readable
8
+
9
+
10
+ @dataclass
11
+ class EmailAddress:
12
+ """
13
+ Represents an email address with name and email.
14
+ Args:
15
+ email: The email address.
16
+ name: The display name (optional).
17
+ """
18
+ email: str
19
+ name: Optional[str] = None
20
+
21
+
22
+ def to_dict(self) -> dict:
23
+ """
24
+ Converts the EmailAddress instance to a dictionary representation.
25
+ Returns:
26
+ A dictionary containing the email address data.
27
+ """
28
+ result = {"email": self.email}
29
+ if self.name:
30
+ result["name"] = self.name
31
+ return result
32
+
33
+ def __str__(self):
34
+ if self.name:
35
+ return f"{self.name} <{self.email}>"
36
+ return self.email
37
+
38
+
39
+ @dataclass
40
+ class EmailAttachment:
41
+ """
42
+ Represents an email attachment.
43
+ Args:
44
+ filename: The name of the attachment file.
45
+ mime_type: The MIME type of the attachment.
46
+ size: The size of the attachment in bytes.
47
+ attachment_id: The unique identifier for the attachment in Gmail.
48
+ message_id: The message id of the message the attachment is attached to.
49
+ """
50
+ filename: str
51
+ mime_type: str
52
+ size: int
53
+ attachment_id: str
54
+ message_id: str
55
+
56
+
57
+ def to_dict(self) -> dict:
58
+ """
59
+ Converts the EmailAttachment instance to a dictionary representation.
60
+ Returns:
61
+ A dictionary containing the attachment data.
62
+ """
63
+ return {
64
+ "filename": self.filename,
65
+ "content_type": self.mime_type,
66
+ "size": self.size,
67
+ "attachment_id": self.attachment_id,
68
+ "message_id": self.message_id,
69
+ }
70
+
71
+
72
+ @dataclass
73
+ class Label:
74
+ """
75
+ Represents a Gmail label.
76
+ Args:
77
+ id: The unique identifier for the label.
78
+ name: The name of the label.
79
+ type: The type of the label (e.g., system, user).
80
+ """
81
+ id: str
82
+ name: str
83
+ type: str
84
+
85
+ def to_dict(self):
86
+ return {
87
+ 'id': self.id,
88
+ 'name': self.name,
89
+ 'type': self.type,
90
+ }
91
+
92
+ def __repr__(self):
93
+ return f"Label(id={self.id}, name={self.name}, type={self.type})"
94
+
95
+
96
+ @dataclass
97
+ class EmailThread:
98
+ """
99
+ Represents a Gmail thread containing multiple related messages.
100
+ Args:
101
+ thread_id: Unique identifier for the thread.
102
+ messages: List of EmailMessage objects in this thread.
103
+ snippet: A short snippet of the thread content.
104
+ history_id: The history ID of the thread.
105
+ """
106
+ thread_id: Optional[str] = None
107
+ messages: List["EmailMessage"] = field(default_factory=list)
108
+ snippet: Optional[str] = None
109
+ history_id: Optional[str] = None
110
+
111
+ def get_latest_message(self) -> Optional["EmailMessage"]:
112
+ """
113
+ Gets the most recent message in the thread.
114
+ Returns:
115
+ The latest EmailMessage or None if no messages exist.
116
+ """
117
+ if not self.messages:
118
+ return None
119
+ return max(self.messages, key=lambda msg: msg.date_time or datetime.min)
120
+
121
+ def get_unread_count(self) -> int:
122
+ """
123
+ Gets the number of unread messages in the thread.
124
+ Returns:
125
+ Count of unread messages.
126
+ """
127
+ return sum(1 for msg in self.messages if not msg.is_read)
128
+
129
+ def has_unread_messages(self) -> bool:
130
+ """
131
+ Checks if the thread has any unread messages.
132
+ Returns:
133
+ True if there are unread messages, False otherwise.
134
+ """
135
+ return any(not msg.is_read for msg in self.messages)
136
+
137
+ def get_participants(self) -> List[EmailAddress]:
138
+ """
139
+ Gets all unique participants in the thread.
140
+ Returns:
141
+ List of unique EmailAddress objects from all messages.
142
+ """
143
+ participants = set()
144
+ for message in self.messages:
145
+ if message.sender:
146
+ participants.add((message.sender.email, message.sender.name))
147
+ for recipient in message.recipients + message.cc_recipients + message.bcc_recipients:
148
+ participants.add((recipient.email, recipient.name))
149
+
150
+ return [EmailAddress(email=email, name=name) for email, name in participants]
151
+
152
+ def __repr__(self):
153
+ latest = self.get_latest_message()
154
+ return (
155
+ f"Thread ID: {self.thread_id}\n"
156
+ f"Messages: {len(self.messages)}\n"
157
+ f"Unread: {self.get_unread_count()}\n"
158
+ f"Latest: {latest.subject if latest else 'No messages'}\n"
159
+ f"Snippet: {self.snippet}\n"
160
+ )
161
+
162
+
163
+ @dataclass
164
+ class EmailMessage:
165
+ """
166
+ Represents a Gmail message with various attributes.
167
+ Args:
168
+ message_id: Unique identifier for the message.
169
+ thread_id: The thread ID this message belongs to.
170
+ subject: The subject line of the email.
171
+ sender: The sender's email address information.
172
+ recipients: List of recipient email addresses (To field).
173
+ cc_recipients: List of CC recipient email addresses.
174
+ bcc_recipients: List of BCC recipient email addresses.
175
+ date_time: When the message was sent or received.
176
+ body_text: Plain text body of the email.
177
+ body_html: HTML body of the email.
178
+ attachments: List of attachments in the email.
179
+ labels: List of Gmail labels applied to the message.
180
+ is_read: Whether the message has been read.
181
+ is_starred: Whether the message is starred.
182
+ is_important: Whether the message is marked as important.
183
+ snippet: A short snippet of the message content.
184
+ reply_to_id: The ID of the message to use when replying to this message.
185
+ """
186
+ message_id: Optional[str] = None
187
+ thread_id: Optional[str] = None
188
+
189
+ reply_to_id: Optional[str] = None
190
+ references: Optional[str] = None
191
+
192
+ subject: Optional[str] = None
193
+ body_html: Optional[str] = None
194
+ body_text: Optional[str] = None
195
+ attachments: List[EmailAttachment] = field(default_factory=list)
196
+
197
+ sender: Optional[EmailAddress] = None
198
+ recipients: List[EmailAddress] = field(default_factory=list)
199
+ cc_recipients: List[EmailAddress] = field(default_factory=list)
200
+ bcc_recipients: List[EmailAddress] = field(default_factory=list)
201
+
202
+ date_time: Optional[datetime] = None
203
+
204
+ labels: List[str] = field(default_factory=list)
205
+ is_read: bool = False
206
+ is_starred: bool = False
207
+ is_important: bool = False
208
+
209
+ snippet: Optional[str] = None
210
+
211
+ def get_plain_text_content(self) -> str:
212
+ """
213
+ Retrieves the plain text content of the email message, converting HTML if necessary.
214
+ Returns:
215
+ The plain text content if available, empty string otherwise.
216
+ """
217
+ if self.body_text:
218
+ return self.body_text.strip()
219
+ elif self.body_html:
220
+ return html2text(self.body_html)
221
+ return ""
222
+
223
+ def has_attachments(self) -> bool:
224
+ """
225
+ Checks if the message has attachments.
226
+ Returns:
227
+ True if the message has attachments, False otherwise.
228
+ """
229
+ return len(self.attachments) > 0
230
+
231
+ def get_recipient_emails(self) -> List[str]:
232
+ """
233
+ Retrieves a list of recipient emails (To).
234
+ Returns:
235
+ A list of recipient email addresses.
236
+ """
237
+ return [recipient.email for recipient in self.recipients]
238
+
239
+ def get_all_recipient_emails(self) -> List[str]:
240
+ """
241
+ Retrieves a list of all recipient email addresses (To, CC, BCC).
242
+ Returns:
243
+ A list of email addresses.
244
+ """
245
+ emails = []
246
+ for recipient in self.recipients + self.cc_recipients + self.bcc_recipients:
247
+ emails.append(recipient.email)
248
+ return emails
249
+
250
+ def is_from(self, email: str) -> bool:
251
+ """
252
+ Checks if the message is from a specific email address.
253
+ Use "me" to check if the message is from the authenticated user.
254
+ Args:
255
+ email: The email address to check.
256
+
257
+ Returns:
258
+ True if the message is from the specified email, False otherwise.
259
+ """
260
+ if email.lower() == "me":
261
+ # Special case for checking if the message is from the authenticated user
262
+ return 'SENT' in self.labels
263
+
264
+ return self.sender and self.sender.email.lower() == email.lower()
265
+
266
+ def has_label(self, label: str) -> bool:
267
+ """
268
+ Checks if the message has a specific label.
269
+ Args:
270
+ label: The label to check for.
271
+
272
+ Returns:
273
+ True if the message has the label, False otherwise.
274
+ """
275
+ return label in self.labels
276
+
277
+ def __repr__(self):
278
+ return (
279
+ f"Subject: {self.subject!r}\n"
280
+ f"From: {self.sender}\n"
281
+ f"To: {', '.join(str(r) for r in self.recipients)}\n"
282
+ f"Date: {convert_datetime_to_readable(self.date_time) if self.date_time else 'Unknown'}\n"
283
+ f"Snippet: {self.snippet}\n"
284
+ f"Labels: {', '.join(self.labels)}\n"
285
+ )