airbyte-agent-mailchimp 0.1.4__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.
- airbyte_agent_mailchimp/__init__.py +217 -0
- airbyte_agent_mailchimp/_vendored/__init__.py +1 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/__init__.py +82 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/auth_strategies.py +1120 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/auth_template.py +135 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/cloud_utils/__init__.py +5 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/cloud_utils/client.py +213 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/connector_model_loader.py +965 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/constants.py +78 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/exceptions.py +23 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/executor/__init__.py +31 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/executor/hosted_executor.py +196 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/executor/local_executor.py +1641 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/executor/models.py +190 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/extensions.py +693 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/__init__.py +37 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/adapters/__init__.py +9 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/adapters/httpx_adapter.py +251 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/config.py +98 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/exceptions.py +119 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/protocols.py +114 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http/response.py +104 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/http_client.py +686 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/introspection.py +262 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/logging/__init__.py +11 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/logging/logger.py +264 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/logging/types.py +92 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/observability/__init__.py +11 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/observability/config.py +179 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/observability/models.py +19 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/observability/redactor.py +81 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/observability/session.py +103 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/performance/__init__.py +6 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/performance/instrumentation.py +57 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/performance/metrics.py +93 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/__init__.py +75 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/base.py +164 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/components.py +239 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/connector.py +120 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/extensions.py +230 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/operations.py +146 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/schema/security.py +223 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/secrets.py +182 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/telemetry/__init__.py +10 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/telemetry/config.py +32 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/telemetry/events.py +59 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/telemetry/tracker.py +155 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/types.py +245 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/utils.py +60 -0
- airbyte_agent_mailchimp/_vendored/connector_sdk/validation.py +822 -0
- airbyte_agent_mailchimp/connector.py +1378 -0
- airbyte_agent_mailchimp/connector_model.py +4749 -0
- airbyte_agent_mailchimp/models.py +956 -0
- airbyte_agent_mailchimp/types.py +164 -0
- airbyte_agent_mailchimp-0.1.4.dist-info/METADATA +119 -0
- airbyte_agent_mailchimp-0.1.4.dist-info/RECORD +57 -0
- airbyte_agent_mailchimp-0.1.4.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,1378 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Mailchimp connector.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Callable, TypeVar, overload
|
|
9
|
+
try:
|
|
10
|
+
from typing import Literal
|
|
11
|
+
except ImportError:
|
|
12
|
+
from typing_extensions import Literal
|
|
13
|
+
|
|
14
|
+
from .connector_model import MailchimpConnectorModel
|
|
15
|
+
from ._vendored.connector_sdk.introspection import describe_entities, generate_tool_description
|
|
16
|
+
from .types import (
|
|
17
|
+
AutomationsListParams,
|
|
18
|
+
CampaignsGetParams,
|
|
19
|
+
CampaignsListParams,
|
|
20
|
+
EmailActivityListParams,
|
|
21
|
+
InterestCategoriesGetParams,
|
|
22
|
+
InterestCategoriesListParams,
|
|
23
|
+
InterestsGetParams,
|
|
24
|
+
InterestsListParams,
|
|
25
|
+
ListMembersGetParams,
|
|
26
|
+
ListMembersListParams,
|
|
27
|
+
ListsGetParams,
|
|
28
|
+
ListsListParams,
|
|
29
|
+
ReportsGetParams,
|
|
30
|
+
ReportsListParams,
|
|
31
|
+
SegmentMembersListParams,
|
|
32
|
+
SegmentsGetParams,
|
|
33
|
+
SegmentsListParams,
|
|
34
|
+
TagsListParams,
|
|
35
|
+
UnsubscribesListParams,
|
|
36
|
+
)
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from .models import MailchimpAuthConfig
|
|
39
|
+
# Import response models and envelope models at runtime
|
|
40
|
+
from .models import (
|
|
41
|
+
MailchimpExecuteResult,
|
|
42
|
+
MailchimpExecuteResultWithMeta,
|
|
43
|
+
CampaignsListResult,
|
|
44
|
+
ListsListResult,
|
|
45
|
+
ListMembersListResult,
|
|
46
|
+
ReportsListResult,
|
|
47
|
+
EmailActivityListResult,
|
|
48
|
+
AutomationsListResult,
|
|
49
|
+
TagsListResult,
|
|
50
|
+
InterestCategoriesListResult,
|
|
51
|
+
InterestsListResult,
|
|
52
|
+
SegmentsListResult,
|
|
53
|
+
SegmentMembersListResult,
|
|
54
|
+
UnsubscribesListResult,
|
|
55
|
+
Automation,
|
|
56
|
+
Campaign,
|
|
57
|
+
EmailActivity,
|
|
58
|
+
Interest,
|
|
59
|
+
InterestCategory,
|
|
60
|
+
List,
|
|
61
|
+
ListMember,
|
|
62
|
+
Report,
|
|
63
|
+
Segment,
|
|
64
|
+
SegmentMember,
|
|
65
|
+
Tag,
|
|
66
|
+
Unsubscribe,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# TypeVar for decorator type preservation
|
|
70
|
+
_F = TypeVar("_F", bound=Callable[..., Any])
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class MailchimpConnector:
|
|
75
|
+
"""
|
|
76
|
+
Type-safe Mailchimp API connector.
|
|
77
|
+
|
|
78
|
+
Auto-generated from OpenAPI specification with full type safety.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
connector_name = "mailchimp"
|
|
82
|
+
connector_version = "1.0.1"
|
|
83
|
+
vendored_sdk_version = "0.1.0" # Version of vendored connector-sdk
|
|
84
|
+
|
|
85
|
+
# Map of (entity, action) -> needs_envelope for envelope wrapping decision
|
|
86
|
+
_ENVELOPE_MAP = {
|
|
87
|
+
("campaigns", "list"): True,
|
|
88
|
+
("campaigns", "get"): None,
|
|
89
|
+
("lists", "list"): True,
|
|
90
|
+
("lists", "get"): None,
|
|
91
|
+
("list_members", "list"): True,
|
|
92
|
+
("list_members", "get"): None,
|
|
93
|
+
("reports", "list"): True,
|
|
94
|
+
("reports", "get"): None,
|
|
95
|
+
("email_activity", "list"): True,
|
|
96
|
+
("automations", "list"): True,
|
|
97
|
+
("tags", "list"): True,
|
|
98
|
+
("interest_categories", "list"): True,
|
|
99
|
+
("interest_categories", "get"): None,
|
|
100
|
+
("interests", "list"): True,
|
|
101
|
+
("interests", "get"): None,
|
|
102
|
+
("segments", "list"): True,
|
|
103
|
+
("segments", "get"): None,
|
|
104
|
+
("segment_members", "list"): True,
|
|
105
|
+
("unsubscribes", "list"): True,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
# Map of (entity, action) -> {python_param_name: api_param_name}
|
|
109
|
+
# Used to convert snake_case TypedDict keys to API parameter names in execute()
|
|
110
|
+
_PARAM_MAP = {
|
|
111
|
+
('campaigns', 'list'): {'count': 'count', 'offset': 'offset', 'type': 'type', 'status': 'status', 'before_send_time': 'before_send_time', 'since_send_time': 'since_send_time', 'before_create_time': 'before_create_time', 'since_create_time': 'since_create_time', 'list_id': 'list_id', 'folder_id': 'folder_id', 'sort_field': 'sort_field', 'sort_dir': 'sort_dir'},
|
|
112
|
+
('campaigns', 'get'): {'campaign_id': 'campaign_id'},
|
|
113
|
+
('lists', 'list'): {'count': 'count', 'offset': 'offset', 'before_date_created': 'before_date_created', 'since_date_created': 'since_date_created', 'before_campaign_last_sent': 'before_campaign_last_sent', 'since_campaign_last_sent': 'since_campaign_last_sent', 'email': 'email', 'sort_field': 'sort_field', 'sort_dir': 'sort_dir'},
|
|
114
|
+
('lists', 'get'): {'list_id': 'list_id'},
|
|
115
|
+
('list_members', 'list'): {'list_id': 'list_id', 'count': 'count', 'offset': 'offset', 'email_type': 'email_type', 'status': 'status', 'since_timestamp_opt': 'since_timestamp_opt', 'before_timestamp_opt': 'before_timestamp_opt', 'since_last_changed': 'since_last_changed', 'before_last_changed': 'before_last_changed', 'unique_email_id': 'unique_email_id', 'vip_only': 'vip_only', 'interest_category_id': 'interest_category_id', 'interest_ids': 'interest_ids', 'interest_match': 'interest_match', 'sort_field': 'sort_field', 'sort_dir': 'sort_dir'},
|
|
116
|
+
('list_members', 'get'): {'list_id': 'list_id', 'subscriber_hash': 'subscriber_hash'},
|
|
117
|
+
('reports', 'list'): {'count': 'count', 'offset': 'offset', 'type': 'type', 'before_send_time': 'before_send_time', 'since_send_time': 'since_send_time'},
|
|
118
|
+
('reports', 'get'): {'campaign_id': 'campaign_id'},
|
|
119
|
+
('email_activity', 'list'): {'campaign_id': 'campaign_id', 'count': 'count', 'offset': 'offset', 'since': 'since'},
|
|
120
|
+
('automations', 'list'): {'count': 'count', 'offset': 'offset', 'before_create_time': 'before_create_time', 'since_create_time': 'since_create_time', 'before_start_time': 'before_start_time', 'since_start_time': 'since_start_time', 'status': 'status'},
|
|
121
|
+
('tags', 'list'): {'list_id': 'list_id', 'name': 'name'},
|
|
122
|
+
('interest_categories', 'list'): {'list_id': 'list_id', 'count': 'count', 'offset': 'offset'},
|
|
123
|
+
('interest_categories', 'get'): {'list_id': 'list_id', 'interest_category_id': 'interest_category_id'},
|
|
124
|
+
('interests', 'list'): {'list_id': 'list_id', 'interest_category_id': 'interest_category_id', 'count': 'count', 'offset': 'offset'},
|
|
125
|
+
('interests', 'get'): {'list_id': 'list_id', 'interest_category_id': 'interest_category_id', 'interest_id': 'interest_id'},
|
|
126
|
+
('segments', 'list'): {'list_id': 'list_id', 'count': 'count', 'offset': 'offset', 'type': 'type', 'since_created_at': 'since_created_at', 'before_created_at': 'before_created_at', 'since_updated_at': 'since_updated_at', 'before_updated_at': 'before_updated_at'},
|
|
127
|
+
('segments', 'get'): {'list_id': 'list_id', 'segment_id': 'segment_id'},
|
|
128
|
+
('segment_members', 'list'): {'list_id': 'list_id', 'segment_id': 'segment_id', 'count': 'count', 'offset': 'offset'},
|
|
129
|
+
('unsubscribes', 'list'): {'campaign_id': 'campaign_id', 'count': 'count', 'offset': 'offset'},
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
def __init__(
|
|
133
|
+
self,
|
|
134
|
+
auth_config: MailchimpAuthConfig | None = None,
|
|
135
|
+
external_user_id: str | None = None,
|
|
136
|
+
airbyte_client_id: str | None = None,
|
|
137
|
+
airbyte_client_secret: str | None = None,
|
|
138
|
+
on_token_refresh: Any | None = None,
|
|
139
|
+
data_center: str | None = None ):
|
|
140
|
+
"""
|
|
141
|
+
Initialize a new mailchimp connector instance.
|
|
142
|
+
|
|
143
|
+
Supports both local and hosted execution modes:
|
|
144
|
+
- Local mode: Provide `auth_config` for direct API calls
|
|
145
|
+
- Hosted mode: Provide `external_user_id`, `airbyte_client_id`, and `airbyte_client_secret` for hosted execution
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
auth_config: Typed authentication configuration (required for local mode)
|
|
149
|
+
external_user_id: External user ID (required for hosted mode)
|
|
150
|
+
airbyte_client_id: Airbyte OAuth client ID (required for hosted mode)
|
|
151
|
+
airbyte_client_secret: Airbyte OAuth client secret (required for hosted mode)
|
|
152
|
+
on_token_refresh: Optional callback for OAuth2 token refresh persistence.
|
|
153
|
+
Called with new_tokens dict when tokens are refreshed. Can be sync or async.
|
|
154
|
+
Example: lambda tokens: save_to_database(tokens) data_center: The data center for your Mailchimp account (e.g., us1, us2, us6)
|
|
155
|
+
Examples:
|
|
156
|
+
# Local mode (direct API calls)
|
|
157
|
+
connector = MailchimpConnector(auth_config=MailchimpAuthConfig(api_key="...", data_center="..."))
|
|
158
|
+
# Hosted mode (executed on Airbyte cloud)
|
|
159
|
+
connector = MailchimpConnector(
|
|
160
|
+
external_user_id="user-123",
|
|
161
|
+
airbyte_client_id="client_abc123",
|
|
162
|
+
airbyte_client_secret="secret_xyz789"
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Local mode with OAuth2 token refresh callback
|
|
166
|
+
def save_tokens(new_tokens: dict) -> None:
|
|
167
|
+
# Persist updated tokens to your storage (file, database, etc.)
|
|
168
|
+
with open("tokens.json", "w") as f:
|
|
169
|
+
json.dump(new_tokens, f)
|
|
170
|
+
|
|
171
|
+
connector = MailchimpConnector(
|
|
172
|
+
auth_config=MailchimpAuthConfig(access_token="...", refresh_token="..."),
|
|
173
|
+
on_token_refresh=save_tokens
|
|
174
|
+
)
|
|
175
|
+
"""
|
|
176
|
+
# Hosted mode: external_user_id, airbyte_client_id, and airbyte_client_secret provided
|
|
177
|
+
if external_user_id and airbyte_client_id and airbyte_client_secret:
|
|
178
|
+
from ._vendored.connector_sdk.executor import HostedExecutor
|
|
179
|
+
self._executor = HostedExecutor(
|
|
180
|
+
external_user_id=external_user_id,
|
|
181
|
+
airbyte_client_id=airbyte_client_id,
|
|
182
|
+
airbyte_client_secret=airbyte_client_secret,
|
|
183
|
+
connector_definition_id=str(MailchimpConnectorModel.id),
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
# Local mode: auth_config required
|
|
187
|
+
if not auth_config:
|
|
188
|
+
raise ValueError(
|
|
189
|
+
"Either provide (external_user_id, airbyte_client_id, airbyte_client_secret) for hosted mode "
|
|
190
|
+
"or auth_config for local mode"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
from ._vendored.connector_sdk.executor import LocalExecutor
|
|
194
|
+
|
|
195
|
+
# Build config_values dict from server variables
|
|
196
|
+
config_values: dict[str, str] = {}
|
|
197
|
+
if data_center:
|
|
198
|
+
config_values["data_center"] = data_center
|
|
199
|
+
|
|
200
|
+
self._executor = LocalExecutor(
|
|
201
|
+
model=MailchimpConnectorModel,
|
|
202
|
+
auth_config=auth_config.model_dump() if auth_config else None,
|
|
203
|
+
config_values=config_values,
|
|
204
|
+
on_token_refresh=on_token_refresh
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Update base_url with server variables if provided
|
|
208
|
+
base_url = self._executor.http_client.base_url
|
|
209
|
+
if data_center:
|
|
210
|
+
base_url = base_url.replace("{data_center}", data_center)
|
|
211
|
+
self._executor.http_client.base_url = base_url
|
|
212
|
+
|
|
213
|
+
# Initialize entity query objects
|
|
214
|
+
self.campaigns = CampaignsQuery(self)
|
|
215
|
+
self.lists = ListsQuery(self)
|
|
216
|
+
self.list_members = ListMembersQuery(self)
|
|
217
|
+
self.reports = ReportsQuery(self)
|
|
218
|
+
self.email_activity = EmailActivityQuery(self)
|
|
219
|
+
self.automations = AutomationsQuery(self)
|
|
220
|
+
self.tags = TagsQuery(self)
|
|
221
|
+
self.interest_categories = InterestCategoriesQuery(self)
|
|
222
|
+
self.interests = InterestsQuery(self)
|
|
223
|
+
self.segments = SegmentsQuery(self)
|
|
224
|
+
self.segment_members = SegmentMembersQuery(self)
|
|
225
|
+
self.unsubscribes = UnsubscribesQuery(self)
|
|
226
|
+
|
|
227
|
+
# ===== TYPED EXECUTE METHOD (Recommended Interface) =====
|
|
228
|
+
|
|
229
|
+
@overload
|
|
230
|
+
async def execute(
|
|
231
|
+
self,
|
|
232
|
+
entity: Literal["campaigns"],
|
|
233
|
+
action: Literal["list"],
|
|
234
|
+
params: "CampaignsListParams"
|
|
235
|
+
) -> "CampaignsListResult": ...
|
|
236
|
+
|
|
237
|
+
@overload
|
|
238
|
+
async def execute(
|
|
239
|
+
self,
|
|
240
|
+
entity: Literal["campaigns"],
|
|
241
|
+
action: Literal["get"],
|
|
242
|
+
params: "CampaignsGetParams"
|
|
243
|
+
) -> "Campaign": ...
|
|
244
|
+
|
|
245
|
+
@overload
|
|
246
|
+
async def execute(
|
|
247
|
+
self,
|
|
248
|
+
entity: Literal["lists"],
|
|
249
|
+
action: Literal["list"],
|
|
250
|
+
params: "ListsListParams"
|
|
251
|
+
) -> "ListsListResult": ...
|
|
252
|
+
|
|
253
|
+
@overload
|
|
254
|
+
async def execute(
|
|
255
|
+
self,
|
|
256
|
+
entity: Literal["lists"],
|
|
257
|
+
action: Literal["get"],
|
|
258
|
+
params: "ListsGetParams"
|
|
259
|
+
) -> "List": ...
|
|
260
|
+
|
|
261
|
+
@overload
|
|
262
|
+
async def execute(
|
|
263
|
+
self,
|
|
264
|
+
entity: Literal["list_members"],
|
|
265
|
+
action: Literal["list"],
|
|
266
|
+
params: "ListMembersListParams"
|
|
267
|
+
) -> "ListMembersListResult": ...
|
|
268
|
+
|
|
269
|
+
@overload
|
|
270
|
+
async def execute(
|
|
271
|
+
self,
|
|
272
|
+
entity: Literal["list_members"],
|
|
273
|
+
action: Literal["get"],
|
|
274
|
+
params: "ListMembersGetParams"
|
|
275
|
+
) -> "ListMember": ...
|
|
276
|
+
|
|
277
|
+
@overload
|
|
278
|
+
async def execute(
|
|
279
|
+
self,
|
|
280
|
+
entity: Literal["reports"],
|
|
281
|
+
action: Literal["list"],
|
|
282
|
+
params: "ReportsListParams"
|
|
283
|
+
) -> "ReportsListResult": ...
|
|
284
|
+
|
|
285
|
+
@overload
|
|
286
|
+
async def execute(
|
|
287
|
+
self,
|
|
288
|
+
entity: Literal["reports"],
|
|
289
|
+
action: Literal["get"],
|
|
290
|
+
params: "ReportsGetParams"
|
|
291
|
+
) -> "Report": ...
|
|
292
|
+
|
|
293
|
+
@overload
|
|
294
|
+
async def execute(
|
|
295
|
+
self,
|
|
296
|
+
entity: Literal["email_activity"],
|
|
297
|
+
action: Literal["list"],
|
|
298
|
+
params: "EmailActivityListParams"
|
|
299
|
+
) -> "EmailActivityListResult": ...
|
|
300
|
+
|
|
301
|
+
@overload
|
|
302
|
+
async def execute(
|
|
303
|
+
self,
|
|
304
|
+
entity: Literal["automations"],
|
|
305
|
+
action: Literal["list"],
|
|
306
|
+
params: "AutomationsListParams"
|
|
307
|
+
) -> "AutomationsListResult": ...
|
|
308
|
+
|
|
309
|
+
@overload
|
|
310
|
+
async def execute(
|
|
311
|
+
self,
|
|
312
|
+
entity: Literal["tags"],
|
|
313
|
+
action: Literal["list"],
|
|
314
|
+
params: "TagsListParams"
|
|
315
|
+
) -> "TagsListResult": ...
|
|
316
|
+
|
|
317
|
+
@overload
|
|
318
|
+
async def execute(
|
|
319
|
+
self,
|
|
320
|
+
entity: Literal["interest_categories"],
|
|
321
|
+
action: Literal["list"],
|
|
322
|
+
params: "InterestCategoriesListParams"
|
|
323
|
+
) -> "InterestCategoriesListResult": ...
|
|
324
|
+
|
|
325
|
+
@overload
|
|
326
|
+
async def execute(
|
|
327
|
+
self,
|
|
328
|
+
entity: Literal["interest_categories"],
|
|
329
|
+
action: Literal["get"],
|
|
330
|
+
params: "InterestCategoriesGetParams"
|
|
331
|
+
) -> "InterestCategory": ...
|
|
332
|
+
|
|
333
|
+
@overload
|
|
334
|
+
async def execute(
|
|
335
|
+
self,
|
|
336
|
+
entity: Literal["interests"],
|
|
337
|
+
action: Literal["list"],
|
|
338
|
+
params: "InterestsListParams"
|
|
339
|
+
) -> "InterestsListResult": ...
|
|
340
|
+
|
|
341
|
+
@overload
|
|
342
|
+
async def execute(
|
|
343
|
+
self,
|
|
344
|
+
entity: Literal["interests"],
|
|
345
|
+
action: Literal["get"],
|
|
346
|
+
params: "InterestsGetParams"
|
|
347
|
+
) -> "Interest": ...
|
|
348
|
+
|
|
349
|
+
@overload
|
|
350
|
+
async def execute(
|
|
351
|
+
self,
|
|
352
|
+
entity: Literal["segments"],
|
|
353
|
+
action: Literal["list"],
|
|
354
|
+
params: "SegmentsListParams"
|
|
355
|
+
) -> "SegmentsListResult": ...
|
|
356
|
+
|
|
357
|
+
@overload
|
|
358
|
+
async def execute(
|
|
359
|
+
self,
|
|
360
|
+
entity: Literal["segments"],
|
|
361
|
+
action: Literal["get"],
|
|
362
|
+
params: "SegmentsGetParams"
|
|
363
|
+
) -> "Segment": ...
|
|
364
|
+
|
|
365
|
+
@overload
|
|
366
|
+
async def execute(
|
|
367
|
+
self,
|
|
368
|
+
entity: Literal["segment_members"],
|
|
369
|
+
action: Literal["list"],
|
|
370
|
+
params: "SegmentMembersListParams"
|
|
371
|
+
) -> "SegmentMembersListResult": ...
|
|
372
|
+
|
|
373
|
+
@overload
|
|
374
|
+
async def execute(
|
|
375
|
+
self,
|
|
376
|
+
entity: Literal["unsubscribes"],
|
|
377
|
+
action: Literal["list"],
|
|
378
|
+
params: "UnsubscribesListParams"
|
|
379
|
+
) -> "UnsubscribesListResult": ...
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
@overload
|
|
383
|
+
async def execute(
|
|
384
|
+
self,
|
|
385
|
+
entity: str,
|
|
386
|
+
action: str,
|
|
387
|
+
params: dict[str, Any]
|
|
388
|
+
) -> MailchimpExecuteResult[Any] | MailchimpExecuteResultWithMeta[Any, Any] | Any: ...
|
|
389
|
+
|
|
390
|
+
async def execute(
|
|
391
|
+
self,
|
|
392
|
+
entity: str,
|
|
393
|
+
action: str,
|
|
394
|
+
params: dict[str, Any] | None = None
|
|
395
|
+
) -> Any:
|
|
396
|
+
"""
|
|
397
|
+
Execute an entity operation with full type safety.
|
|
398
|
+
|
|
399
|
+
This is the recommended interface for blessed connectors as it:
|
|
400
|
+
- Uses the same signature as non-blessed connectors
|
|
401
|
+
- Provides full IDE autocomplete for entity/action/params
|
|
402
|
+
- Makes migration from generic to blessed connectors seamless
|
|
403
|
+
|
|
404
|
+
Args:
|
|
405
|
+
entity: Entity name (e.g., "customers")
|
|
406
|
+
action: Operation action (e.g., "create", "get", "list")
|
|
407
|
+
params: Operation parameters (typed based on entity+action)
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
Typed response based on the operation
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
customer = await connector.execute(
|
|
414
|
+
entity="customers",
|
|
415
|
+
action="get",
|
|
416
|
+
params={"id": "cus_123"}
|
|
417
|
+
)
|
|
418
|
+
"""
|
|
419
|
+
from ._vendored.connector_sdk.executor import ExecutionConfig
|
|
420
|
+
|
|
421
|
+
# Remap parameter names from snake_case (TypedDict keys) to API parameter names
|
|
422
|
+
if params:
|
|
423
|
+
param_map = self._PARAM_MAP.get((entity, action), {})
|
|
424
|
+
if param_map:
|
|
425
|
+
params = {param_map.get(k, k): v for k, v in params.items()}
|
|
426
|
+
|
|
427
|
+
# Use ExecutionConfig for both local and hosted executors
|
|
428
|
+
config = ExecutionConfig(
|
|
429
|
+
entity=entity,
|
|
430
|
+
action=action,
|
|
431
|
+
params=params
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
result = await self._executor.execute(config)
|
|
435
|
+
|
|
436
|
+
if not result.success:
|
|
437
|
+
raise RuntimeError(f"Execution failed: {result.error}")
|
|
438
|
+
|
|
439
|
+
# Check if this operation has extractors configured
|
|
440
|
+
has_extractors = self._ENVELOPE_MAP.get((entity, action), False)
|
|
441
|
+
|
|
442
|
+
if has_extractors:
|
|
443
|
+
# With extractors - return Pydantic envelope with data and meta
|
|
444
|
+
if result.meta is not None:
|
|
445
|
+
return MailchimpExecuteResultWithMeta[Any, Any](
|
|
446
|
+
data=result.data,
|
|
447
|
+
meta=result.meta
|
|
448
|
+
)
|
|
449
|
+
else:
|
|
450
|
+
return MailchimpExecuteResult[Any](data=result.data)
|
|
451
|
+
else:
|
|
452
|
+
# No extractors - return raw response data
|
|
453
|
+
return result.data
|
|
454
|
+
|
|
455
|
+
# ===== INTROSPECTION METHODS =====
|
|
456
|
+
|
|
457
|
+
@classmethod
|
|
458
|
+
def describe(cls, func: _F) -> _F:
|
|
459
|
+
"""
|
|
460
|
+
Decorator that populates a function's docstring with connector capabilities.
|
|
461
|
+
|
|
462
|
+
This class method can be used as a decorator to automatically generate
|
|
463
|
+
comprehensive documentation for AI tool functions.
|
|
464
|
+
|
|
465
|
+
Usage:
|
|
466
|
+
@mcp.tool()
|
|
467
|
+
@MailchimpConnector.describe
|
|
468
|
+
async def execute(entity: str, action: str, params: dict):
|
|
469
|
+
'''Execute operations.'''
|
|
470
|
+
...
|
|
471
|
+
|
|
472
|
+
The decorated function's __doc__ will be updated with:
|
|
473
|
+
- Available entities and their actions
|
|
474
|
+
- Parameter signatures with required (*) and optional (?) markers
|
|
475
|
+
- Response structure documentation
|
|
476
|
+
- Example questions (if available in OpenAPI spec)
|
|
477
|
+
|
|
478
|
+
Args:
|
|
479
|
+
func: The function to decorate
|
|
480
|
+
|
|
481
|
+
Returns:
|
|
482
|
+
The same function with updated __doc__
|
|
483
|
+
"""
|
|
484
|
+
description = generate_tool_description(MailchimpConnectorModel)
|
|
485
|
+
|
|
486
|
+
original_doc = func.__doc__ or ""
|
|
487
|
+
if original_doc.strip():
|
|
488
|
+
func.__doc__ = f"{original_doc.strip()}\n{description}"
|
|
489
|
+
else:
|
|
490
|
+
func.__doc__ = description
|
|
491
|
+
|
|
492
|
+
return func
|
|
493
|
+
|
|
494
|
+
def list_entities(self) -> list[dict[str, Any]]:
|
|
495
|
+
"""
|
|
496
|
+
Get structured data about available entities, actions, and parameters.
|
|
497
|
+
|
|
498
|
+
Returns a list of entity descriptions with:
|
|
499
|
+
- entity_name: Name of the entity (e.g., "contacts", "deals")
|
|
500
|
+
- description: Entity description from the first endpoint
|
|
501
|
+
- available_actions: List of actions (e.g., ["list", "get", "create"])
|
|
502
|
+
- parameters: Dict mapping action -> list of parameter dicts
|
|
503
|
+
|
|
504
|
+
Example:
|
|
505
|
+
entities = connector.list_entities()
|
|
506
|
+
for entity in entities:
|
|
507
|
+
print(f"{entity['entity_name']}: {entity['available_actions']}")
|
|
508
|
+
"""
|
|
509
|
+
return describe_entities(MailchimpConnectorModel)
|
|
510
|
+
|
|
511
|
+
def entity_schema(self, entity: str) -> dict[str, Any] | None:
|
|
512
|
+
"""
|
|
513
|
+
Get the JSON schema for an entity.
|
|
514
|
+
|
|
515
|
+
Args:
|
|
516
|
+
entity: Entity name (e.g., "contacts", "companies")
|
|
517
|
+
|
|
518
|
+
Returns:
|
|
519
|
+
JSON schema dict describing the entity structure, or None if not found.
|
|
520
|
+
|
|
521
|
+
Example:
|
|
522
|
+
schema = connector.entity_schema("contacts")
|
|
523
|
+
if schema:
|
|
524
|
+
print(f"Contact properties: {list(schema.get('properties', {}).keys())}")
|
|
525
|
+
"""
|
|
526
|
+
entity_def = next(
|
|
527
|
+
(e for e in MailchimpConnectorModel.entities if e.name == entity),
|
|
528
|
+
None
|
|
529
|
+
)
|
|
530
|
+
if entity_def is None:
|
|
531
|
+
logging.getLogger(__name__).warning(
|
|
532
|
+
f"Entity '{entity}' not found. Available entities: "
|
|
533
|
+
f"{[e.name for e in MailchimpConnectorModel.entities]}"
|
|
534
|
+
)
|
|
535
|
+
return entity_def.entity_schema if entity_def else None
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
class CampaignsQuery:
|
|
540
|
+
"""
|
|
541
|
+
Query class for Campaigns entity operations.
|
|
542
|
+
"""
|
|
543
|
+
|
|
544
|
+
def __init__(self, connector: MailchimpConnector):
|
|
545
|
+
"""Initialize query with connector reference."""
|
|
546
|
+
self._connector = connector
|
|
547
|
+
|
|
548
|
+
async def list(
|
|
549
|
+
self,
|
|
550
|
+
count: int | None = None,
|
|
551
|
+
offset: int | None = None,
|
|
552
|
+
type: str | None = None,
|
|
553
|
+
status: str | None = None,
|
|
554
|
+
before_send_time: str | None = None,
|
|
555
|
+
since_send_time: str | None = None,
|
|
556
|
+
before_create_time: str | None = None,
|
|
557
|
+
since_create_time: str | None = None,
|
|
558
|
+
list_id: str | None = None,
|
|
559
|
+
folder_id: str | None = None,
|
|
560
|
+
sort_field: str | None = None,
|
|
561
|
+
sort_dir: str | None = None,
|
|
562
|
+
**kwargs
|
|
563
|
+
) -> CampaignsListResult:
|
|
564
|
+
"""
|
|
565
|
+
Get all campaigns in an account
|
|
566
|
+
|
|
567
|
+
Args:
|
|
568
|
+
count: The number of records to return. Default is 10. Maximum is 1000.
|
|
569
|
+
offset: Used for pagination, this is the number of records from a collection to skip.
|
|
570
|
+
type: The campaign type
|
|
571
|
+
status: The status of the campaign
|
|
572
|
+
before_send_time: Restrict the response to campaigns sent before the set time
|
|
573
|
+
since_send_time: Restrict the response to campaigns sent after the set time
|
|
574
|
+
before_create_time: Restrict the response to campaigns created before the set time
|
|
575
|
+
since_create_time: Restrict the response to campaigns created after the set time
|
|
576
|
+
list_id: The unique id for the list
|
|
577
|
+
folder_id: The unique folder id
|
|
578
|
+
sort_field: Returns files sorted by the specified field
|
|
579
|
+
sort_dir: Determines the order direction for sorted results
|
|
580
|
+
**kwargs: Additional parameters
|
|
581
|
+
|
|
582
|
+
Returns:
|
|
583
|
+
CampaignsListResult
|
|
584
|
+
"""
|
|
585
|
+
params = {k: v for k, v in {
|
|
586
|
+
"count": count,
|
|
587
|
+
"offset": offset,
|
|
588
|
+
"type": type,
|
|
589
|
+
"status": status,
|
|
590
|
+
"before_send_time": before_send_time,
|
|
591
|
+
"since_send_time": since_send_time,
|
|
592
|
+
"before_create_time": before_create_time,
|
|
593
|
+
"since_create_time": since_create_time,
|
|
594
|
+
"list_id": list_id,
|
|
595
|
+
"folder_id": folder_id,
|
|
596
|
+
"sort_field": sort_field,
|
|
597
|
+
"sort_dir": sort_dir,
|
|
598
|
+
**kwargs
|
|
599
|
+
}.items() if v is not None}
|
|
600
|
+
|
|
601
|
+
result = await self._connector.execute("campaigns", "list", params)
|
|
602
|
+
# Cast generic envelope to concrete typed result
|
|
603
|
+
return CampaignsListResult(
|
|
604
|
+
data=result.data,
|
|
605
|
+
meta=result.meta
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
async def get(
|
|
611
|
+
self,
|
|
612
|
+
campaign_id: str,
|
|
613
|
+
**kwargs
|
|
614
|
+
) -> Campaign:
|
|
615
|
+
"""
|
|
616
|
+
Get information about a specific campaign
|
|
617
|
+
|
|
618
|
+
Args:
|
|
619
|
+
campaign_id: The unique id for the campaign
|
|
620
|
+
**kwargs: Additional parameters
|
|
621
|
+
|
|
622
|
+
Returns:
|
|
623
|
+
Campaign
|
|
624
|
+
"""
|
|
625
|
+
params = {k: v for k, v in {
|
|
626
|
+
"campaign_id": campaign_id,
|
|
627
|
+
**kwargs
|
|
628
|
+
}.items() if v is not None}
|
|
629
|
+
|
|
630
|
+
result = await self._connector.execute("campaigns", "get", params)
|
|
631
|
+
return result
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
class ListsQuery:
|
|
636
|
+
"""
|
|
637
|
+
Query class for Lists entity operations.
|
|
638
|
+
"""
|
|
639
|
+
|
|
640
|
+
def __init__(self, connector: MailchimpConnector):
|
|
641
|
+
"""Initialize query with connector reference."""
|
|
642
|
+
self._connector = connector
|
|
643
|
+
|
|
644
|
+
async def list(
|
|
645
|
+
self,
|
|
646
|
+
count: int | None = None,
|
|
647
|
+
offset: int | None = None,
|
|
648
|
+
before_date_created: str | None = None,
|
|
649
|
+
since_date_created: str | None = None,
|
|
650
|
+
before_campaign_last_sent: str | None = None,
|
|
651
|
+
since_campaign_last_sent: str | None = None,
|
|
652
|
+
email: str | None = None,
|
|
653
|
+
sort_field: str | None = None,
|
|
654
|
+
sort_dir: str | None = None,
|
|
655
|
+
**kwargs
|
|
656
|
+
) -> ListsListResult:
|
|
657
|
+
"""
|
|
658
|
+
Get information about all lists in the account
|
|
659
|
+
|
|
660
|
+
Args:
|
|
661
|
+
count: The number of records to return
|
|
662
|
+
offset: Used for pagination
|
|
663
|
+
before_date_created: Restrict response to lists created before the set date
|
|
664
|
+
since_date_created: Restrict response to lists created after the set date
|
|
665
|
+
before_campaign_last_sent: Restrict results to lists created before the last campaign send date
|
|
666
|
+
since_campaign_last_sent: Restrict results to lists created after the last campaign send date
|
|
667
|
+
email: Restrict results to lists that include a specific subscriber's email address
|
|
668
|
+
sort_field: Returns files sorted by the specified field
|
|
669
|
+
sort_dir: Determines the order direction for sorted results
|
|
670
|
+
**kwargs: Additional parameters
|
|
671
|
+
|
|
672
|
+
Returns:
|
|
673
|
+
ListsListResult
|
|
674
|
+
"""
|
|
675
|
+
params = {k: v for k, v in {
|
|
676
|
+
"count": count,
|
|
677
|
+
"offset": offset,
|
|
678
|
+
"before_date_created": before_date_created,
|
|
679
|
+
"since_date_created": since_date_created,
|
|
680
|
+
"before_campaign_last_sent": before_campaign_last_sent,
|
|
681
|
+
"since_campaign_last_sent": since_campaign_last_sent,
|
|
682
|
+
"email": email,
|
|
683
|
+
"sort_field": sort_field,
|
|
684
|
+
"sort_dir": sort_dir,
|
|
685
|
+
**kwargs
|
|
686
|
+
}.items() if v is not None}
|
|
687
|
+
|
|
688
|
+
result = await self._connector.execute("lists", "list", params)
|
|
689
|
+
# Cast generic envelope to concrete typed result
|
|
690
|
+
return ListsListResult(
|
|
691
|
+
data=result.data,
|
|
692
|
+
meta=result.meta
|
|
693
|
+
)
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
async def get(
|
|
698
|
+
self,
|
|
699
|
+
list_id: str,
|
|
700
|
+
**kwargs
|
|
701
|
+
) -> List:
|
|
702
|
+
"""
|
|
703
|
+
Get information about a specific list in your Mailchimp account
|
|
704
|
+
|
|
705
|
+
Args:
|
|
706
|
+
list_id: The unique ID for the list
|
|
707
|
+
**kwargs: Additional parameters
|
|
708
|
+
|
|
709
|
+
Returns:
|
|
710
|
+
List
|
|
711
|
+
"""
|
|
712
|
+
params = {k: v for k, v in {
|
|
713
|
+
"list_id": list_id,
|
|
714
|
+
**kwargs
|
|
715
|
+
}.items() if v is not None}
|
|
716
|
+
|
|
717
|
+
result = await self._connector.execute("lists", "get", params)
|
|
718
|
+
return result
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
class ListMembersQuery:
|
|
723
|
+
"""
|
|
724
|
+
Query class for ListMembers entity operations.
|
|
725
|
+
"""
|
|
726
|
+
|
|
727
|
+
def __init__(self, connector: MailchimpConnector):
|
|
728
|
+
"""Initialize query with connector reference."""
|
|
729
|
+
self._connector = connector
|
|
730
|
+
|
|
731
|
+
async def list(
|
|
732
|
+
self,
|
|
733
|
+
list_id: str,
|
|
734
|
+
count: int | None = None,
|
|
735
|
+
offset: int | None = None,
|
|
736
|
+
email_type: str | None = None,
|
|
737
|
+
status: str | None = None,
|
|
738
|
+
since_timestamp_opt: str | None = None,
|
|
739
|
+
before_timestamp_opt: str | None = None,
|
|
740
|
+
since_last_changed: str | None = None,
|
|
741
|
+
before_last_changed: str | None = None,
|
|
742
|
+
unique_email_id: str | None = None,
|
|
743
|
+
vip_only: bool | None = None,
|
|
744
|
+
interest_category_id: str | None = None,
|
|
745
|
+
interest_ids: str | None = None,
|
|
746
|
+
interest_match: str | None = None,
|
|
747
|
+
sort_field: str | None = None,
|
|
748
|
+
sort_dir: str | None = None,
|
|
749
|
+
**kwargs
|
|
750
|
+
) -> ListMembersListResult:
|
|
751
|
+
"""
|
|
752
|
+
Get information about members in a specific Mailchimp list
|
|
753
|
+
|
|
754
|
+
Args:
|
|
755
|
+
list_id: The unique ID for the list
|
|
756
|
+
count: The number of records to return
|
|
757
|
+
offset: Used for pagination
|
|
758
|
+
email_type: The email type
|
|
759
|
+
status: The subscriber's status
|
|
760
|
+
since_timestamp_opt: Restrict results to subscribers who opted-in after the set timeframe
|
|
761
|
+
before_timestamp_opt: Restrict results to subscribers who opted-in before the set timeframe
|
|
762
|
+
since_last_changed: Restrict results to subscribers whose information changed after the set timeframe
|
|
763
|
+
before_last_changed: Restrict results to subscribers whose information changed before the set timeframe
|
|
764
|
+
unique_email_id: A unique identifier for the email address across all Mailchimp lists
|
|
765
|
+
vip_only: A filter to return only the list's VIP members
|
|
766
|
+
interest_category_id: The unique id for the interest category
|
|
767
|
+
interest_ids: Used to filter list members by interests
|
|
768
|
+
interest_match: Used to filter list members by interests
|
|
769
|
+
sort_field: Returns files sorted by the specified field
|
|
770
|
+
sort_dir: Determines the order direction for sorted results
|
|
771
|
+
**kwargs: Additional parameters
|
|
772
|
+
|
|
773
|
+
Returns:
|
|
774
|
+
ListMembersListResult
|
|
775
|
+
"""
|
|
776
|
+
params = {k: v for k, v in {
|
|
777
|
+
"list_id": list_id,
|
|
778
|
+
"count": count,
|
|
779
|
+
"offset": offset,
|
|
780
|
+
"email_type": email_type,
|
|
781
|
+
"status": status,
|
|
782
|
+
"since_timestamp_opt": since_timestamp_opt,
|
|
783
|
+
"before_timestamp_opt": before_timestamp_opt,
|
|
784
|
+
"since_last_changed": since_last_changed,
|
|
785
|
+
"before_last_changed": before_last_changed,
|
|
786
|
+
"unique_email_id": unique_email_id,
|
|
787
|
+
"vip_only": vip_only,
|
|
788
|
+
"interest_category_id": interest_category_id,
|
|
789
|
+
"interest_ids": interest_ids,
|
|
790
|
+
"interest_match": interest_match,
|
|
791
|
+
"sort_field": sort_field,
|
|
792
|
+
"sort_dir": sort_dir,
|
|
793
|
+
**kwargs
|
|
794
|
+
}.items() if v is not None}
|
|
795
|
+
|
|
796
|
+
result = await self._connector.execute("list_members", "list", params)
|
|
797
|
+
# Cast generic envelope to concrete typed result
|
|
798
|
+
return ListMembersListResult(
|
|
799
|
+
data=result.data,
|
|
800
|
+
meta=result.meta
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
async def get(
|
|
806
|
+
self,
|
|
807
|
+
list_id: str,
|
|
808
|
+
subscriber_hash: str,
|
|
809
|
+
**kwargs
|
|
810
|
+
) -> ListMember:
|
|
811
|
+
"""
|
|
812
|
+
Get information about a specific list member
|
|
813
|
+
|
|
814
|
+
Args:
|
|
815
|
+
list_id: The unique ID for the list
|
|
816
|
+
subscriber_hash: The MD5 hash of the lowercase version of the list member's email address
|
|
817
|
+
**kwargs: Additional parameters
|
|
818
|
+
|
|
819
|
+
Returns:
|
|
820
|
+
ListMember
|
|
821
|
+
"""
|
|
822
|
+
params = {k: v for k, v in {
|
|
823
|
+
"list_id": list_id,
|
|
824
|
+
"subscriber_hash": subscriber_hash,
|
|
825
|
+
**kwargs
|
|
826
|
+
}.items() if v is not None}
|
|
827
|
+
|
|
828
|
+
result = await self._connector.execute("list_members", "get", params)
|
|
829
|
+
return result
|
|
830
|
+
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
class ReportsQuery:
|
|
834
|
+
"""
|
|
835
|
+
Query class for Reports entity operations.
|
|
836
|
+
"""
|
|
837
|
+
|
|
838
|
+
def __init__(self, connector: MailchimpConnector):
|
|
839
|
+
"""Initialize query with connector reference."""
|
|
840
|
+
self._connector = connector
|
|
841
|
+
|
|
842
|
+
async def list(
|
|
843
|
+
self,
|
|
844
|
+
count: int | None = None,
|
|
845
|
+
offset: int | None = None,
|
|
846
|
+
type: str | None = None,
|
|
847
|
+
before_send_time: str | None = None,
|
|
848
|
+
since_send_time: str | None = None,
|
|
849
|
+
**kwargs
|
|
850
|
+
) -> ReportsListResult:
|
|
851
|
+
"""
|
|
852
|
+
Get campaign reports
|
|
853
|
+
|
|
854
|
+
Args:
|
|
855
|
+
count: The number of records to return
|
|
856
|
+
offset: Used for pagination
|
|
857
|
+
type: The campaign type
|
|
858
|
+
before_send_time: Restrict the response to campaigns sent before the set time
|
|
859
|
+
since_send_time: Restrict the response to campaigns sent after the set time
|
|
860
|
+
**kwargs: Additional parameters
|
|
861
|
+
|
|
862
|
+
Returns:
|
|
863
|
+
ReportsListResult
|
|
864
|
+
"""
|
|
865
|
+
params = {k: v for k, v in {
|
|
866
|
+
"count": count,
|
|
867
|
+
"offset": offset,
|
|
868
|
+
"type": type,
|
|
869
|
+
"before_send_time": before_send_time,
|
|
870
|
+
"since_send_time": since_send_time,
|
|
871
|
+
**kwargs
|
|
872
|
+
}.items() if v is not None}
|
|
873
|
+
|
|
874
|
+
result = await self._connector.execute("reports", "list", params)
|
|
875
|
+
# Cast generic envelope to concrete typed result
|
|
876
|
+
return ReportsListResult(
|
|
877
|
+
data=result.data,
|
|
878
|
+
meta=result.meta
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
|
|
883
|
+
async def get(
|
|
884
|
+
self,
|
|
885
|
+
campaign_id: str,
|
|
886
|
+
**kwargs
|
|
887
|
+
) -> Report:
|
|
888
|
+
"""
|
|
889
|
+
Get report details for a specific sent campaign
|
|
890
|
+
|
|
891
|
+
Args:
|
|
892
|
+
campaign_id: The unique id for the campaign
|
|
893
|
+
**kwargs: Additional parameters
|
|
894
|
+
|
|
895
|
+
Returns:
|
|
896
|
+
Report
|
|
897
|
+
"""
|
|
898
|
+
params = {k: v for k, v in {
|
|
899
|
+
"campaign_id": campaign_id,
|
|
900
|
+
**kwargs
|
|
901
|
+
}.items() if v is not None}
|
|
902
|
+
|
|
903
|
+
result = await self._connector.execute("reports", "get", params)
|
|
904
|
+
return result
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
class EmailActivityQuery:
|
|
909
|
+
"""
|
|
910
|
+
Query class for EmailActivity entity operations.
|
|
911
|
+
"""
|
|
912
|
+
|
|
913
|
+
def __init__(self, connector: MailchimpConnector):
|
|
914
|
+
"""Initialize query with connector reference."""
|
|
915
|
+
self._connector = connector
|
|
916
|
+
|
|
917
|
+
async def list(
|
|
918
|
+
self,
|
|
919
|
+
campaign_id: str,
|
|
920
|
+
count: int | None = None,
|
|
921
|
+
offset: int | None = None,
|
|
922
|
+
since: str | None = None,
|
|
923
|
+
**kwargs
|
|
924
|
+
) -> EmailActivityListResult:
|
|
925
|
+
"""
|
|
926
|
+
Get a list of member's subscriber activity in a specific campaign
|
|
927
|
+
|
|
928
|
+
Args:
|
|
929
|
+
campaign_id: The unique id for the campaign
|
|
930
|
+
count: The number of records to return
|
|
931
|
+
offset: Used for pagination
|
|
932
|
+
since: Restrict results to email activity events that occur after a specific time
|
|
933
|
+
**kwargs: Additional parameters
|
|
934
|
+
|
|
935
|
+
Returns:
|
|
936
|
+
EmailActivityListResult
|
|
937
|
+
"""
|
|
938
|
+
params = {k: v for k, v in {
|
|
939
|
+
"campaign_id": campaign_id,
|
|
940
|
+
"count": count,
|
|
941
|
+
"offset": offset,
|
|
942
|
+
"since": since,
|
|
943
|
+
**kwargs
|
|
944
|
+
}.items() if v is not None}
|
|
945
|
+
|
|
946
|
+
result = await self._connector.execute("email_activity", "list", params)
|
|
947
|
+
# Cast generic envelope to concrete typed result
|
|
948
|
+
return EmailActivityListResult(
|
|
949
|
+
data=result.data,
|
|
950
|
+
meta=result.meta
|
|
951
|
+
)
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
class AutomationsQuery:
|
|
956
|
+
"""
|
|
957
|
+
Query class for Automations entity operations.
|
|
958
|
+
"""
|
|
959
|
+
|
|
960
|
+
def __init__(self, connector: MailchimpConnector):
|
|
961
|
+
"""Initialize query with connector reference."""
|
|
962
|
+
self._connector = connector
|
|
963
|
+
|
|
964
|
+
async def list(
|
|
965
|
+
self,
|
|
966
|
+
count: int | None = None,
|
|
967
|
+
offset: int | None = None,
|
|
968
|
+
before_create_time: str | None = None,
|
|
969
|
+
since_create_time: str | None = None,
|
|
970
|
+
before_start_time: str | None = None,
|
|
971
|
+
since_start_time: str | None = None,
|
|
972
|
+
status: str | None = None,
|
|
973
|
+
**kwargs
|
|
974
|
+
) -> AutomationsListResult:
|
|
975
|
+
"""
|
|
976
|
+
Get a summary of an account's classic automations
|
|
977
|
+
|
|
978
|
+
Args:
|
|
979
|
+
count: The number of records to return
|
|
980
|
+
offset: Used for pagination
|
|
981
|
+
before_create_time: Restrict the response to automations created before this time
|
|
982
|
+
since_create_time: Restrict the response to automations created after this time
|
|
983
|
+
before_start_time: Restrict the response to automations started before this time
|
|
984
|
+
since_start_time: Restrict the response to automations started after this time
|
|
985
|
+
status: Restrict the results to automations with the specified status
|
|
986
|
+
**kwargs: Additional parameters
|
|
987
|
+
|
|
988
|
+
Returns:
|
|
989
|
+
AutomationsListResult
|
|
990
|
+
"""
|
|
991
|
+
params = {k: v for k, v in {
|
|
992
|
+
"count": count,
|
|
993
|
+
"offset": offset,
|
|
994
|
+
"before_create_time": before_create_time,
|
|
995
|
+
"since_create_time": since_create_time,
|
|
996
|
+
"before_start_time": before_start_time,
|
|
997
|
+
"since_start_time": since_start_time,
|
|
998
|
+
"status": status,
|
|
999
|
+
**kwargs
|
|
1000
|
+
}.items() if v is not None}
|
|
1001
|
+
|
|
1002
|
+
result = await self._connector.execute("automations", "list", params)
|
|
1003
|
+
# Cast generic envelope to concrete typed result
|
|
1004
|
+
return AutomationsListResult(
|
|
1005
|
+
data=result.data,
|
|
1006
|
+
meta=result.meta
|
|
1007
|
+
)
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
|
|
1011
|
+
class TagsQuery:
|
|
1012
|
+
"""
|
|
1013
|
+
Query class for Tags entity operations.
|
|
1014
|
+
"""
|
|
1015
|
+
|
|
1016
|
+
def __init__(self, connector: MailchimpConnector):
|
|
1017
|
+
"""Initialize query with connector reference."""
|
|
1018
|
+
self._connector = connector
|
|
1019
|
+
|
|
1020
|
+
async def list(
|
|
1021
|
+
self,
|
|
1022
|
+
list_id: str,
|
|
1023
|
+
name: str | None = None,
|
|
1024
|
+
**kwargs
|
|
1025
|
+
) -> TagsListResult:
|
|
1026
|
+
"""
|
|
1027
|
+
Search for tags on a list by name
|
|
1028
|
+
|
|
1029
|
+
Args:
|
|
1030
|
+
list_id: The unique ID for the list
|
|
1031
|
+
name: The search query used to filter tags
|
|
1032
|
+
**kwargs: Additional parameters
|
|
1033
|
+
|
|
1034
|
+
Returns:
|
|
1035
|
+
TagsListResult
|
|
1036
|
+
"""
|
|
1037
|
+
params = {k: v for k, v in {
|
|
1038
|
+
"list_id": list_id,
|
|
1039
|
+
"name": name,
|
|
1040
|
+
**kwargs
|
|
1041
|
+
}.items() if v is not None}
|
|
1042
|
+
|
|
1043
|
+
result = await self._connector.execute("tags", "list", params)
|
|
1044
|
+
# Cast generic envelope to concrete typed result
|
|
1045
|
+
return TagsListResult(
|
|
1046
|
+
data=result.data,
|
|
1047
|
+
meta=result.meta
|
|
1048
|
+
)
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
|
|
1052
|
+
class InterestCategoriesQuery:
|
|
1053
|
+
"""
|
|
1054
|
+
Query class for InterestCategories entity operations.
|
|
1055
|
+
"""
|
|
1056
|
+
|
|
1057
|
+
def __init__(self, connector: MailchimpConnector):
|
|
1058
|
+
"""Initialize query with connector reference."""
|
|
1059
|
+
self._connector = connector
|
|
1060
|
+
|
|
1061
|
+
async def list(
|
|
1062
|
+
self,
|
|
1063
|
+
list_id: str,
|
|
1064
|
+
count: int | None = None,
|
|
1065
|
+
offset: int | None = None,
|
|
1066
|
+
**kwargs
|
|
1067
|
+
) -> InterestCategoriesListResult:
|
|
1068
|
+
"""
|
|
1069
|
+
Get information about a list's interest categories
|
|
1070
|
+
|
|
1071
|
+
Args:
|
|
1072
|
+
list_id: The unique ID for the list
|
|
1073
|
+
count: The number of records to return
|
|
1074
|
+
offset: Used for pagination
|
|
1075
|
+
**kwargs: Additional parameters
|
|
1076
|
+
|
|
1077
|
+
Returns:
|
|
1078
|
+
InterestCategoriesListResult
|
|
1079
|
+
"""
|
|
1080
|
+
params = {k: v for k, v in {
|
|
1081
|
+
"list_id": list_id,
|
|
1082
|
+
"count": count,
|
|
1083
|
+
"offset": offset,
|
|
1084
|
+
**kwargs
|
|
1085
|
+
}.items() if v is not None}
|
|
1086
|
+
|
|
1087
|
+
result = await self._connector.execute("interest_categories", "list", params)
|
|
1088
|
+
# Cast generic envelope to concrete typed result
|
|
1089
|
+
return InterestCategoriesListResult(
|
|
1090
|
+
data=result.data,
|
|
1091
|
+
meta=result.meta
|
|
1092
|
+
)
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
async def get(
|
|
1097
|
+
self,
|
|
1098
|
+
list_id: str,
|
|
1099
|
+
interest_category_id: str,
|
|
1100
|
+
**kwargs
|
|
1101
|
+
) -> InterestCategory:
|
|
1102
|
+
"""
|
|
1103
|
+
Get information about a specific interest category
|
|
1104
|
+
|
|
1105
|
+
Args:
|
|
1106
|
+
list_id: The unique ID for the list
|
|
1107
|
+
interest_category_id: The unique ID for the interest category
|
|
1108
|
+
**kwargs: Additional parameters
|
|
1109
|
+
|
|
1110
|
+
Returns:
|
|
1111
|
+
InterestCategory
|
|
1112
|
+
"""
|
|
1113
|
+
params = {k: v for k, v in {
|
|
1114
|
+
"list_id": list_id,
|
|
1115
|
+
"interest_category_id": interest_category_id,
|
|
1116
|
+
**kwargs
|
|
1117
|
+
}.items() if v is not None}
|
|
1118
|
+
|
|
1119
|
+
result = await self._connector.execute("interest_categories", "get", params)
|
|
1120
|
+
return result
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
|
|
1124
|
+
class InterestsQuery:
|
|
1125
|
+
"""
|
|
1126
|
+
Query class for Interests entity operations.
|
|
1127
|
+
"""
|
|
1128
|
+
|
|
1129
|
+
def __init__(self, connector: MailchimpConnector):
|
|
1130
|
+
"""Initialize query with connector reference."""
|
|
1131
|
+
self._connector = connector
|
|
1132
|
+
|
|
1133
|
+
async def list(
|
|
1134
|
+
self,
|
|
1135
|
+
list_id: str,
|
|
1136
|
+
interest_category_id: str,
|
|
1137
|
+
count: int | None = None,
|
|
1138
|
+
offset: int | None = None,
|
|
1139
|
+
**kwargs
|
|
1140
|
+
) -> InterestsListResult:
|
|
1141
|
+
"""
|
|
1142
|
+
Get a list of this category's interests
|
|
1143
|
+
|
|
1144
|
+
Args:
|
|
1145
|
+
list_id: The unique ID for the list
|
|
1146
|
+
interest_category_id: The unique ID for the interest category
|
|
1147
|
+
count: The number of records to return
|
|
1148
|
+
offset: Used for pagination
|
|
1149
|
+
**kwargs: Additional parameters
|
|
1150
|
+
|
|
1151
|
+
Returns:
|
|
1152
|
+
InterestsListResult
|
|
1153
|
+
"""
|
|
1154
|
+
params = {k: v for k, v in {
|
|
1155
|
+
"list_id": list_id,
|
|
1156
|
+
"interest_category_id": interest_category_id,
|
|
1157
|
+
"count": count,
|
|
1158
|
+
"offset": offset,
|
|
1159
|
+
**kwargs
|
|
1160
|
+
}.items() if v is not None}
|
|
1161
|
+
|
|
1162
|
+
result = await self._connector.execute("interests", "list", params)
|
|
1163
|
+
# Cast generic envelope to concrete typed result
|
|
1164
|
+
return InterestsListResult(
|
|
1165
|
+
data=result.data,
|
|
1166
|
+
meta=result.meta
|
|
1167
|
+
)
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
async def get(
|
|
1172
|
+
self,
|
|
1173
|
+
list_id: str,
|
|
1174
|
+
interest_category_id: str,
|
|
1175
|
+
interest_id: str,
|
|
1176
|
+
**kwargs
|
|
1177
|
+
) -> Interest:
|
|
1178
|
+
"""
|
|
1179
|
+
Get interests or group names for a specific category
|
|
1180
|
+
|
|
1181
|
+
Args:
|
|
1182
|
+
list_id: The unique ID for the list
|
|
1183
|
+
interest_category_id: The unique ID for the interest category
|
|
1184
|
+
interest_id: The specific interest or group name
|
|
1185
|
+
**kwargs: Additional parameters
|
|
1186
|
+
|
|
1187
|
+
Returns:
|
|
1188
|
+
Interest
|
|
1189
|
+
"""
|
|
1190
|
+
params = {k: v for k, v in {
|
|
1191
|
+
"list_id": list_id,
|
|
1192
|
+
"interest_category_id": interest_category_id,
|
|
1193
|
+
"interest_id": interest_id,
|
|
1194
|
+
**kwargs
|
|
1195
|
+
}.items() if v is not None}
|
|
1196
|
+
|
|
1197
|
+
result = await self._connector.execute("interests", "get", params)
|
|
1198
|
+
return result
|
|
1199
|
+
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
class SegmentsQuery:
|
|
1203
|
+
"""
|
|
1204
|
+
Query class for Segments entity operations.
|
|
1205
|
+
"""
|
|
1206
|
+
|
|
1207
|
+
def __init__(self, connector: MailchimpConnector):
|
|
1208
|
+
"""Initialize query with connector reference."""
|
|
1209
|
+
self._connector = connector
|
|
1210
|
+
|
|
1211
|
+
async def list(
|
|
1212
|
+
self,
|
|
1213
|
+
list_id: str,
|
|
1214
|
+
count: int | None = None,
|
|
1215
|
+
offset: int | None = None,
|
|
1216
|
+
type: str | None = None,
|
|
1217
|
+
since_created_at: str | None = None,
|
|
1218
|
+
before_created_at: str | None = None,
|
|
1219
|
+
since_updated_at: str | None = None,
|
|
1220
|
+
before_updated_at: str | None = None,
|
|
1221
|
+
**kwargs
|
|
1222
|
+
) -> SegmentsListResult:
|
|
1223
|
+
"""
|
|
1224
|
+
Get information about all available segments for a specific list
|
|
1225
|
+
|
|
1226
|
+
Args:
|
|
1227
|
+
list_id: The unique ID for the list
|
|
1228
|
+
count: The number of records to return
|
|
1229
|
+
offset: Used for pagination
|
|
1230
|
+
type: Limit results based on segment type
|
|
1231
|
+
since_created_at: Restrict results to segments created after the set time
|
|
1232
|
+
before_created_at: Restrict results to segments created before the set time
|
|
1233
|
+
since_updated_at: Restrict results to segments updated after the set time
|
|
1234
|
+
before_updated_at: Restrict results to segments updated before the set time
|
|
1235
|
+
**kwargs: Additional parameters
|
|
1236
|
+
|
|
1237
|
+
Returns:
|
|
1238
|
+
SegmentsListResult
|
|
1239
|
+
"""
|
|
1240
|
+
params = {k: v for k, v in {
|
|
1241
|
+
"list_id": list_id,
|
|
1242
|
+
"count": count,
|
|
1243
|
+
"offset": offset,
|
|
1244
|
+
"type": type,
|
|
1245
|
+
"since_created_at": since_created_at,
|
|
1246
|
+
"before_created_at": before_created_at,
|
|
1247
|
+
"since_updated_at": since_updated_at,
|
|
1248
|
+
"before_updated_at": before_updated_at,
|
|
1249
|
+
**kwargs
|
|
1250
|
+
}.items() if v is not None}
|
|
1251
|
+
|
|
1252
|
+
result = await self._connector.execute("segments", "list", params)
|
|
1253
|
+
# Cast generic envelope to concrete typed result
|
|
1254
|
+
return SegmentsListResult(
|
|
1255
|
+
data=result.data,
|
|
1256
|
+
meta=result.meta
|
|
1257
|
+
)
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
async def get(
|
|
1262
|
+
self,
|
|
1263
|
+
list_id: str,
|
|
1264
|
+
segment_id: str,
|
|
1265
|
+
**kwargs
|
|
1266
|
+
) -> Segment:
|
|
1267
|
+
"""
|
|
1268
|
+
Get information about a specific segment
|
|
1269
|
+
|
|
1270
|
+
Args:
|
|
1271
|
+
list_id: The unique ID for the list
|
|
1272
|
+
segment_id: The unique id for the segment
|
|
1273
|
+
**kwargs: Additional parameters
|
|
1274
|
+
|
|
1275
|
+
Returns:
|
|
1276
|
+
Segment
|
|
1277
|
+
"""
|
|
1278
|
+
params = {k: v for k, v in {
|
|
1279
|
+
"list_id": list_id,
|
|
1280
|
+
"segment_id": segment_id,
|
|
1281
|
+
**kwargs
|
|
1282
|
+
}.items() if v is not None}
|
|
1283
|
+
|
|
1284
|
+
result = await self._connector.execute("segments", "get", params)
|
|
1285
|
+
return result
|
|
1286
|
+
|
|
1287
|
+
|
|
1288
|
+
|
|
1289
|
+
class SegmentMembersQuery:
|
|
1290
|
+
"""
|
|
1291
|
+
Query class for SegmentMembers entity operations.
|
|
1292
|
+
"""
|
|
1293
|
+
|
|
1294
|
+
def __init__(self, connector: MailchimpConnector):
|
|
1295
|
+
"""Initialize query with connector reference."""
|
|
1296
|
+
self._connector = connector
|
|
1297
|
+
|
|
1298
|
+
async def list(
|
|
1299
|
+
self,
|
|
1300
|
+
list_id: str,
|
|
1301
|
+
segment_id: str,
|
|
1302
|
+
count: int | None = None,
|
|
1303
|
+
offset: int | None = None,
|
|
1304
|
+
**kwargs
|
|
1305
|
+
) -> SegmentMembersListResult:
|
|
1306
|
+
"""
|
|
1307
|
+
Get information about members in a saved segment
|
|
1308
|
+
|
|
1309
|
+
Args:
|
|
1310
|
+
list_id: The unique ID for the list
|
|
1311
|
+
segment_id: The unique id for the segment
|
|
1312
|
+
count: The number of records to return
|
|
1313
|
+
offset: Used for pagination
|
|
1314
|
+
**kwargs: Additional parameters
|
|
1315
|
+
|
|
1316
|
+
Returns:
|
|
1317
|
+
SegmentMembersListResult
|
|
1318
|
+
"""
|
|
1319
|
+
params = {k: v for k, v in {
|
|
1320
|
+
"list_id": list_id,
|
|
1321
|
+
"segment_id": segment_id,
|
|
1322
|
+
"count": count,
|
|
1323
|
+
"offset": offset,
|
|
1324
|
+
**kwargs
|
|
1325
|
+
}.items() if v is not None}
|
|
1326
|
+
|
|
1327
|
+
result = await self._connector.execute("segment_members", "list", params)
|
|
1328
|
+
# Cast generic envelope to concrete typed result
|
|
1329
|
+
return SegmentMembersListResult(
|
|
1330
|
+
data=result.data,
|
|
1331
|
+
meta=result.meta
|
|
1332
|
+
)
|
|
1333
|
+
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
class UnsubscribesQuery:
|
|
1337
|
+
"""
|
|
1338
|
+
Query class for Unsubscribes entity operations.
|
|
1339
|
+
"""
|
|
1340
|
+
|
|
1341
|
+
def __init__(self, connector: MailchimpConnector):
|
|
1342
|
+
"""Initialize query with connector reference."""
|
|
1343
|
+
self._connector = connector
|
|
1344
|
+
|
|
1345
|
+
async def list(
|
|
1346
|
+
self,
|
|
1347
|
+
campaign_id: str,
|
|
1348
|
+
count: int | None = None,
|
|
1349
|
+
offset: int | None = None,
|
|
1350
|
+
**kwargs
|
|
1351
|
+
) -> UnsubscribesListResult:
|
|
1352
|
+
"""
|
|
1353
|
+
Get information about members who have unsubscribed from a specific campaign
|
|
1354
|
+
|
|
1355
|
+
Args:
|
|
1356
|
+
campaign_id: The unique id for the campaign
|
|
1357
|
+
count: The number of records to return
|
|
1358
|
+
offset: Used for pagination
|
|
1359
|
+
**kwargs: Additional parameters
|
|
1360
|
+
|
|
1361
|
+
Returns:
|
|
1362
|
+
UnsubscribesListResult
|
|
1363
|
+
"""
|
|
1364
|
+
params = {k: v for k, v in {
|
|
1365
|
+
"campaign_id": campaign_id,
|
|
1366
|
+
"count": count,
|
|
1367
|
+
"offset": offset,
|
|
1368
|
+
**kwargs
|
|
1369
|
+
}.items() if v is not None}
|
|
1370
|
+
|
|
1371
|
+
result = await self._connector.execute("unsubscribes", "list", params)
|
|
1372
|
+
# Cast generic envelope to concrete typed result
|
|
1373
|
+
return UnsubscribesListResult(
|
|
1374
|
+
data=result.data,
|
|
1375
|
+
meta=result.meta
|
|
1376
|
+
)
|
|
1377
|
+
|
|
1378
|
+
|