notte-sdk 0.0.dev0__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,285 @@
1
+ from collections.abc import Sequence
2
+ from typing import Any, Unpack
3
+
4
+ from notte_core.credentials.base import CredentialField
5
+ from pydantic import BaseModel
6
+ from typing_extensions import final, override
7
+
8
+ from notte_sdk.endpoints.base import BaseClient, NotteEndpoint
9
+ from notte_sdk.errors import NotteAPIError
10
+ from notte_sdk.types import (
11
+ AddCredentialsRequest,
12
+ AddCredentialsRequestDict,
13
+ AddCredentialsResponse,
14
+ DeleteCredentialsRequest,
15
+ DeleteCredentialsRequestDict,
16
+ DeleteCredentialsResponse,
17
+ EmailResponse,
18
+ EmailsReadRequest,
19
+ EmailsReadRequestDict,
20
+ GetCredentialsRequest,
21
+ GetCredentialsRequestDict,
22
+ GetCredentialsResponse,
23
+ PersonaCreateRequest,
24
+ PersonaCreateRequestDict,
25
+ PersonaCreateResponse,
26
+ SMSReadRequest,
27
+ SMSReadRequestDict,
28
+ SMSResponse,
29
+ VirtualNumberRequest,
30
+ VirtualNumberRequestDict,
31
+ VirtualNumberResponse,
32
+ )
33
+
34
+
35
+ @final
36
+ class PersonasClient(BaseClient):
37
+ """
38
+ Client for the Notte API.
39
+
40
+ Note: this client is only able to handle one session at a time.
41
+ If you need to handle multiple sessions, you need to create a new client for each session.
42
+ """
43
+
44
+ # Session
45
+ EMAILS_READ = "{persona_id}/email/read"
46
+ SMS_READ = "{persona_id}/sms/read"
47
+ CREATE_NUMBER = "{persona_id}/create-number"
48
+ CREATE_PERSONA = "create"
49
+ ADD_CREDENTIALS = "{persona_id}/credentials"
50
+ GET_CREDENTIALS = "{persona_id}/credentials"
51
+ DELETE_CREDENTIALS = "{persona_id}/credentials"
52
+
53
+ def __init__(
54
+ self,
55
+ api_key: str | None = None,
56
+ verbose: bool = False,
57
+ ):
58
+ """
59
+ Initialize a PersonasClient instance.
60
+
61
+ Initializes the client with an optional API key for persona management.
62
+ """
63
+ super().__init__(base_endpoint_path="personas", api_key=api_key, verbose=verbose)
64
+
65
+ @override
66
+ @staticmethod
67
+ def endpoints() -> Sequence[NotteEndpoint[BaseModel]]:
68
+ """Returns the available persona endpoints.
69
+
70
+ Aggregates endpoints from PersonasClient for creating personas, reading messages, etc..."""
71
+ return [
72
+ PersonasClient.email_read_endpoint(""),
73
+ PersonasClient.sms_read_endpoint(""),
74
+ PersonasClient.create_number_endpoint(""),
75
+ PersonasClient.create_persona_endpoint(),
76
+ PersonasClient.add_credentials_endpoint(""),
77
+ PersonasClient.get_credentials_endpoint(""),
78
+ PersonasClient.delete_credentials_endpoint(""),
79
+ ]
80
+
81
+ @staticmethod
82
+ def email_read_endpoint(persona_id: str) -> NotteEndpoint[EmailResponse]:
83
+ """
84
+ Returns a NotteEndpoint configured for reading persona emails.
85
+
86
+ The returned endpoint uses the email_read path from PersonasClient with the GET method
87
+ and expects a sequence of EmailResponse.
88
+ """
89
+ return NotteEndpoint(
90
+ path=PersonasClient.EMAILS_READ.format(persona_id=persona_id),
91
+ response=EmailResponse,
92
+ method="GET",
93
+ )
94
+
95
+ @staticmethod
96
+ def sms_read_endpoint(persona_id: str) -> NotteEndpoint[SMSResponse]:
97
+ """
98
+ Returns a NotteEndpoint configured for reading persona sms messages.
99
+
100
+ The returned endpoint uses the sms_read path from PersonasClient with the GET method
101
+ and expects a sequence of SMSResponse.
102
+ """
103
+ return NotteEndpoint(
104
+ path=PersonasClient.SMS_READ.format(persona_id=persona_id),
105
+ response=SMSResponse,
106
+ method="GET",
107
+ )
108
+
109
+ @staticmethod
110
+ def create_number_endpoint(persona_id: str) -> NotteEndpoint[VirtualNumberResponse]:
111
+ """
112
+ Returns a NotteEndpoint configured for creating a virtual phone number.
113
+
114
+ The returned endpoint uses the create number path from PersonasClient with the POST method and expects a VirtualNumberResponse.
115
+ """
116
+ return NotteEndpoint(
117
+ path=PersonasClient.CREATE_NUMBER.format(persona_id=persona_id),
118
+ response=VirtualNumberResponse,
119
+ method="POST",
120
+ )
121
+
122
+ @staticmethod
123
+ def create_persona_endpoint() -> NotteEndpoint[PersonaCreateResponse]:
124
+ """
125
+ Returns a NotteEndpoint configured for creating a persona.
126
+
127
+ The returned endpoint uses the credentials from PersonasClient with the POST method and expects a PersonaCreateResponse.
128
+ """
129
+ return NotteEndpoint(
130
+ path=PersonasClient.CREATE_PERSONA,
131
+ response=PersonaCreateResponse,
132
+ method="POST",
133
+ )
134
+
135
+ @staticmethod
136
+ def add_credentials_endpoint(persona_id: str) -> NotteEndpoint[AddCredentialsResponse]:
137
+ """
138
+ Returns a NotteEndpoint configured for adding credentials.
139
+
140
+ The returned endpoint uses the credentials from PersonasClient with the POST method and expects an AddCredentialsResponse.
141
+ """
142
+ return NotteEndpoint(
143
+ path=PersonasClient.ADD_CREDENTIALS.format(persona_id=persona_id),
144
+ response=AddCredentialsResponse,
145
+ method="POST",
146
+ )
147
+
148
+ @staticmethod
149
+ def get_credentials_endpoint(persona_id: str) -> NotteEndpoint[GetCredentialsResponse]:
150
+ """
151
+ Returns a NotteEndpoint configured for getting credentials.
152
+
153
+ The returned endpoint uses the credentials from PersonasClient with the GET method and expects a GetCredentialsResponse.
154
+ """
155
+ return NotteEndpoint(
156
+ path=PersonasClient.GET_CREDENTIALS.format(persona_id=persona_id),
157
+ response=GetCredentialsResponse,
158
+ method="GET",
159
+ )
160
+
161
+ @staticmethod
162
+ def delete_credentials_endpoint(persona_id: str) -> NotteEndpoint[DeleteCredentialsResponse]:
163
+ """
164
+ Returns a NotteEndpoint configured for deleting credentials.
165
+
166
+ The returned endpoint uses the create persona path from PersonasClient with the DELETE method and expects a DeleteCredentialsResponse.
167
+ """
168
+ return NotteEndpoint(
169
+ path=PersonasClient.DELETE_CREDENTIALS.format(persona_id=persona_id),
170
+ response=DeleteCredentialsResponse,
171
+ method="DELETE",
172
+ )
173
+
174
+ def add_credentials(self, persona_id: str, **data: Unpack[AddCredentialsRequestDict]) -> AddCredentialsResponse:
175
+ """
176
+ Add credentials
177
+
178
+ Args:
179
+ persona_id: The ID of the persona to add credentials to
180
+ **data: Query parameters including:
181
+ url: Website url for which to add credentials (if None, singleton credentials)
182
+ credentials: The credentials to add
183
+
184
+ Returns:
185
+ AddCredentialsResponse: status for added credentials
186
+ """
187
+ params = AddCredentialsRequest.from_request_dict(data)
188
+ response = self.request(PersonasClient.add_credentials_endpoint(persona_id).with_request(params))
189
+ return response
190
+
191
+ def get_credentials(self, persona_id: str, **data: Unpack[GetCredentialsRequestDict]) -> GetCredentialsResponse:
192
+ """
193
+ Get credentials
194
+
195
+ Args:
196
+ persona_id: The ID of the persona to get credentials from
197
+ **data: Query parameters including:
198
+ url: Website url for which to get credentials (if None, return singleton credentials)
199
+
200
+ Returns:
201
+ GetCredentialsResponse: returned credentials
202
+ """
203
+ params = GetCredentialsRequest.model_validate(data)
204
+ endpoint = PersonasClient.get_credentials_endpoint(persona_id).with_params(params)
205
+
206
+ # need to do some trickery to build Creds
207
+ response: Any = self._request(endpoint)
208
+ if not isinstance(response, dict):
209
+ raise NotteAPIError(path=endpoint.path, response=response)
210
+
211
+ creds = [CredentialField.from_dict(field) for field in response["credentials"]] # type: ignore
212
+
213
+ return GetCredentialsResponse(credentials=creds)
214
+
215
+ def delete_credentials(
216
+ self, persona_id: str, **data: Unpack[DeleteCredentialsRequestDict]
217
+ ) -> DeleteCredentialsResponse:
218
+ """
219
+ Delete credentials
220
+
221
+ Args:
222
+ persona_id: The ID of the persona for which we remove credentials
223
+ **data: Query parameters including:
224
+ url: Website url for which we remove credentials (if None, delete singleton credentials)
225
+
226
+ Returns:
227
+ DeleteCredentialsResponse: status for deleted credentials
228
+ """
229
+ params = DeleteCredentialsRequest.model_validate(data)
230
+ response = self.request(PersonasClient.delete_credentials_endpoint(persona_id).with_params(params))
231
+ return response
232
+
233
+ def create_persona(self, **data: Unpack[PersonaCreateRequestDict]) -> PersonaCreateResponse:
234
+ """
235
+ Create persona
236
+
237
+ Args:
238
+
239
+ Returns:
240
+ PersonaCreateResponse: The persona created
241
+ """
242
+ params = PersonaCreateRequest.model_validate(data)
243
+ response = self.request(PersonasClient.create_persona_endpoint().with_request(params))
244
+ return response
245
+
246
+ def create_number(self, persona_id: str, **data: Unpack[VirtualNumberRequestDict]) -> VirtualNumberResponse:
247
+ """
248
+ Create phone number for persona (if one didn't exist before)
249
+
250
+ Args:
251
+
252
+ Returns:
253
+ VirtualNumberResponse: The status
254
+ """
255
+ params = VirtualNumberRequest.model_validate(data)
256
+ response = self.request(PersonasClient.create_number_endpoint(persona_id).with_request(params))
257
+ return response
258
+
259
+ def email_read(self, persona_id: str, **data: Unpack[EmailsReadRequestDict]) -> Sequence[EmailResponse]:
260
+ """
261
+ Reads recent emails sent to the persona
262
+
263
+ Args:
264
+ **data: Keyword arguments representing details for querying emails.
265
+
266
+ Returns:
267
+ Sequence[EmailResponse]: The list of emails found
268
+ """
269
+ request = EmailsReadRequest.model_validate(data)
270
+ response = self.request_list(PersonasClient.email_read_endpoint(persona_id).with_params(request))
271
+ return response
272
+
273
+ def sms_read(self, persona_id: str, **data: Unpack[SMSReadRequestDict]) -> Sequence[SMSResponse]:
274
+ """
275
+ Reads recent sms messages sent to the persona
276
+
277
+ Args:
278
+ **data: Keyword arguments representing details for querying sms messages.
279
+
280
+ Returns:
281
+ Sequence[SMSResponse]: The list of sms messages found
282
+ """
283
+ request = SMSReadRequest.model_validate(data)
284
+ response = self.request_list(PersonasClient.sms_read_endpoint(persona_id).with_params(request))
285
+ return response