ingestr 0.5.1__py3-none-any.whl → 0.6.1__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 ingestr might be problematic. Click here for more details.

@@ -0,0 +1,587 @@
1
+ """Fetches Gorgias data."""
2
+
3
+ from typing import Iterable
4
+
5
+ import dlt
6
+ from dlt.common.time import ensure_pendulum_datetime
7
+ from dlt.common.typing import TAnyDateTime, TDataItem
8
+ from dlt.sources import DltResource
9
+
10
+ from .helpers import GorgiasApi
11
+
12
+
13
+ @dlt.source(name="gorgias", max_table_nesting=0)
14
+ def gorgias_source(
15
+ domain: str = dlt.secrets.value,
16
+ email: str = dlt.config.value,
17
+ api_key: str = dlt.secrets.value,
18
+ start_date: TAnyDateTime = "2024-06-15",
19
+ end_date: TAnyDateTime = None,
20
+ ) -> Iterable[DltResource]:
21
+ """
22
+ The source for the Gorgias pipeline. Available resources include tickets, users, and conversations.
23
+
24
+ Args:
25
+ domain: The domain of your Gorgias account.
26
+ email: The email associated with your Gorgias account.
27
+ api_key: The API key for accessing the Gorgias API.
28
+ items_per_page: The max number of items to fetch per page. Defaults to 100.
29
+
30
+ Returns:
31
+ Iterable[DltResource]: A list of DltResource objects representing the data resources.
32
+ """
33
+
34
+ client = GorgiasApi(domain, email, api_key)
35
+
36
+ start_date_obj = ensure_pendulum_datetime(start_date)
37
+ end_date_obj = ensure_pendulum_datetime(end_date) if end_date else None
38
+
39
+ @dlt.resource(
40
+ primary_key="id",
41
+ write_disposition="merge",
42
+ columns={
43
+ "id": {
44
+ "data_type": "bigint",
45
+ "nullable": False,
46
+ "primary_key": True,
47
+ "description": "ID of the user.",
48
+ },
49
+ "external_id": {
50
+ "data_type": "text",
51
+ "nullable": True,
52
+ "description": "External ID of the user in a foreign system.",
53
+ },
54
+ "active": {
55
+ "data_type": "bool",
56
+ "nullable": False,
57
+ "description": "Indicates if the user is active.",
58
+ },
59
+ "email": {
60
+ "data_type": "text",
61
+ "nullable": True,
62
+ "description": "Email address of the user.",
63
+ },
64
+ "name": {
65
+ "data_type": "text",
66
+ "nullable": True,
67
+ "description": "Full name of the user.",
68
+ },
69
+ "firstname": {
70
+ "data_type": "text",
71
+ "nullable": False,
72
+ "description": "First name of the user.",
73
+ },
74
+ "lastname": {
75
+ "data_type": "text",
76
+ "nullable": False,
77
+ "description": "Last name of the user.",
78
+ },
79
+ "language": {
80
+ "data_type": "text",
81
+ "nullable": True,
82
+ "description": "Preferred language of the user.",
83
+ },
84
+ "timezone": {
85
+ "data_type": "text",
86
+ "nullable": True,
87
+ "description": "Time zone of the user.",
88
+ },
89
+ "created_datetime": {
90
+ "data_type": "timestamp",
91
+ "precision": 6,
92
+ "nullable": False,
93
+ "description": "When the user was created.",
94
+ },
95
+ "updated_datetime": {
96
+ "data_type": "timestamp",
97
+ "precision": 6,
98
+ "nullable": False,
99
+ "description": "When the user was last updated.",
100
+ },
101
+ "meta": {
102
+ "data_type": "complex",
103
+ "nullable": True,
104
+ "description": "Meta information associated with the user.",
105
+ },
106
+ "data": {
107
+ "data_type": "complex",
108
+ "nullable": True,
109
+ "description": "Additional data associated with the user.",
110
+ },
111
+ "note": {
112
+ "data_type": "text",
113
+ "nullable": True,
114
+ "description": "Notes about the user.",
115
+ },
116
+ },
117
+ )
118
+ def customers(
119
+ updated_datetime=dlt.sources.incremental("updated_datetime", start_date_obj),
120
+ ) -> Iterable[TDataItem]:
121
+ """
122
+ The resource for customers on your Gorgias domain, supports incremental loading and pagination.
123
+
124
+ Args:
125
+ updated_datetime: The saved state of the last 'updated_datetime' value.
126
+
127
+ Returns:
128
+ Iterable[TDataItem]: A generator of products.
129
+ """
130
+ yield from client.get_pages(
131
+ "customers",
132
+ params={},
133
+ start_date=updated_datetime.start_value,
134
+ end_date=end_date_obj,
135
+ )
136
+
137
+ @dlt.resource(
138
+ primary_key="id",
139
+ write_disposition="merge",
140
+ columns={
141
+ "id": {
142
+ "data_type": "bigint",
143
+ "nullable": False,
144
+ "primary_key": True,
145
+ "description": "Primary identifier for the ticket",
146
+ },
147
+ "uri": {
148
+ "data_type": "text",
149
+ "nullable": False,
150
+ "description": "API endpoint for the ticket",
151
+ },
152
+ "external_id": {
153
+ "data_type": "text",
154
+ "nullable": True,
155
+ "description": "External identifier for the ticket",
156
+ },
157
+ "language": {
158
+ "data_type": "text",
159
+ "nullable": True,
160
+ "description": "Language of the ticket",
161
+ },
162
+ "status": {
163
+ "data_type": "text",
164
+ "nullable": False,
165
+ "description": "Status of the ticket",
166
+ },
167
+ "priority": {
168
+ "data_type": "text",
169
+ "nullable": False,
170
+ "description": "Priority level of the ticket",
171
+ },
172
+ "channel": {
173
+ "data_type": "text",
174
+ "nullable": False,
175
+ "description": "The channel used to initiate the conversation with the customer.",
176
+ },
177
+ "via": {
178
+ "data_type": "text",
179
+ "nullable": False,
180
+ "description": "Method used to create the ticket",
181
+ },
182
+ "from_agent": {
183
+ "data_type": "bool",
184
+ "nullable": False,
185
+ "description": "Indicates if the ticket was created by an agent",
186
+ },
187
+ "customer": {
188
+ "data_type": "complex",
189
+ "nullable": False,
190
+ "description": "The customer linked to the ticket.",
191
+ },
192
+ "assignee_user": {
193
+ "data_type": "complex",
194
+ "nullable": True,
195
+ "description": "User assigned to the ticket",
196
+ },
197
+ "assignee_team": {
198
+ "data_type": "complex",
199
+ "nullable": True,
200
+ "description": "Team assigned to the ticket",
201
+ },
202
+ "subject": {
203
+ "data_type": "text",
204
+ "nullable": True,
205
+ "description": "Subject of the ticket",
206
+ },
207
+ "excerpt": {
208
+ "data_type": "text",
209
+ "nullable": True,
210
+ "description": "Excerpt of the ticket",
211
+ },
212
+ "integrations": {
213
+ "data_type": "complex",
214
+ "nullable": False,
215
+ "description": "Integration information related to the ticket",
216
+ },
217
+ "meta": {
218
+ "data_type": "complex",
219
+ "nullable": True,
220
+ "description": "Meta information related to the ticket",
221
+ },
222
+ "tags": {
223
+ "data_type": "complex",
224
+ "nullable": False,
225
+ "description": "Tags associated with the ticket",
226
+ },
227
+ "messages_count": {
228
+ "data_type": "bigint",
229
+ "nullable": False,
230
+ "description": "Count of messages in the ticket",
231
+ },
232
+ "is_unread": {
233
+ "data_type": "bool",
234
+ "nullable": False,
235
+ "description": "Indicates if the ticket is unread",
236
+ },
237
+ "spam": {
238
+ "data_type": "bool",
239
+ "nullable": False,
240
+ "description": "Indicates if the ticket is marked as spam",
241
+ },
242
+ "created_datetime": {
243
+ "data_type": "timestamp",
244
+ "precision": 6,
245
+ "nullable": False,
246
+ "description": "Creation timestamp of the ticket",
247
+ },
248
+ "opened_datetime": {
249
+ "data_type": "timestamp",
250
+ "precision": 6,
251
+ "nullable": True,
252
+ "description": "Opened timestamp of the ticket",
253
+ },
254
+ "last_received_message_datetime": {
255
+ "data_type": "timestamp",
256
+ "precision": 6,
257
+ "nullable": True,
258
+ "description": "Timestamp of the last received message",
259
+ },
260
+ "last_message_datetime": {
261
+ "data_type": "timestamp",
262
+ "precision": 6,
263
+ "nullable": True,
264
+ "description": "Timestamp of the last message",
265
+ },
266
+ "updated_datetime": {
267
+ "data_type": "timestamp",
268
+ "precision": 6,
269
+ "nullable": False,
270
+ "description": "Last updated timestamp of the ticket",
271
+ },
272
+ "closed_datetime": {
273
+ "data_type": "timestamp",
274
+ "precision": 6,
275
+ "nullable": True,
276
+ "description": "Closed timestamp of the ticket",
277
+ },
278
+ "snooze_datetime": {
279
+ "data_type": "timestamp",
280
+ "precision": 6,
281
+ "nullable": True,
282
+ "description": "Snooze timestamp of the ticket",
283
+ },
284
+ "trashed_datetime": {
285
+ "data_type": "timestamp",
286
+ "precision": 6,
287
+ "nullable": True,
288
+ "description": "Trashed timestamp of the ticket",
289
+ },
290
+ },
291
+ )
292
+ def tickets(
293
+ updated_datetime=dlt.sources.incremental("updated_datetime", start_date_obj),
294
+ ) -> Iterable[TDataItem]:
295
+ """
296
+ The resource for tickets on your Gorgias domain, supports incremental loading and pagination.
297
+
298
+ Args:
299
+ updated_datetime: The saved state of the last 'updated_datetime' value.
300
+
301
+ Returns:
302
+ Iterable[TDataItem]: A generator of products.
303
+ """
304
+ yield from client.get_pages(
305
+ "tickets",
306
+ params={},
307
+ start_date=updated_datetime.start_value,
308
+ end_date=end_date_obj,
309
+ )
310
+
311
+ @dlt.resource(
312
+ primary_key="id",
313
+ write_disposition="merge",
314
+ columns={
315
+ "id": {
316
+ "data_type": "bigint",
317
+ "nullable": False,
318
+ "primary_key": True,
319
+ "description": "Primary identifier for the ticket",
320
+ },
321
+ "uri": {
322
+ "data_type": "text",
323
+ "nullable": False,
324
+ "description": "API endpoint for the ticket",
325
+ },
326
+ "message_id": {
327
+ "data_type": "text",
328
+ "nullable": True,
329
+ "description": "ID of the message on the service that send the message.It can be the ID of an email, a Messenger message, a Facebook comment, etc...",
330
+ },
331
+ "ticket_id": {
332
+ "data_type": "bigint",
333
+ "nullable": True,
334
+ "description": "The ID of the ticket the message is associated with.",
335
+ },
336
+ "external_id": {
337
+ "data_type": "text",
338
+ "nullable": True,
339
+ "description": "External identifier for the ticket",
340
+ },
341
+ "public": {
342
+ "data_type": "bool",
343
+ "nullable": False,
344
+ "description": "Public flag",
345
+ },
346
+ "channel": {
347
+ "data_type": "text",
348
+ "nullable": False,
349
+ "description": "The channel used to initiate the conversation with the customer.",
350
+ },
351
+ "via": {
352
+ "data_type": "text",
353
+ "nullable": False,
354
+ "description": "How the message has been received, or sent from Gorgias.",
355
+ },
356
+ "sender": {
357
+ "data_type": "complex",
358
+ "nullable": False,
359
+ "description": "The person who sent the message. It can be a user or a customer.",
360
+ },
361
+ "integration_id": {
362
+ "data_type": "bigint",
363
+ "nullable": True,
364
+ "description": "ID of the integration that either received or sent the message.",
365
+ },
366
+ "intents": {
367
+ "data_type": "complex",
368
+ "nullable": True,
369
+ "description": "",
370
+ },
371
+ "rule_id": {
372
+ "data_type": "bigint",
373
+ "nullable": True,
374
+ "description": "ID of the rule which sent the message, if any.",
375
+ },
376
+ "from_agent": {
377
+ "data_type": "bool",
378
+ "nullable": True,
379
+ "description": "Whether the message was sent by your company to a customer, or the opposite.",
380
+ },
381
+ "receiver": {
382
+ "data_type": "complex",
383
+ "nullable": True,
384
+ "description": "The primary receiver of the message. It can be a user or a customer. Optional when the source type is 'internal-note'.",
385
+ },
386
+ "subject": {
387
+ "data_type": "text",
388
+ "nullable": True,
389
+ "description": "The subject of the message.",
390
+ },
391
+ "body_text": {
392
+ "data_type": "text",
393
+ "nullable": True,
394
+ "description": "The full text version of the body of the message, if any.",
395
+ },
396
+ "body_html": {
397
+ "data_type": "text",
398
+ "nullable": True,
399
+ "description": "The full HTML version of the body of the message, if any.",
400
+ },
401
+ "stripped_text": {
402
+ "data_type": "text",
403
+ "nullable": True,
404
+ "description": "The text version of the body of the message without email signatures and previous replies.",
405
+ },
406
+ "stripped_html": {
407
+ "data_type": "text",
408
+ "nullable": True,
409
+ "description": "The HTML version of the body of the message without email signatures and previous replies.",
410
+ },
411
+ "stripped_signature": {
412
+ "data_type": "text",
413
+ "nullable": True,
414
+ "description": "",
415
+ },
416
+ "headers": {
417
+ "data_type": "complex",
418
+ "nullable": True,
419
+ "description": "Headers of the message",
420
+ },
421
+ "attachments": {
422
+ "data_type": "complex",
423
+ "nullable": True,
424
+ "description": "A list of files attached to the message.",
425
+ },
426
+ "actions": {
427
+ "data_type": "complex",
428
+ "nullable": True,
429
+ "description": "A list of actions performed on the message.",
430
+ },
431
+ "macros": {
432
+ "data_type": "complex",
433
+ "nullable": True,
434
+ "description": "A list of macros",
435
+ },
436
+ "meta": {
437
+ "data_type": "complex",
438
+ "nullable": True,
439
+ "description": "Message metadata",
440
+ },
441
+ "created_datetime": {
442
+ "data_type": "timestamp",
443
+ "precision": 6,
444
+ "nullable": False,
445
+ "description": "When the message was created.",
446
+ },
447
+ "sent_datetime": {
448
+ "data_type": "timestamp",
449
+ "precision": 6,
450
+ "nullable": True,
451
+ "description": "When the message was sent. If ommited, the message will be sent by Gorgias.",
452
+ },
453
+ "failed_datetime": {
454
+ "data_type": "timestamp",
455
+ "precision": 6,
456
+ "nullable": True,
457
+ "description": "When the message failed to be sent. Messages that couldn't be sent can be resend.",
458
+ },
459
+ "deleted_datetime": {
460
+ "data_type": "timestamp",
461
+ "precision": 6,
462
+ "nullable": True,
463
+ "description": "When the message was deleted.",
464
+ },
465
+ "opened_datetime": {
466
+ "data_type": "timestamp",
467
+ "precision": 6,
468
+ "nullable": True,
469
+ "description": "When the message was opened by the receiver.",
470
+ },
471
+ "last_sending_error": {
472
+ "data_type": "text",
473
+ "nullable": True,
474
+ "description": "Details of the last error encountered when Gorgias attempted to send the message.",
475
+ },
476
+ "is_retriable": {
477
+ "data_type": "bool",
478
+ "nullable": True,
479
+ "description": "Can be retried",
480
+ },
481
+ },
482
+ )
483
+ def ticket_messages(
484
+ updated_datetime=dlt.sources.incremental("updated_datetime", start_date_obj),
485
+ ) -> Iterable[TDataItem]:
486
+ """
487
+ The resource for ticket messages on your Gorgias domain, supports incremental loading and pagination.
488
+
489
+ Args:
490
+ updated_datetime: The saved state of the last 'updated_datetime' value.
491
+
492
+ Returns:
493
+ Iterable[TDataItem]: A generator of products.
494
+ """
495
+ yield from client.get_pages(
496
+ "messages",
497
+ params={"order_by": "created_datetime:desc"},
498
+ start_date=updated_datetime.start_value,
499
+ end_date=end_date_obj,
500
+ )
501
+
502
+ @dlt.resource(
503
+ primary_key="id",
504
+ write_disposition="merge",
505
+ columns={
506
+ "id": {
507
+ "data_type": "bigint",
508
+ "nullable": False,
509
+ "primary_key": True,
510
+ "description": "ID of the satisfaction survey.",
511
+ },
512
+ "body_text": {
513
+ "data_type": "text",
514
+ "nullable": True,
515
+ "description": "Text body of the satisfaction survey.",
516
+ },
517
+ "created_datetime": {
518
+ "data_type": "timestamp",
519
+ "precision": 6,
520
+ "nullable": False,
521
+ "description": "When the satisfaction survey was created.",
522
+ },
523
+ "customer_id": {
524
+ "data_type": "bigint",
525
+ "nullable": False,
526
+ "description": "ID of the customer linked to the survey.",
527
+ },
528
+ "meta": {
529
+ "data_type": "complex",
530
+ "nullable": True,
531
+ "description": "Meta information associated with the survey.",
532
+ },
533
+ "score": {
534
+ "data_type": "double",
535
+ "nullable": True,
536
+ "description": "Score given in the satisfaction survey.",
537
+ },
538
+ "scored_datetime": {
539
+ "data_type": "timestamp",
540
+ "precision": 6,
541
+ "nullable": True,
542
+ "description": "When the score was given.",
543
+ },
544
+ "sent_datetime": {
545
+ "data_type": "timestamp",
546
+ "precision": 6,
547
+ "nullable": True,
548
+ "description": "When the satisfaction survey was sent.",
549
+ },
550
+ "should_send_datetime": {
551
+ "data_type": "timestamp",
552
+ "precision": 6,
553
+ "nullable": True,
554
+ "description": "When the survey should be sent.",
555
+ },
556
+ "ticket_id": {
557
+ "data_type": "bigint",
558
+ "nullable": False,
559
+ "description": "ID of the ticket linked to the survey.",
560
+ },
561
+ "uri": {
562
+ "data_type": "text",
563
+ "nullable": False,
564
+ "description": "URI of the satisfaction survey.",
565
+ },
566
+ },
567
+ )
568
+ def satisfaction_surveys(
569
+ updated_datetime=dlt.sources.incremental("updated_datetime", start_date_obj),
570
+ ) -> Iterable[TDataItem]:
571
+ """
572
+ The resource for satisfaction surveys on your Gorgias domain, supports incremental loading and pagination.
573
+
574
+ Args:
575
+ updated_datetime: The saved state of the last 'updated_datetime' value.
576
+
577
+ Returns:
578
+ Iterable[TDataItem]: A generator of products.
579
+ """
580
+ yield from client.get_pages(
581
+ "satisfaction-surveys",
582
+ params={"order_by": "created_datetime:desc"},
583
+ start_date=updated_datetime.start_value,
584
+ end_date=end_date_obj,
585
+ )
586
+
587
+ return (customers, tickets, ticket_messages, satisfaction_surveys)