scheme-sdk 0.3.5__py3-none-any.whl → 0.3.7__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.
|
@@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
|
|
|
2
2
|
from datetime import datetime
|
|
3
3
|
from dataclasses import dataclass, field
|
|
4
4
|
from typing import Any, Dict, Iterable, Optional
|
|
5
|
+
from html_sanitizer import Sanitizer
|
|
5
6
|
|
|
6
7
|
from .base import BaseConnector
|
|
7
8
|
|
|
@@ -11,6 +12,11 @@ class MessageConnector(BaseConnector, ABC):
|
|
|
11
12
|
Abstract base class for all message connectors.
|
|
12
13
|
"""
|
|
13
14
|
|
|
15
|
+
_sanitizer: Sanitizer
|
|
16
|
+
|
|
17
|
+
def __init__(self):
|
|
18
|
+
self._sanitizer = Sanitizer()
|
|
19
|
+
|
|
14
20
|
@abstractmethod
|
|
15
21
|
def fetch_conversations(self) -> Iterable[Dict[str, Any]]:
|
|
16
22
|
"""
|
|
@@ -85,6 +91,7 @@ class MessageConnector(BaseConnector, ABC):
|
|
|
85
91
|
"""
|
|
86
92
|
...
|
|
87
93
|
|
|
94
|
+
@abstractmethod
|
|
88
95
|
def normalize_message(self, raw_message: Dict[str, Any]) -> Dict[str, Any]:
|
|
89
96
|
"""
|
|
90
97
|
Transform a platform-specific message into canonical format.
|
|
@@ -100,6 +107,7 @@ class MessageConnector(BaseConnector, ABC):
|
|
|
100
107
|
"""
|
|
101
108
|
...
|
|
102
109
|
|
|
110
|
+
@abstractmethod
|
|
103
111
|
def normalize_conversation(
|
|
104
112
|
self, raw_conversation: Dict[str, Any]
|
|
105
113
|
) -> Dict[str, Any]:
|
|
@@ -134,6 +142,18 @@ class MessageConnector(BaseConnector, ABC):
|
|
|
134
142
|
self._logger.warning(f"search_messages not implemented for {self.platform}")
|
|
135
143
|
return iter([])
|
|
136
144
|
|
|
145
|
+
def _sanitize_html(self, html: str) -> str:
|
|
146
|
+
"""
|
|
147
|
+
Sanitize HTML content.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
html: HTML content to sanitize
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Sanitized HTML content
|
|
154
|
+
"""
|
|
155
|
+
return self._sanitizer.sanitize(html)
|
|
156
|
+
|
|
137
157
|
|
|
138
158
|
@dataclass
|
|
139
159
|
class Conversation:
|
scheme_sdk/connectors/outlook.py
CHANGED
|
@@ -4,6 +4,12 @@ from typing import Any, Dict, List, Optional
|
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
|
+
from pprint import pprint as pp
|
|
8
|
+
from dotenv import load_dotenv
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
load_dotenv()
|
|
12
|
+
|
|
7
13
|
from .base import MessageConnector
|
|
8
14
|
|
|
9
15
|
|
|
@@ -14,6 +20,7 @@ class OutlookConnector(MessageConnector):
|
|
|
14
20
|
_backoff_cap_seconds = 30
|
|
15
21
|
|
|
16
22
|
def __init__(self, token: str):
|
|
23
|
+
super().__init__()
|
|
17
24
|
self.token = token
|
|
18
25
|
self.base = "https://graph.microsoft.com/v1.0"
|
|
19
26
|
|
|
@@ -23,17 +30,27 @@ class OutlookConnector(MessageConnector):
|
|
|
23
30
|
query: Optional[str] = None,
|
|
24
31
|
since_iso: Optional[str] = None,
|
|
25
32
|
) -> List[Dict]:
|
|
33
|
+
"""Fetch conversations from Outlook. Filter criteria are ignored if query is provided.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
top (int, optional): The number of conversations to fetch. Defaults to 50.
|
|
37
|
+
query (Optional[str], optional): The query to search for. Defaults to None.
|
|
38
|
+
since_iso (Optional[str], optional): The date to search for. Defaults to None.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
List[Dict]: The conversations.
|
|
42
|
+
"""
|
|
26
43
|
url = f"{self.base}/me/messages"
|
|
27
44
|
page_size = min(max(top, 50), 200)
|
|
28
45
|
params = {
|
|
29
46
|
"$select": "id,conversationId,subject,from,receivedDateTime,hasAttachments,webLink",
|
|
30
|
-
"$orderby": "receivedDateTime desc",
|
|
31
47
|
"$top": str(page_size),
|
|
32
48
|
}
|
|
33
|
-
if since_iso:
|
|
34
|
-
params["$filter"] = f"receivedDateTime ge {since_iso}"
|
|
35
49
|
if query:
|
|
36
|
-
params["$search"] = query
|
|
50
|
+
params["$search"] = f'"{query}"'
|
|
51
|
+
elif since_iso:
|
|
52
|
+
params["$filter"] = f"receivedDateTime ge {since_iso}"
|
|
53
|
+
params["$orderby"] = "receivedDateTime desc"
|
|
37
54
|
|
|
38
55
|
# Dedupe by conversationId, fetching more pages until we have enough.
|
|
39
56
|
threads_by_conv: Dict[str, Dict] = {}
|
|
@@ -67,6 +84,15 @@ class OutlookConnector(MessageConnector):
|
|
|
67
84
|
conversation_id: str,
|
|
68
85
|
since_iso: Optional[str] = None,
|
|
69
86
|
) -> List[Dict]:
|
|
87
|
+
"""Fetch messages from a specific conversation.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
conversation_id (str): The ID of the conversation.
|
|
91
|
+
since_iso (Optional[str], optional): The date to search for. Defaults to None.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
List[Dict]: The messages.
|
|
95
|
+
"""
|
|
70
96
|
url = f"{self.base}/me/messages"
|
|
71
97
|
filter_parts = [f"conversationId eq '{conversation_id}'"]
|
|
72
98
|
if since_iso:
|
|
@@ -88,10 +114,18 @@ class OutlookConnector(MessageConnector):
|
|
|
88
114
|
]
|
|
89
115
|
|
|
90
116
|
def normalize_message(self, message: Dict) -> Dict[str, Any]:
|
|
117
|
+
"""Normalize a message from Outlook.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
message (Dict): The message to normalize.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Dict[str, Any]: The normalized message.
|
|
124
|
+
"""
|
|
91
125
|
return {
|
|
92
126
|
"title": message["subject"],
|
|
93
127
|
"platform": self.platform,
|
|
94
|
-
"text": message["body"]["content"],
|
|
128
|
+
"text": self._sanitize_html(message["body"]["content"]),
|
|
95
129
|
"direct_link": message["webLink"],
|
|
96
130
|
"metadata": {
|
|
97
131
|
"platform_conversation_id": message["conversationId"],
|
|
@@ -106,6 +140,14 @@ class OutlookConnector(MessageConnector):
|
|
|
106
140
|
}
|
|
107
141
|
|
|
108
142
|
def normalize_conversation(self, conversation: Dict) -> Dict[str, Any]:
|
|
143
|
+
"""Normalize a conversation from Outlook.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
conversation (Dict): The conversation to normalize.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Dict[str, Any]: The normalized conversation.
|
|
150
|
+
"""
|
|
109
151
|
return {
|
|
110
152
|
"id": conversation["conversationId"],
|
|
111
153
|
"title": conversation["subject"],
|
|
@@ -177,3 +219,11 @@ class OutlookConnector(MessageConnector):
|
|
|
177
219
|
next_params = None # nextLink already includes the query string
|
|
178
220
|
|
|
179
221
|
return items
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
if __name__ == "__main__":
|
|
225
|
+
connector = OutlookConnector(os.getenv("OUTLOOK_TOKEN"))
|
|
226
|
+
conversations = connector.fetch_conversations(top=1)
|
|
227
|
+
pp(conversations)
|
|
228
|
+
messages = connector.fetch_messages(conversations[0]["id"])
|
|
229
|
+
pp(messages)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: scheme_sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: The Scheme SDK provides connectors for ingesting conversations, messages, and files across communication platforms.
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
@@ -203,6 +203,7 @@ License: Apache License
|
|
|
203
203
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
204
204
|
See the License for the specific language governing permissions and
|
|
205
205
|
limitations under the License.
|
|
206
|
+
Requires-Dist: html-sanitizer>=2.6.0
|
|
206
207
|
Requires-Dist: requests>=2.32.5
|
|
207
208
|
Requires-Python: >=3.11
|
|
208
209
|
Project-URL: Homepage, https://www.schemebig.com/
|
|
@@ -3,11 +3,11 @@ scheme_sdk/connectors/__init__.py,sha256=d7XyCKbx0QklcAFyhTbNxTg0PakQfTs3eQSayYU
|
|
|
3
3
|
scheme_sdk/connectors/base/__init__.py,sha256=7bTnekIGEB0S8jDT7tBfCIgsW4VXtK_Da_vrrYhByEw,639
|
|
4
4
|
scheme_sdk/connectors/base/base.py,sha256=JtsD-HBdjC_Jl22M9j-ihe0tyXJw6JpgWsZp_ozCwDA,8855
|
|
5
5
|
scheme_sdk/connectors/base/errors.py,sha256=53Dhz5qImXJe0q0cO7IqG4yja0OC0hnxMNMMmgdCtW0,1152
|
|
6
|
-
scheme_sdk/connectors/base/message.py,sha256=
|
|
6
|
+
scheme_sdk/connectors/base/message.py,sha256=WqKGMsv8YTbCafkA53ybrlgF3FseVKx1M2jjN9O_7kE,5851
|
|
7
7
|
scheme_sdk/connectors/discord.py,sha256=CdtzVlwT0aHcUayhLGno_vmfhdt_WRtGOeV2zj7Ye7I,844
|
|
8
8
|
scheme_sdk/connectors/gmail.py,sha256=wZCj917qujXSE9jexqvkDgdmz02y6QST8q9KNRwEvg0,866
|
|
9
|
-
scheme_sdk/connectors/outlook.py,sha256=
|
|
9
|
+
scheme_sdk/connectors/outlook.py,sha256=udANT0wZNOla_u0Tp8ih-HVLeJeGp7P7GHux6l2SMgs,7798
|
|
10
10
|
scheme_sdk/connectors/slack.py,sha256=_g--XxS4_ImT0fs0HX9vNquTkUlaikiylBhsgJzCC-4,1434
|
|
11
|
-
scheme_sdk-0.3.
|
|
12
|
-
scheme_sdk-0.3.
|
|
13
|
-
scheme_sdk-0.3.
|
|
11
|
+
scheme_sdk-0.3.7.dist-info/WHEEL,sha256=e_m4S054HL0hyR3CpOk-b7Q7fDX6BuFkgL5OjAExXas,80
|
|
12
|
+
scheme_sdk-0.3.7.dist-info/METADATA,sha256=Iu9KqEFvFFKg37iuf2i0h7gyljcTjMPElFf8ZnSgQNY,15121
|
|
13
|
+
scheme_sdk-0.3.7.dist-info/RECORD,,
|
|
File without changes
|