stackshift 0.1.2__py3-none-any.whl → 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.
- stackshift/__init__.py +8 -1
- stackshift/client.py +1 -1
- stackshift/mail.py +35 -3
- stackshift/mail_advanced.py +21 -1
- stackshift/mail_campaigns.py +61 -0
- stackshift/{mail_phase7.py → mail_events_webhooks.py} +8 -0
- stackshift/mail_exports.py +30 -0
- stackshift/mail_streams.py +18 -0
- {stackshift-0.1.2.dist-info → stackshift-1.0.0.dist-info}/METADATA +1 -1
- stackshift-1.0.0.dist-info/RECORD +15 -0
- {stackshift-0.1.2.dist-info → stackshift-1.0.0.dist-info}/WHEEL +1 -1
- stackshift-0.1.2.dist-info/RECORD +0 -12
- {stackshift-0.1.2.dist-info → stackshift-1.0.0.dist-info}/top_level.txt +0 -0
stackshift/__init__.py
CHANGED
|
@@ -8,7 +8,10 @@ from .mail import (
|
|
|
8
8
|
MailTemplatesClient,
|
|
9
9
|
)
|
|
10
10
|
from .mail_reputation import MailLimitsClient, MailReputationClient, MailReputationEventsClient
|
|
11
|
-
from .
|
|
11
|
+
from .mail_events_webhooks import MailEventsClient, MailWebhooksClient, verify_webhook_signature
|
|
12
|
+
from .mail_streams import MailStreamsClient
|
|
13
|
+
from .mail_campaigns import MailAudiencesClient, MailCampaignsClient
|
|
14
|
+
from .mail_exports import MailExportsClient
|
|
12
15
|
from .projects import ProjectsClient
|
|
13
16
|
|
|
14
17
|
__all__ = [
|
|
@@ -25,6 +28,10 @@ __all__ = [
|
|
|
25
28
|
"MailReputationEventsClient",
|
|
26
29
|
"MailTemplatesClient",
|
|
27
30
|
"MailWebhooksClient",
|
|
31
|
+
"MailStreamsClient",
|
|
32
|
+
"MailAudiencesClient",
|
|
33
|
+
"MailCampaignsClient",
|
|
34
|
+
"MailExportsClient",
|
|
28
35
|
"ProjectsClient",
|
|
29
36
|
"asset_transform_options",
|
|
30
37
|
"asset_transform_spec",
|
stackshift/client.py
CHANGED
|
@@ -43,7 +43,7 @@ class StackShift:
|
|
|
43
43
|
def _request(self, base_url: str, method: str, path: str, **kwargs: Any) -> Any:
|
|
44
44
|
headers = kwargs.pop("headers", {})
|
|
45
45
|
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
46
|
-
headers["User-Agent"] = "StackShift-Python/0
|
|
46
|
+
headers["User-Agent"] = "StackShift-Python/1.0"
|
|
47
47
|
|
|
48
48
|
response = self.session.request(method, f"{base_url}{path}", headers=headers, **kwargs)
|
|
49
49
|
payload = response.json() if response.content else None
|
stackshift/mail.py
CHANGED
|
@@ -4,8 +4,11 @@ from typing import Any
|
|
|
4
4
|
from urllib.parse import quote
|
|
5
5
|
|
|
6
6
|
from .mail_advanced import MailAnalyticsClient, MailBatchClient, MailInboundClient, MailScheduledClient
|
|
7
|
-
from .
|
|
7
|
+
from .mail_events_webhooks import MailEventsClient, MailWebhooksClient
|
|
8
8
|
from .mail_reputation import MailLimitsClient, MailReputationClient
|
|
9
|
+
from .mail_streams import MailStreamsClient
|
|
10
|
+
from .mail_campaigns import MailAudiencesClient, MailCampaignsClient
|
|
11
|
+
from .mail_exports import MailExportsClient
|
|
9
12
|
|
|
10
13
|
|
|
11
14
|
class MailClient:
|
|
@@ -19,6 +22,10 @@ class MailClient:
|
|
|
19
22
|
self.templates = MailTemplatesClient(client)
|
|
20
23
|
self.events = MailEventsClient(client)
|
|
21
24
|
self.webhooks = MailWebhooksClient(client)
|
|
25
|
+
self.streams = MailStreamsClient(client)
|
|
26
|
+
self.audiences = MailAudiencesClient(client)
|
|
27
|
+
self.campaigns = MailCampaignsClient(client)
|
|
28
|
+
self.exports = MailExportsClient(client)
|
|
22
29
|
self.limits = MailLimitsClient(client)
|
|
23
30
|
self.reputation = MailReputationClient(client)
|
|
24
31
|
self.scheduled = MailScheduledClient(client)
|
|
@@ -39,6 +46,9 @@ class MailClient:
|
|
|
39
46
|
reply_to: str | dict[str, str] | None = None,
|
|
40
47
|
idempotency_key: str | None = None,
|
|
41
48
|
attachments: list[dict[str, Any]] | None = None,
|
|
49
|
+
headers: dict[str, str] | None = None,
|
|
50
|
+
tags: dict[str, str] | None = None,
|
|
51
|
+
stream: str | None = None,
|
|
42
52
|
) -> dict[str, Any]:
|
|
43
53
|
payload = {
|
|
44
54
|
"from": from_,
|
|
@@ -51,6 +61,9 @@ class MailClient:
|
|
|
51
61
|
"text": text,
|
|
52
62
|
"idempotencyKey": idempotency_key,
|
|
53
63
|
"attachments": attachments,
|
|
64
|
+
"headers": headers,
|
|
65
|
+
"tags": tags,
|
|
66
|
+
"stream": stream,
|
|
54
67
|
}
|
|
55
68
|
clean = {key: value for key, value in payload.items() if value is not None}
|
|
56
69
|
return self._client.mail_request("POST", "/mail/send", json=clean)
|
|
@@ -68,6 +81,9 @@ class MailClient:
|
|
|
68
81
|
reply_to: str | dict[str, str] | None = None,
|
|
69
82
|
idempotency_key: str | None = None,
|
|
70
83
|
attachments: list[dict[str, Any]] | None = None,
|
|
84
|
+
headers: dict[str, str] | None = None,
|
|
85
|
+
tags: dict[str, str] | None = None,
|
|
86
|
+
stream: str | None = None,
|
|
71
87
|
) -> dict[str, Any]:
|
|
72
88
|
payload = {
|
|
73
89
|
"template": template,
|
|
@@ -80,6 +96,9 @@ class MailClient:
|
|
|
80
96
|
"data": data,
|
|
81
97
|
"idempotencyKey": idempotency_key,
|
|
82
98
|
"attachments": attachments,
|
|
99
|
+
"headers": headers,
|
|
100
|
+
"tags": tags,
|
|
101
|
+
"stream": stream,
|
|
83
102
|
}
|
|
84
103
|
clean = {key: value for key, value in payload.items() if value is not None}
|
|
85
104
|
return self._client.mail_request("POST", "/mail/send-template", json=clean)
|
|
@@ -162,6 +181,18 @@ class MailTemplatesClient:
|
|
|
162
181
|
clean = {key: value for key, value in payload.items() if value is not None}
|
|
163
182
|
return self._client.mail_request("POST", f"/mail/templates/{quote(template_id)}/preview", json=clean)
|
|
164
183
|
|
|
184
|
+
def diagnostics(
|
|
185
|
+
self,
|
|
186
|
+
template_id: str,
|
|
187
|
+
*,
|
|
188
|
+
data: dict[str, Any] | None = None,
|
|
189
|
+
version_id: str | None = None,
|
|
190
|
+
stream: str | None = None,
|
|
191
|
+
) -> dict[str, Any]:
|
|
192
|
+
payload = {"data": data, "versionId": version_id, "stream": stream}
|
|
193
|
+
clean = {key: value for key, value in payload.items() if value is not None}
|
|
194
|
+
return self._client.mail_request("POST", f"/mail/templates/{quote(template_id)}/diagnostics", json=clean)
|
|
195
|
+
|
|
165
196
|
def test_send(
|
|
166
197
|
self,
|
|
167
198
|
template_id: str,
|
|
@@ -231,8 +262,9 @@ class MailMessagesClient:
|
|
|
231
262
|
def bounces(self, message_id: str) -> dict[str, Any]:
|
|
232
263
|
return self._client.mail_request("GET", f"/mail/messages/{quote(message_id)}/bounces")
|
|
233
264
|
|
|
234
|
-
def timeline(self, message_id: str) -> dict[str, Any]:
|
|
235
|
-
|
|
265
|
+
def timeline(self, message_id: str, *, recipient: str | None = None) -> dict[str, Any]:
|
|
266
|
+
params = {"recipient": recipient} if recipient else None
|
|
267
|
+
return self._client.mail_request("GET", f"/mail/messages/{quote(message_id)}/timeline", params=params)
|
|
236
268
|
|
|
237
269
|
|
|
238
270
|
class MailSuppressionsClient:
|
stackshift/mail_advanced.py
CHANGED
|
@@ -36,11 +36,31 @@ class MailBatchClient:
|
|
|
36
36
|
from_: str | dict[str, str],
|
|
37
37
|
recipients: list[dict[str, Any]],
|
|
38
38
|
version_id: str | None = None,
|
|
39
|
+
headers: dict[str, str] | None = None,
|
|
40
|
+
tags: dict[str, str] | None = None,
|
|
41
|
+
stream: str | None = None,
|
|
39
42
|
) -> dict[str, Any]:
|
|
40
|
-
payload = {
|
|
43
|
+
payload = {
|
|
44
|
+
"template": template,
|
|
45
|
+
"from": from_,
|
|
46
|
+
"recipients": recipients,
|
|
47
|
+
"versionId": version_id,
|
|
48
|
+
"headers": headers,
|
|
49
|
+
"tags": tags,
|
|
50
|
+
"stream": stream,
|
|
51
|
+
}
|
|
41
52
|
clean = {key: value for key, value in payload.items() if value is not None}
|
|
42
53
|
return self._client.mail_request("POST", "/mail/batch-template", json=clean)
|
|
43
54
|
|
|
55
|
+
def list(self) -> dict[str, Any]:
|
|
56
|
+
return self._client.mail_request("GET", "/mail/batches")
|
|
57
|
+
|
|
58
|
+
def get(self, batch_id: str) -> dict[str, Any]:
|
|
59
|
+
return self._client.mail_request("GET", f"/mail/batches/{quote(batch_id)}")
|
|
60
|
+
|
|
61
|
+
def items(self, batch_id: str) -> dict[str, Any]:
|
|
62
|
+
return self._client.mail_request("GET", f"/mail/batches/{quote(batch_id)}/items")
|
|
63
|
+
|
|
44
64
|
|
|
45
65
|
class MailInboundClient:
|
|
46
66
|
def __init__(self, client: Any) -> None:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
from urllib.parse import quote
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class MailAudiencesClient:
|
|
8
|
+
def __init__(self, client: Any) -> None:
|
|
9
|
+
self._client = client
|
|
10
|
+
|
|
11
|
+
def create(self, *, name: str, description: str | None = None) -> dict[str, Any]:
|
|
12
|
+
payload = {"name": name, "description": description}
|
|
13
|
+
return self._client.mail_request("POST", "/mail/audiences", json={key: value for key, value in payload.items() if value is not None})
|
|
14
|
+
|
|
15
|
+
def list(self) -> dict[str, Any]:
|
|
16
|
+
return self._client.mail_request("GET", "/mail/audiences")
|
|
17
|
+
|
|
18
|
+
def get(self, audience_id: str) -> dict[str, Any]:
|
|
19
|
+
return self._client.mail_request("GET", f"/mail/audiences/{quote(audience_id)}")
|
|
20
|
+
|
|
21
|
+
def members(self, audience_id: str) -> dict[str, Any]:
|
|
22
|
+
return self._client.mail_request("GET", f"/mail/audiences/{quote(audience_id)}/members")
|
|
23
|
+
|
|
24
|
+
def import_members(self, audience_id: str, members: list[dict[str, Any]]) -> dict[str, Any]:
|
|
25
|
+
return self._client.mail_request(
|
|
26
|
+
"POST",
|
|
27
|
+
f"/mail/audiences/{quote(audience_id)}/imports",
|
|
28
|
+
json={"members": members},
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MailCampaignsClient:
|
|
33
|
+
def __init__(self, client: Any) -> None:
|
|
34
|
+
self._client = client
|
|
35
|
+
|
|
36
|
+
def create(
|
|
37
|
+
self,
|
|
38
|
+
*,
|
|
39
|
+
name: str,
|
|
40
|
+
audience_id: str,
|
|
41
|
+
template: str,
|
|
42
|
+
from_: str,
|
|
43
|
+
version_id: str | None = None,
|
|
44
|
+
) -> dict[str, Any]:
|
|
45
|
+
payload = {
|
|
46
|
+
"name": name,
|
|
47
|
+
"audienceId": audience_id,
|
|
48
|
+
"template": template,
|
|
49
|
+
"from": from_,
|
|
50
|
+
"versionId": version_id,
|
|
51
|
+
}
|
|
52
|
+
return self._client.mail_request("POST", "/mail/campaigns", json={key: value for key, value in payload.items() if value is not None})
|
|
53
|
+
|
|
54
|
+
def list(self) -> dict[str, Any]:
|
|
55
|
+
return self._client.mail_request("GET", "/mail/campaigns")
|
|
56
|
+
|
|
57
|
+
def get(self, campaign_id: str) -> dict[str, Any]:
|
|
58
|
+
return self._client.mail_request("GET", f"/mail/campaigns/{quote(campaign_id)}")
|
|
59
|
+
|
|
60
|
+
def send(self, campaign_id: str) -> dict[str, Any]:
|
|
61
|
+
return self._client.mail_request("POST", f"/mail/campaigns/{quote(campaign_id)}/send")
|
|
@@ -100,6 +100,14 @@ class MailWebhooksClient:
|
|
|
100
100
|
def retry_delivery(self, delivery_id: str) -> dict[str, Any]:
|
|
101
101
|
return self._client.mail_request("POST", f"/mail/webhook-deliveries/{quote(delivery_id)}/retry")
|
|
102
102
|
|
|
103
|
+
def replay(self, webhook_id: str, *, event_ids: list[str], idempotency_key: str) -> dict[str, Any]:
|
|
104
|
+
return self._client.mail_request(
|
|
105
|
+
"POST",
|
|
106
|
+
f"/mail/webhooks/{quote(webhook_id)}/replay",
|
|
107
|
+
headers={"Idempotency-Key": idempotency_key},
|
|
108
|
+
json={"eventIds": event_ids},
|
|
109
|
+
)
|
|
110
|
+
|
|
103
111
|
def verify_signature(
|
|
104
112
|
self,
|
|
105
113
|
*,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any
|
|
5
|
+
from urllib.parse import quote
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MailExportsClient:
|
|
9
|
+
def __init__(self, client: Any) -> None:
|
|
10
|
+
self._client = client
|
|
11
|
+
|
|
12
|
+
def create(self, *, from_: datetime | None = None, to: datetime | None = None) -> dict[str, Any]:
|
|
13
|
+
payload = {
|
|
14
|
+
"kind": "recipient_delivery",
|
|
15
|
+
"format": "jsonl",
|
|
16
|
+
"from": from_.isoformat() if from_ else None,
|
|
17
|
+
"to": to.isoformat() if to else None,
|
|
18
|
+
}
|
|
19
|
+
return self._client.mail_request(
|
|
20
|
+
"POST", "/mail/exports", json={key: value for key, value in payload.items() if value is not None}
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
def list(self) -> dict[str, Any]:
|
|
24
|
+
return self._client.mail_request("GET", "/mail/exports")
|
|
25
|
+
|
|
26
|
+
def get(self, export_id: str) -> dict[str, Any]:
|
|
27
|
+
return self._client.mail_request("GET", f"/mail/exports/{quote(export_id)}")
|
|
28
|
+
|
|
29
|
+
def download_path(self, export_id: str) -> str:
|
|
30
|
+
return f"/mail/exports/{quote(export_id)}/download"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class MailStreamsClient:
|
|
7
|
+
def __init__(self, client: Any) -> None:
|
|
8
|
+
self._client = client
|
|
9
|
+
|
|
10
|
+
def create(self, *, name: str, slug: str, type: str) -> dict[str, Any]:
|
|
11
|
+
return self._client.mail_request(
|
|
12
|
+
"POST",
|
|
13
|
+
"/mail/streams",
|
|
14
|
+
json={"name": name, "slug": slug, "type": type},
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
def list(self) -> dict[str, Any]:
|
|
18
|
+
return self._client.mail_request("GET", "/mail/streams")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
stackshift/__init__.py,sha256=QJxD-b_E7P0_6s04v1GhbyyaXLweNohIZPnwmS-jUAc,1278
|
|
2
|
+
stackshift/assets.py,sha256=qRzL9BNZSneNBc3es_vLsY4_hh_r3zOfdO_rAKQq5LU,22949
|
|
3
|
+
stackshift/client.py,sha256=myLN4B_SsolilJWpdlTZv8xwYnj1q-xOmjcSaF_P0mM,3000
|
|
4
|
+
stackshift/mail.py,sha256=akjk8ATJLl7Wv8b2re9LPL5n2Vjvjnz8HK6yNhP6Vj0,14863
|
|
5
|
+
stackshift/mail_advanced.py,sha256=e7Z0SCvonNaS36BnEfhioUh9fnZDU2vcIKmqc1Mqmvo,4192
|
|
6
|
+
stackshift/mail_campaigns.py,sha256=-ZQV88gY1PsuKNA4KYcKVqS1To39EOukKu1Is9qRCPU,2198
|
|
7
|
+
stackshift/mail_events_webhooks.py,sha256=iVYz_5DvGaE-Acw5uh_JN7P5LWvgfN-2bLnb_z1CMRU,5712
|
|
8
|
+
stackshift/mail_exports.py,sha256=sbwBbypS1APv2DnunYmyViEjUHP1PMSrM0tVcbxcits,1054
|
|
9
|
+
stackshift/mail_reputation.py,sha256=mPvPkZeqcQc5808PhBK7gYsgf4Fk_U19nRxSsJ60MGU,1112
|
|
10
|
+
stackshift/mail_streams.py,sha256=F7iBzHtWhCFw1cTjwPixNJfCvxdjvsDprZQG2A9-NIs,504
|
|
11
|
+
stackshift/projects.py,sha256=oYWaE7xNRR6OXuPEwJH-oFFeOmDA9ozq6jJY09ANIHA,498
|
|
12
|
+
stackshift-1.0.0.dist-info/METADATA,sha256=zeVp95gxjKNQMXEagLnJU0I1WEUbHCl7kSJmjpRhY5s,152
|
|
13
|
+
stackshift-1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
14
|
+
stackshift-1.0.0.dist-info/top_level.txt,sha256=qe3uWsu_O9mNtq7bIck9Y8rjTIMrH0kzgAlGFDoRGqs,11
|
|
15
|
+
stackshift-1.0.0.dist-info/RECORD,,
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
stackshift/__init__.py,sha256=e5QZUzE6m_195Cvvawyv8p_M18eNkQzW6sBgBn3SlRo,1008
|
|
2
|
-
stackshift/assets.py,sha256=qRzL9BNZSneNBc3es_vLsY4_hh_r3zOfdO_rAKQq5LU,22949
|
|
3
|
-
stackshift/client.py,sha256=AcJivv4VRCQ756MRrxCrLi0Q4in-4np0Re8ceQSTF1Y,3000
|
|
4
|
-
stackshift/mail.py,sha256=vegCniMcWBvHtz_UGAfNfVxFYTety8H3KKFQsWfKZSs,13462
|
|
5
|
-
stackshift/mail_advanced.py,sha256=-lzajXqlrkR8qA4YpRX5Sv3VwcEQITtKfIXbWwjRRQE,3533
|
|
6
|
-
stackshift/mail_phase7.py,sha256=Ud2fyKwt-vpaw7vgEayLw5q9tiDIF-fkfTBaoGJMJBI,5377
|
|
7
|
-
stackshift/mail_reputation.py,sha256=mPvPkZeqcQc5808PhBK7gYsgf4Fk_U19nRxSsJ60MGU,1112
|
|
8
|
-
stackshift/projects.py,sha256=oYWaE7xNRR6OXuPEwJH-oFFeOmDA9ozq6jJY09ANIHA,498
|
|
9
|
-
stackshift-0.1.2.dist-info/METADATA,sha256=GKbdBmBmZWOUs8DTe-amYxZNbplrh7pAlkaRtkBWQ14,152
|
|
10
|
-
stackshift-0.1.2.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
11
|
-
stackshift-0.1.2.dist-info/top_level.txt,sha256=qe3uWsu_O9mNtq7bIck9Y8rjTIMrH0kzgAlGFDoRGqs,11
|
|
12
|
-
stackshift-0.1.2.dist-info/RECORD,,
|
|
File without changes
|