diff --git a/.gitignore b/.gitignore index 796b25dc3..5e0a9d100 100644 --- a/.gitignore +++ b/.gitignore @@ -87,6 +87,7 @@ !/macrocli/ !/sbox/ !/quietshrink/ +!/mailchimp/ # Step 5: Inside each software dir, ignore everything (including dotfiles) /gimp/* @@ -181,6 +182,8 @@ /sbox/.* /quietshrink/* /quietshrink/.* +/mailchimp/* +/mailchimp/.* # Step 6: ...except agent-harness/ !/gimp/agent-harness/ @@ -235,6 +238,7 @@ !/macrocli/agent-harness/ !/sbox/agent-harness/ !/quietshrink/agent-harness/ +!/mailchimp/agent-harness/ # Exclude non-gedit demo macros from macrocli (local only) /macrocli/agent-harness/cli_anything/macrocli/macro_definitions/demo/flameshot* diff --git a/README.md b/README.md index b22f197ee..d98b16cd8 100644 --- a/README.md +++ b/README.md @@ -862,6 +862,13 @@ Each application received complete, production-ready CLI interfaces โ€” not demo โœ… 55+ cmds +๐Ÿ“ง Mailchimp +Email Marketing & Automation +cli-anything-mailchimp +Mailchimp Marketing API v3.0 +โœ… 303 cmds + + ๐Ÿ“š Zotero Reference Management cli-anything-zotero @@ -1162,6 +1169,7 @@ cli-anything/ โ”œโ”€โ”€ ๐ŸŽต audacity/agent-harness/ # Audacity CLI (161 tests) โ”œโ”€โ”€ ๐ŸŒ browser/agent-harness/ # Browser CLI (DOMShell MCP, new) โ”œโ”€โ”€ ๐Ÿ“„ libreoffice/agent-harness/ # LibreOffice CLI (158 tests) +โ”œโ”€โ”€ ๐Ÿ“ง mailchimp/agent-harness/ # Mailchimp Marketing API CLI (303 commands, 36 unit tests) โ”œโ”€โ”€ ๐Ÿ“š zotero/agent-harness/ # Zotero CLI (new, write import support) โ”œโ”€โ”€ ๐Ÿ“ mubu/agent-harness/ # Mubu CLI (96 tests) โ”œโ”€โ”€ ๐Ÿ“น obs-studio/agent-harness/ # OBS Studio CLI (153 tests) diff --git a/mailchimp/agent-harness/MAILCHIMP.md b/mailchimp/agent-harness/MAILCHIMP.md new file mode 100644 index 000000000..106c61682 --- /dev/null +++ b/mailchimp/agent-harness/MAILCHIMP.md @@ -0,0 +1,160 @@ +# MAILCHIMP.md โ€” cli-anything Harness for Mailchimp Marketing API v3.0 + +## Overview + +`cli-anything-mailchimp` makes the [Mailchimp Marketing API v3.0](https://mailchimp.com/developer/marketing/docs/fundamentals/) fully agent-native. Every endpoint from the official Swagger spec is exposed as a typed Click command, with JSON output and REPL mode. + +**303 commands across 30 resource groups**, covering the full Marketing API surface. + +--- + +## Backend + +| Property | Value | +|---|---| +| API base | `https://.api.mailchimp.com/3.0` | +| Auth | HTTP Basic โ€” username `anystring`, password = API key | +| Key format | `-` e.g. `abc123-us8` | +| Spec source | `mailchimp/mailchimp-client-lib-codegen` โ†’ `spec/marketing.json` (Swagger 2.0) | + +**Required env var:** +```bash +export MAILCHIMP_API_KEY=- +``` +No config files. The data-centre prefix (`us8`, `eu2`, etc.) is derived automatically from the API key suffix. + +--- + +## Command Hierarchy + +``` +cli-anything-mailchimp [--json] [--version] +โ”‚ +โ”œโ”€โ”€ ping # GET /ping โ€” health check +โ”œโ”€โ”€ root # GET / โ€” account info +โ”‚ +โ”œโ”€โ”€ lists # 66 operations (audiences, members, merge fields, segments, tags, webhooks) +โ”‚ โ”œโ”€โ”€ list / get / create / update / delete +โ”‚ โ”œโ”€โ”€ list-lists-id-members / get-lists-id-members-id / create-members / ... +โ”‚ โ”œโ”€โ”€ list-merge-fields / create-merge-fields / ... +โ”‚ โ”œโ”€โ”€ list-segments / get-segment-id / create-segments / ... +โ”‚ โ””โ”€โ”€ list-webhooks / get-webhook-id / create-webhooks / ... +โ”‚ +โ”œโ”€โ”€ campaigns # 22 operations +โ”‚ โ”œโ”€โ”€ list / get / create / update / delete +โ”‚ โ”œโ”€โ”€ send / schedule / cancel-send / pause / resume / replicate +โ”‚ โ”œโ”€โ”€ list-content / list-feedback / get-feedback-id / create-feedback +โ”‚ โ””โ”€โ”€ list-send-checklist / create-resend +โ”‚ +โ”œโ”€โ”€ reports # 22 operations โ€” sent campaign analytics +โ”‚ โ”œโ”€โ”€ list / get +โ”‚ โ”œโ”€โ”€ list-abuse-reports / list-click-details / list-domain-performance +โ”‚ โ”œโ”€โ”€ list-email-activity / list-locations / list-open-details +โ”‚ โ””โ”€โ”€ list-sub-reports / list-unsubscribed +โ”‚ +โ”œโ”€โ”€ automations # 18 operations +โ”‚ โ”œโ”€โ”€ list / get / create / update +โ”‚ โ”œโ”€โ”€ pause / start / archive +โ”‚ โ””โ”€โ”€ list-emails / get-email / pause-email / start-email / delete-email +โ”‚ +โ”œโ”€โ”€ ecommerce # 60 operations โ€” stores, orders, products, carts, promo codes +โ”œโ”€โ”€ templates # 6 operations +โ”œโ”€โ”€ template-folders # 5 operations +โ”œโ”€โ”€ campaign-folders # 5 operations +โ”œโ”€โ”€ file-manager # 11 operations โ€” files and folders +โ”œโ”€โ”€ reporting # 12 operations โ€” Facebook/landing-page reporting +โ”œโ”€โ”€ landing-pages # 8 operations +โ”œโ”€โ”€ sms-campaigns # 10 operations +โ”œโ”€โ”€ surveys # 3 operations +โ”œโ”€โ”€ audiences # 4 operations โ€” connected audience management +โ”œโ”€โ”€ batch-webhooks # 5 operations +โ”œโ”€โ”€ batches # 4 operations โ€” bulk API batch operations +โ”œโ”€โ”€ connected-sites # 5 operations +โ”œโ”€โ”€ contacts # 4 operations +โ”œโ”€โ”€ conversations # 4 operations +โ”œโ”€โ”€ customer-journeys # 1 operation +โ”œโ”€โ”€ facebook-ads # 2 operations +โ”œโ”€โ”€ verified-domains # 5 operations +โ”œโ”€โ”€ authorized-apps # 2 operations +โ”œโ”€โ”€ activity-feed # 1 operation +โ”œโ”€โ”€ account-export # 1 operation +โ”œโ”€โ”€ account-exports # 2 operations +โ”œโ”€โ”€ search-campaigns # 1 operation +โ””โ”€โ”€ search-members # 1 operation +``` + +--- + +## Output Strategy + +All commands share a root `--json` flag: + +```bash +cli-anything-mailchimp --json lists list +cli-anything-mailchimp --json campaigns get +``` + +**JSON envelopes** (commands emit the native Mailchimp API response): + +| Endpoint type | Shape | +|---|---| +| List / collection | Native shape: `{"lists":[...], "total_items":N}` / `{"campaigns":[...]}` etc. โ€” resource key matches the API path noun | +| Single resource GET | Raw Mailchimp response object | +| Mutation (POST/PATCH/PUT) | Raw Mailchimp response object | +| DELETE | `{"ok": true, "message": "Deleted."}` | +| Error | `{"ok": false, "message": "...", "data": }` | + +Use the Mailchimp-native field name when piping to `jq` (e.g. `.lists[]`, `.campaigns[]`, `.members[]`). + +Human mode prints compact key-value pairs for single objects and annotated lists for collections. + +Collection commands expose Mailchimp's native `count` and `offset` query parameters where the API supports them. The CLI does not auto-fetch every page by default. + +--- + +## Design Decisions + +1. **Code generation from spec** โ€” 303 commands are auto-generated from Mailchimp's public Swagger 2.0 spec via `_codegen/generate.py`. Generated files are committed so end-users get fast `--help` without downloading the spec. + +2. **Env-var-only auth** โ€” per CLI-Anything convention, no config files. `MAILCHIMP_API_KEY` is the single source of truth. + +3. **Verbatim `repl_skin.py`** โ€” the REPL skin is copied unmodified from `cli-anything-plugin/repl_skin.py` as required by CLI-Anything's contribution rules. + +4. **Path params as positional args** โ€” Mailchimp path parameters (`{list_id}`, `{campaign_id}`, etc.) become required positional Click arguments, keeping commands concise. + +5. **Body as `--data` JSON** โ€” request bodies are passed as `--data '{"key": "value"}'` JSON strings. This avoids generating dozens of per-field flags per command and works naturally for agent use (agents can construct JSON payloads directly). + +6. **Subscriber hash utility** โ€” `cli_anything.mailchimp.core.client.subscriber_hash(email)` computes the MD5 hash Mailchimp uses as a member identifier, matching the Node.js reference implementation. + +--- + +## File Layout + +``` +mailchimp/agent-harness/ +โ”œโ”€โ”€ setup.py +โ”œโ”€โ”€ MAILCHIMP.md โ† this file +โ””โ”€โ”€ cli_anything/mailchimp/ + โ”œโ”€โ”€ __init__.py + โ”œโ”€โ”€ __main__.py + โ”œโ”€โ”€ mailchimp_cli.py โ† Click root + REPL + โ”œโ”€โ”€ README.md + โ”œโ”€โ”€ core/ + โ”‚ โ”œโ”€โ”€ client.py โ† HTTP client, auth, error handling + โ”‚ โ””โ”€โ”€ pagination.py โ† count/offset paginator + โ”œโ”€โ”€ commands/ โ† auto-generated (30 modules) + โ”‚ โ”œโ”€โ”€ __init__.py โ† imports ALL_GROUPS + โ”‚ โ”œโ”€โ”€ lists.py โ† 66 commands + โ”‚ โ”œโ”€โ”€ campaigns.py โ† 22 commands + โ”‚ โ””โ”€โ”€ ... โ† one module per tag + โ”œโ”€โ”€ utils/ + โ”‚ โ”œโ”€โ”€ output.py โ† _out() JSON/human switch + โ”‚ โ””โ”€โ”€ repl_skin.py โ† verbatim copy from cli-anything-plugin/repl_skin.py + โ”œโ”€โ”€ _codegen/ + โ”‚ โ””โ”€โ”€ generate.py โ† spec โ†’ commands/*.py generator + โ”œโ”€โ”€ skills/SKILL.md โ† packaged skill copy + โ””โ”€โ”€ tests/ + โ”œโ”€โ”€ TEST.md + โ”œโ”€โ”€ test_core.py โ† unit tests (no API key) + โ””โ”€โ”€ test_full_e2e.py โ† 9 live tests (gated on API key) +``` diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/README.md b/mailchimp/agent-harness/cli_anything/mailchimp/README.md new file mode 100644 index 000000000..a552b04df --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/README.md @@ -0,0 +1,26 @@ +# cli-anything-mailchimp + +Python CLI harness for the [Mailchimp Marketing API v3.0](https://mailchimp.com/developer/marketing/docs/fundamentals/), built on the [CLI-Anything](https://github.com/HKUDS/CLI-Anything) framework. + +## Install + +```bash +pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=mailchimp/agent-harness +``` + +## Auth + +```bash +export MAILCHIMP_API_KEY=- +``` + +## Usage + +```bash +cli-anything-mailchimp ping +cli-anything-mailchimp --json lists list +cli-anything-mailchimp --json campaigns list --count 10 +cli-anything-mailchimp # interactive REPL +``` + +See `SKILL.md` for full command reference. diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/__init__.py b/mailchimp/agent-harness/cli_anything/mailchimp/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/__init__.py @@ -0,0 +1 @@ + diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/__main__.py b/mailchimp/agent-harness/cli_anything/mailchimp/__main__.py new file mode 100644 index 000000000..793b5c756 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/__main__.py @@ -0,0 +1,3 @@ +from cli_anything.mailchimp.mailchimp_cli import main +if __name__ == "__main__": + main() diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/_codegen/__init__.py b/mailchimp/agent-harness/cli_anything/mailchimp/_codegen/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/_codegen/__init__.py @@ -0,0 +1 @@ + diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/_codegen/generate.py b/mailchimp/agent-harness/cli_anything/mailchimp/_codegen/generate.py new file mode 100644 index 000000000..130a3f202 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/_codegen/generate.py @@ -0,0 +1,429 @@ +""" +Code generator: Mailchimp Swagger 2.0 spec โ†’ Click command modules. + +Usage: + python -m cli_anything.mailchimp._codegen.generate + +Downloads the Mailchimp Marketing API spec and emits one Python module per +tag into cli_anything/mailchimp/commands/. The generated files are committed +to the repository so end-users do not need to run the generator. +""" + +from __future__ import annotations + +import builtins +import json +import keyword +import os +import re +import sys +import textwrap +from collections import defaultdict +from pathlib import Path + +import requests + +SPEC_URL = ( + "https://raw.githubusercontent.com/mailchimp/mailchimp-client-lib-codegen" + "/main/spec/marketing.json" +) + +OUT_DIR = Path(__file__).resolve().parents[1] / "commands" + +# Tags that should be skipped (internal/meta). +_SKIP_TAGS: set[str] = set() + +# Names that must not appear as Python function/param names even if technically +# valid identifiers (builtins + common shadowing traps). +_BUILTIN_NAMES: frozenset[str] = frozenset(dir(builtins)) + + +def _slugify(name: str) -> str: + """Convert camelCase or PascalCase or space-separated to kebab-case.""" + s = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1-\2", name) + s = re.sub(r"([a-z\d])([A-Z])", r"\1-\2", s) + s = s.replace(" ", "-").replace("_", "-").lower() + s = re.sub(r"-+", "-", s).strip("-") + return s + + +def _safe_name(name: str) -> str: + """Convert a string to a safe Python identifier (keywords and builtins get underscore suffix).""" + name = re.sub(r"[^a-zA-Z0-9_]", "_", name) + if name and name[0].isdigit(): + name = "_" + name + if keyword.iskeyword(name) or name in _BUILTIN_NAMES: + name += "_" + return name + + +def _tag_to_module(tag: str) -> str: + return _slugify(tag).replace("-", "_") + + +def _tag_to_group(tag: str) -> str: + return _slugify(tag) + + +def _infer_command_name(method: str, path: str, operation_id: str) -> str: + """Derive a clean command name from the HTTP method and path.""" + # Action endpoints (POST to .../actions/xxx) + action_match = re.search(r"/actions/([^/]+)$", path) + if action_match: + return _slugify(action_match.group(1)) + + # Determine if this is a collection endpoint or single-resource by checking + # whether the path ends with a path parameter. + ends_with_param = bool(re.search(r"\{[^}]+\}$", path)) + + if method == "get": + return "get" if ends_with_param else "list" + elif method == "post": + return "create" + elif method in ("patch", "put"): + return "update" + elif method == "delete": + return "delete" + else: + return _slugify(operation_id) + + +def _dedup_suffix(cmd_name: str, path: str, operation_id: str, count: int) -> str: + """Return a unique suffix for a colliding command name. + + Prefers a slug derived from the operationId over a raw path segment, + because path segments are often path-param shaped ({list_id}) which + produces confusing names like 'create-list-id'. + """ + # Try a meaningful suffix from the operationId (strip the HTTP verb prefix) + op_slug = _slugify(re.sub(r"^(get|post|patch|put|delete)", "", operation_id)) + if op_slug and op_slug != cmd_name: + return f"{cmd_name}-{op_slug}" + + # Fall back to the last non-param path segment + segments = [s for s in path.rstrip("/").split("/") if s and not s.startswith("{")] + if segments: + suffix = _slugify(segments[-1]) + if suffix and suffix != cmd_name: + return f"{cmd_name}-{suffix}" + + return f"{cmd_name}-{count}" + + +def _param_type_to_click(param: dict) -> str: + t = param.get("type", "string") + if t == "integer": + return "int" + if t == "boolean": + return "bool" + return "str" + + +def _click_help_text(description: str) -> str: + """Return a single-line Click help string without truncating useful API context.""" + first_line = description.split("\n")[0] + return " ".join(first_line.replace('"', '\\"').split()) + + +def _collect_params(operation: dict, path: str) -> tuple[list[dict], list[dict], dict | None]: + """Return (path_params, query_params, body_param) from operation.""" + params = operation.get("parameters", []) + path_params = [p for p in params if p.get("in") == "path"] + query_params = [p for p in params if p.get("in") == "query"] + body_params = [p for p in params if p.get("in") == "body"] + body = body_params[0] if body_params else None + return path_params, query_params, body + + +def _generate_command_func( + cmd_name: str, + method: str, + path: str, + operation: dict, + path_params: list, + query_params: list, + body_param: dict | None, +) -> str: + summary = operation.get("summary", "").replace('"', '\\"') + # C1: prefix with _cmd_ so no builtin shadowing (list, get, delete, etc.) + func_name = "_cmd_" + _safe_name(cmd_name.replace("-", "_")) + + lines: list[str] = [] + + group_var = f"{_tag_to_module(operation['tags'][0])}_group" + decorators = [f'@{group_var}.command("{cmd_name}")'] + + # Path params as Click arguments (positional) + for p in path_params: + py_arg = _safe_name(p["name"]).upper() + decorators.append(f'@click.argument("{py_arg}")') + + # Body option + if body_param is not None: + decorators.append( + '@click.option("--data", default=None, ' + 'help="Request body as JSON string.")' + ) + + # I3: All query params (no arbitrary cap); --extra-params escape hatch + for p in query_params: + flag = _slugify(p["name"]) + py_name = _safe_name(p["name"]).lower() + ptype = _param_type_to_click(p) + desc = _click_help_text(p.get("description", "")) + if ptype == "int": + type_clause = "type=int, " + elif ptype == "bool": + type_clause = "type=bool, " + else: + type_clause = "" + decorators.append( + f'@click.option("--{flag}", "{py_name}", default=None, {type_clause}help="{desc}")' + ) + + # Escape hatch for extra/future query params + decorators.append( + '@click.option("--extra-params", default=None, ' + 'help="Extra query params as JSON object, e.g. \'{\\"key\\":\\"val\\"}\'")' + ) + + decorators.append("@click.pass_context") + + for d in decorators: + lines.append(d) + + # Function signature โ€” M4: no module-level USE_JSON import needed + sig_parts = ["ctx"] + for p in path_params: + sig_parts.append(_safe_name(p["name"]).lower()) + if body_param is not None: + sig_parts.append("data") + for p in query_params: + sig_parts.append(_safe_name(p["name"]).lower()) + sig_parts.append("extra_params") + + lines.append(f'def {func_name}({", ".join(sig_parts)}):') + lines.append(f' """{summary}"""') + + lines.append(" from cli_anything.mailchimp.core.client import get_client, MailchimpError") + lines.append(" from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err") + + # Build path with lowercased path params + url_parts = re.sub( + r"\{([^}]+)\}", + lambda m: "{" + _safe_name(m.group(1)).lower() + "}", + path, + ) + lines.append(f' path = f"{url_parts}"') + + # Build query params dict + if query_params: + lines.append(" params = {k: v for k, v in {") + for p in query_params: + py_name = _safe_name(p["name"]).lower() + lines.append(f' "{p["name"]}": {py_name},') + lines.append(" }.items() if v is not None}") + else: + lines.append(" params = {}") + + # Merge --extra-params + lines.append(" if extra_params:") + lines.append(' params.update(_parse_json_option(extra_params, "--extra-params", require_object=True))') + + # Parse body + if body_param is not None: + lines.append(' body = _parse_json_option(data, "--data") if data else None') + + # Make the request + lines.append(" client = get_client()") + lines.append(" try:") + if method == "get": + lines.append(" result = client.get(path, params=params or None)") + elif method == "post": + body_arg = "body" if body_param else "None" + lines.append(f" result = client.post(path, json={body_arg}, params=params or None)") + elif method == "patch": + body_arg = "body" if body_param else "None" + lines.append(f" result = client.patch(path, json={body_arg}, params=params or None)") + elif method == "put": + body_arg = "body" if body_param else "None" + lines.append(f" result = client.put(path, json={body_arg}, params=params or None)") + elif method == "delete": + lines.append(" result = client.delete(path, params=params or None)") + else: + lines.append(" result = client.get(path, params=params or None)") + + lines.append(" except MailchimpError as e:") + lines.append(" _out_err(e.status, e.title, e.detail, e.raw)") + lines.append(" return") + + if method == "delete": + lines.append(' _out_ok("Deleted.")') + else: + lines.append(" _out(result)") + + lines.append("") + return "\n".join(lines) + + +def _generate_module(tag: str, operations: list[tuple[str, str, dict]]) -> str: + """Generate a complete Python module for a given tag.""" + module_name = _tag_to_module(tag) + group_name = _tag_to_group(tag) + group_var = f"{module_name}_group" + + group_decorator = f'@click.group("{group_name}")' + group_signature = f"def {group_var}(ctx):" + if tag.lower() == "ping": + group_decorator = f'@click.group("{group_name}", invoke_without_command=True)' + group_lines = [ + f' """{_slugify(tag)} resource commands."""', + ] + if tag.lower() == "ping": + group_lines.extend( + [ + " if ctx.invoked_subcommand is None:", + " ctx.invoke(_cmd_list_)", + ] + ) + + header_lines = [ + f'"""Commands for the Mailchimp /{group_name} API resource.', + "", + "Auto-generated by cli_anything/mailchimp/_codegen/generate.py.", + "Do not edit manually โ€” re-run the generator to update.", + '"""', + "", + "import json", + "", + "import click", + "", + "", + "def _parse_json_option(value, option_name, require_object=False):", + " try:", + " parsed = json.loads(value)", + " except json.JSONDecodeError as exc:", + " raise click.BadParameter(", + ' f"must be valid JSON ({exc.msg})",', + " param_hint=option_name,", + " ) from exc", + " if require_object and not isinstance(parsed, dict):", + ' raise click.BadParameter("must be a JSON object", param_hint=option_name)', + " return parsed", + "", + "", + group_decorator, + "@click.pass_context", + group_signature, + *group_lines, + "", + "", + ] + header = "\n".join(header_lines) + + body_parts: list[str] = [] + # Track ALL assigned names (base + deduped) to guarantee uniqueness. + assigned: set[str] = set() + + for method, path, operation in sorted(operations, key=lambda x: (x[1], x[0])): + op_id = operation.get("operationId", "") + cmd_name = _infer_command_name(method, path, op_id) + + # I4: De-duplicate using operationId slug; fall back to counter if still collides. + if cmd_name in assigned: + candidate = _dedup_suffix(cmd_name, path, op_id, 2) + counter = 2 + while candidate in assigned: + counter += 1 + candidate = f"{cmd_name}-{counter}" + cmd_name = candidate + + assigned.add(cmd_name) + + operation = dict(operation) + operation.setdefault("tags", [tag]) + + path_params, query_params, body_param = _collect_params(operation, path) + func_code = _generate_command_func( + cmd_name, method, path, operation, path_params, query_params, body_param + ) + body_parts.append(func_code) + if tag.lower() == "campaigns" and cmd_name == "list-campaigns-id-content": + body_parts.append('campaigns_group.add_command(_cmd_list_campaigns_id_content, "list-content")\n') + if tag.lower() == "campaigns" and cmd_name == "list-campaigns-id-send-checklist": + body_parts.append('campaigns_group.add_command(_cmd_list_campaigns_id_send_checklist, "list-send-checklist")\n') + if tag.lower() == "reports" and cmd_name == "list-reports-id-click-details": + body_parts.append('reports_group.add_command(_cmd_list_reports_id_click_details, "list-click-details")\n') + if tag.lower() == "reports" and cmd_name == "list-reports-id-domain-performance": + body_parts.append('reports_group.add_command(_cmd_list_reports_id_domain_performance, "list-domain-performance")\n') + if tag.lower() == "reports" and cmd_name == "list-reports-id-email-activity": + body_parts.append('reports_group.add_command(_cmd_list_reports_id_email_activity, "list-email-activity")\n') + if tag.lower() == "reports" and cmd_name == "list-reports-id-locations": + body_parts.append('reports_group.add_command(_cmd_list_reports_id_locations, "list-locations")\n') + if tag.lower() == "reports" and cmd_name == "list-reports-id-open-details": + body_parts.append('reports_group.add_command(_cmd_list_reports_id_open_details, "list-open-details")\n') + if tag.lower() == "reports" and cmd_name == "list-reports-id-unsubscribed": + body_parts.append('reports_group.add_command(_cmd_list_reports_id_unsubscribed, "list-unsubscribed")\n') + if tag.lower() == "automations" and cmd_name == "list-automations-id-emails": + body_parts.append('automations_group.add_command(_cmd_list_automations_id_emails, "list-emails")\n') + if tag.lower() == "lists" and cmd_name == "create-lists-id-members": + body_parts.append('lists_group.add_command(_cmd_create_lists_id_members, "create-members")\n') + if tag.lower() == "lists" and cmd_name == "list-preview-a-segment": + body_parts.append('lists_group.add_command(_cmd_list_preview_a_segment, "list-lists-id-segments")\n') + + return header + "\n".join(body_parts) + + +def load_spec(url: str = SPEC_URL) -> dict: + print(f"Fetching spec from {url} ...", file=sys.stderr) + resp = requests.get(url, timeout=60) + resp.raise_for_status() + return resp.json() + + +def generate(spec: dict, out_dir: Path = OUT_DIR) -> None: + out_dir.mkdir(parents=True, exist_ok=True) + + by_tag: dict[str, list[tuple[str, str, dict]]] = defaultdict(list) + + for path, path_item in spec.get("paths", {}).items(): + for method, operation in path_item.items(): + if method not in ("get", "post", "patch", "put", "delete"): + continue + if not isinstance(operation, dict): + continue + tags = operation.get("tags", ["misc"]) + tag = tags[0] + if tag in _SKIP_TAGS: + continue + by_tag[tag].append((method, path, operation)) + + generated: list[str] = [] + for tag, operations in sorted(by_tag.items()): + module_name = _tag_to_module(tag) + out_path = out_dir / f"{module_name}.py" + code = _generate_module(tag, operations) + out_path.write_text(code, encoding="utf-8") + generated.append(module_name) + print(f" Generated {out_path.name} ({len(operations)} commands)", file=sys.stderr) + + # Write __init__.py that imports all groups + init_lines = ['"""Auto-generated command groups for cli-anything-mailchimp."""', ""] + for mod in sorted(generated): + group_var = f"{mod}_group" + init_lines.append(f"from cli_anything.mailchimp.commands.{mod} import {group_var}") + init_lines.append("") + init_lines.append("ALL_GROUPS = [") + for mod in sorted(generated): + group_var = f"{mod}_group" + init_lines.append(f" {group_var},") + init_lines.append("]") + init_lines.append("") + + (out_dir / "__init__.py").write_text("\n".join(init_lines), encoding="utf-8") + print(f"\nDone โ€” {len(generated)} modules written to {out_dir}", file=sys.stderr) + + +if __name__ == "__main__": + spec = load_spec() + generate(spec) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/__init__.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/__init__.py new file mode 100644 index 000000000..2cb1ce622 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/__init__.py @@ -0,0 +1,65 @@ +"""Auto-generated command groups for cli-anything-mailchimp.""" + +from cli_anything.mailchimp.commands.account_export import account_export_group +from cli_anything.mailchimp.commands.account_exports import account_exports_group +from cli_anything.mailchimp.commands.activity_feed import activity_feed_group +from cli_anything.mailchimp.commands.audiences import audiences_group +from cli_anything.mailchimp.commands.authorized_apps import authorized_apps_group +from cli_anything.mailchimp.commands.automations import automations_group +from cli_anything.mailchimp.commands.batch_webhooks import batch_webhooks_group +from cli_anything.mailchimp.commands.batches import batches_group +from cli_anything.mailchimp.commands.campaign_folders import campaign_folders_group +from cli_anything.mailchimp.commands.campaigns import campaigns_group +from cli_anything.mailchimp.commands.connected_sites import connected_sites_group +from cli_anything.mailchimp.commands.contacts import contacts_group +from cli_anything.mailchimp.commands.conversations import conversations_group +from cli_anything.mailchimp.commands.customer_journeys import customer_journeys_group +from cli_anything.mailchimp.commands.ecommerce import ecommerce_group +from cli_anything.mailchimp.commands.facebook_ads import facebook_ads_group +from cli_anything.mailchimp.commands.file_manager import file_manager_group +from cli_anything.mailchimp.commands.landing_pages import landing_pages_group +from cli_anything.mailchimp.commands.lists import lists_group +from cli_anything.mailchimp.commands.ping import ping_group +from cli_anything.mailchimp.commands.reporting import reporting_group +from cli_anything.mailchimp.commands.reports import reports_group +from cli_anything.mailchimp.commands.root import root_group +from cli_anything.mailchimp.commands.search_campaigns import search_campaigns_group +from cli_anything.mailchimp.commands.search_members import search_members_group +from cli_anything.mailchimp.commands.sms_campaigns import sms_campaigns_group +from cli_anything.mailchimp.commands.surveys import surveys_group +from cli_anything.mailchimp.commands.template_folders import template_folders_group +from cli_anything.mailchimp.commands.templates import templates_group +from cli_anything.mailchimp.commands.verified_domains import verified_domains_group + +ALL_GROUPS = [ + account_export_group, + account_exports_group, + activity_feed_group, + audiences_group, + authorized_apps_group, + automations_group, + batch_webhooks_group, + batches_group, + campaign_folders_group, + campaigns_group, + connected_sites_group, + contacts_group, + conversations_group, + customer_journeys_group, + ecommerce_group, + facebook_ads_group, + file_manager_group, + landing_pages_group, + lists_group, + ping_group, + reporting_group, + reports_group, + root_group, + search_campaigns_group, + search_members_group, + sms_campaigns_group, + surveys_group, + template_folders_group, + templates_group, + verified_domains_group, +] diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/account_export.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/account_export.py new file mode 100644 index 000000000..724211309 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/account_export.py @@ -0,0 +1,53 @@ +"""Commands for the Mailchimp /account-export API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("account-export") +@click.pass_context +def account_export_group(ctx): + """account-export resource commands.""" + +@account_export_group.command("get") +@click.argument("EXPORT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, export_id, fields, exclude_fields, extra_params): + """Get account export info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/account-exports/{export_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/account_exports.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/account_exports.py new file mode 100644 index 000000000..69e5f0d99 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/account_exports.py @@ -0,0 +1,77 @@ +"""Commands for the Mailchimp /account-exports API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("account-exports") +@click.pass_context +def account_exports_group(ctx): + """account-exports resource commands.""" + +@account_exports_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List account exports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/account-exports" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@account_exports_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add export""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/account-exports" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/activity_feed.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/activity_feed.py new file mode 100644 index 000000000..bf8caeabc --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/activity_feed.py @@ -0,0 +1,52 @@ +"""Commands for the Mailchimp /activity-feed API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("activity-feed") +@click.pass_context +def activity_feed_group(ctx): + """activity-feed resource commands.""" + +@activity_feed_group.command("list") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, count, offset, extra_params): + """Get latest chimp chatter""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/activity-feed/chimp-chatter" + params = {k: v for k, v in { + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/audiences.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/audiences.py new file mode 100644 index 000000000..8ea4fc767 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/audiences.py @@ -0,0 +1,150 @@ +"""Commands for the Mailchimp /audiences API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("audiences") +@click.pass_context +def audiences_group(ctx): + """audiences resource commands.""" + +@audiences_group.command("list") +@click.argument("AUDIENCE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--cursor", "cursor", default=None, help="Paginate through a collection of records by setting the `cursor` parameter to a `next_cursor` attribute returned by a previous request. Default value fetches the first \"page\" of results.") +@click.option("--created-before", "created_before", default=None, help="Restricts the response to contacts created at or before the specified time (inclusive). Uses ISO 8601 format: 2025-04-23T15:41:36+00:00.") +@click.option("--created-since", "created_since", default=None, help="Restricts the response to contacts created after the specified time (exclusive). Uses ISO 8601 format: 2025-04-23T15:41:36+00:00.") +@click.option("--updated-before", "updated_before", default=None, help="Restricts the response to contacts updated at or before the specified time (inclusive). Uses ISO 8601 format: 2025-04-23T15:41:36+00:00.") +@click.option("--updated-since", "updated_since", default=None, help="Restricts the response to contacts updated after the specified time (exclusive). Uses ISO 8601 format: 2025-04-23T15:41:36+00:00.") +@click.option("--sort-field", "sort_field", default=None, help="Specifies the field to sort the returned contacts by.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, audience_id, fields, exclude_fields, count, cursor, created_before, created_since, updated_before, updated_since, sort_field, sort_dir, extra_params): + """Get Contacts""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}/contacts" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "cursor": cursor, + "created_before": created_before, + "created_since": created_since, + "updated_before": updated_before, + "updated_since": updated_since, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@audiences_group.command("create") +@click.argument("AUDIENCE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--merge-field-validation-mode", "merge_field_validation_mode", default=None, help="Defines how merge field validation is handled. When set to `ignore_required_checks`, the API does not raise an error if required merge fields are missing from the request. When set to `strict`, the API enforces validation and returns an error if any required merge field is not provided. If this setting is omitted, `strict` is applied by default.") +@click.option("--data-mode", "data_mode", default=None, help="Indicates the data processing mode. In `historical` mode, contact data changes do not trigger automations or webhooks. In `live mode`, such changes do trigger them.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, audience_id, data, merge_field_validation_mode, data_mode, extra_params): + """Add Contact""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}/contacts" + params = {k: v for k, v in { + "merge_field_validation_mode": merge_field_validation_mode, + "data_mode": data_mode, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@audiences_group.command("get") +@click.argument("AUDIENCE_ID") +@click.argument("CONTACT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, audience_id, contact_id, fields, exclude_fields, extra_params): + """Get Contact""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}/contacts/{contact_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@audiences_group.command("update") +@click.argument("AUDIENCE_ID") +@click.argument("CONTACT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--merge-field-validation-mode", "merge_field_validation_mode", default=None, help="Defines how merge field validation is handled. When set to `ignore_required_checks`, the API does not raise an error if required merge fields are missing from the request. When set to `strict`, the API enforces validation and returns an error if any required merge field is not provided. If this setting is omitted, `strict` is applied by default.") +@click.option("--data-mode", "data_mode", default=None, help="Indicates the data processing mode. In `historical` mode, contact data changes do not trigger automations or webhooks. In `live mode`, such changes do trigger them.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, audience_id, contact_id, data, merge_field_validation_mode, data_mode, extra_params): + """Update Contact""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}/contacts/{contact_id}" + params = {k: v for k, v in { + "merge_field_validation_mode": merge_field_validation_mode, + "data_mode": data_mode, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/authorized_apps.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/authorized_apps.py new file mode 100644 index 000000000..38bb6fd85 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/authorized_apps.py @@ -0,0 +1,81 @@ +"""Commands for the Mailchimp /authorized-apps API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("authorized-apps") +@click.pass_context +def authorized_apps_group(ctx): + """authorized-apps resource commands.""" + +@authorized_apps_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List authorized apps""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/authorized-apps" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@authorized_apps_group.command("get") +@click.argument("APP_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, app_id, fields, exclude_fields, extra_params): + """Get authorized app info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/authorized-apps/{app_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/automations.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/automations.py new file mode 100644 index 000000000..3ca327bcc --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/automations.py @@ -0,0 +1,430 @@ +"""Commands for the Mailchimp /automations API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("automations") +@click.pass_context +def automations_group(ctx): + """automations resource commands.""" + +@automations_group.command("list") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--before-create-time", "before_create_time", default=None, help="Restrict the response to automations created before this time. Uses the ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-create-time", "since_create_time", default=None, help="Restrict the response to automations created after this time. Uses the ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-start-time", "before_start_time", default=None, help="Restrict the response to automations started before this time. Uses the ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-start-time", "since_start_time", default=None, help="Restrict the response to automations started after this time. Uses the ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--status", "status", default=None, help="Restrict the results to automations with the specified status.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, count, offset, fields, exclude_fields, before_create_time, since_create_time, before_start_time, since_start_time, status, extra_params): + """List automations""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations" + params = {k: v for k, v in { + "count": count, + "offset": offset, + "fields": fields, + "exclude_fields": exclude_fields, + "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, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add automation""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("get") +@click.argument("WORKFLOW_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, workflow_id, fields, exclude_fields, extra_params): + """Get automation info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("archive") +@click.argument("WORKFLOW_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_archive(ctx, workflow_id, extra_params): + """Archive automation""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/actions/archive" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("pause-all-emails") +@click.argument("WORKFLOW_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_pause_all_emails(ctx, workflow_id, extra_params): + """Pause automation emails""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/actions/pause-all-emails" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("start-all-emails") +@click.argument("WORKFLOW_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_start_all_emails(ctx, workflow_id, extra_params): + """Start automation emails""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/actions/start-all-emails" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("list-automations-id-emails") +@click.argument("WORKFLOW_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_automations_id_emails(ctx, workflow_id, extra_params): + """List automated emails""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +automations_group.add_command(_cmd_list_automations_id_emails, "list-emails") + +@automations_group.command("delete") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, workflow_id, workflow_email_id, extra_params): + """Delete workflow email""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@automations_group.command("get-automations-id-emails-id") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_automations_id_emails_id(ctx, workflow_id, workflow_email_id, extra_params): + """Get workflow email info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("update") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, workflow_id, workflow_email_id, data, extra_params): + """Update workflow email""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("pause") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_pause(ctx, workflow_id, workflow_email_id, extra_params): + """Pause automated email""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}/actions/pause" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("start") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_start(ctx, workflow_id, workflow_email_id, extra_params): + """Start automated email""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}/actions/start" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("list-automations-id-emails-id-queue") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_automations_id_emails_id_queue(ctx, workflow_id, workflow_email_id, extra_params): + """List automated email subscribers""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}/queue" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("create-automations-id-emails-id-queue") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_automations_id_emails_id_queue(ctx, workflow_id, workflow_email_id, data, extra_params): + """Add subscriber to workflow email""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}/queue" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("get-automations-id-emails-id-queue-id") +@click.argument("WORKFLOW_ID") +@click.argument("WORKFLOW_EMAIL_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_automations_id_emails_id_queue_id(ctx, workflow_id, workflow_email_id, subscriber_hash, extra_params): + """Get automated email subscriber""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/emails/{workflow_email_id}/queue/{subscriber_hash}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("list-automations-id-removed-subscribers") +@click.argument("WORKFLOW_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_automations_id_removed_subscribers(ctx, workflow_id, extra_params): + """List subscribers removed from workflow""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/removed-subscribers" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("create-automations-id-removed-subscribers") +@click.argument("WORKFLOW_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_automations_id_removed_subscribers(ctx, workflow_id, data, extra_params): + """Remove subscriber from workflow""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/removed-subscribers" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@automations_group.command("get-automations-id-removed-subscribers-id") +@click.argument("WORKFLOW_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_automations_id_removed_subscribers_id(ctx, workflow_id, subscriber_hash, extra_params): + """Get subscriber removed from workflow""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/automations/{workflow_id}/removed-subscribers/{subscriber_hash}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/batch_webhooks.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/batch_webhooks.py new file mode 100644 index 000000000..dd1655409 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/batch_webhooks.py @@ -0,0 +1,144 @@ +"""Commands for the Mailchimp /batch-webhooks API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("batch-webhooks") +@click.pass_context +def batch_webhooks_group(ctx): + """batch-webhooks resource commands.""" + +@batch_webhooks_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List batch webhooks""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batch-webhooks" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@batch_webhooks_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add batch webhook""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batch-webhooks" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@batch_webhooks_group.command("delete") +@click.argument("BATCH_WEBHOOK_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, batch_webhook_id, extra_params): + """Delete batch webhook""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batch-webhooks/{batch_webhook_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@batch_webhooks_group.command("get") +@click.argument("BATCH_WEBHOOK_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, batch_webhook_id, fields, exclude_fields, extra_params): + """Get batch webhook info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batch-webhooks/{batch_webhook_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@batch_webhooks_group.command("update") +@click.argument("BATCH_WEBHOOK_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, batch_webhook_id, data, extra_params): + """Update batch webhook""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batch-webhooks/{batch_webhook_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/batches.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/batches.py new file mode 100644 index 000000000..1aa3a7c5b --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/batches.py @@ -0,0 +1,122 @@ +"""Commands for the Mailchimp /batches API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("batches") +@click.pass_context +def batches_group(ctx): + """batches resource commands.""" + +@batches_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List batch requests""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batches" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@batches_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Start batch operation""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batches" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@batches_group.command("delete") +@click.argument("BATCH_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, batch_id, extra_params): + """Delete batch request""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batches/{batch_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@batches_group.command("get") +@click.argument("BATCH_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, batch_id, fields, exclude_fields, extra_params): + """Get batch operation status""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/batches/{batch_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/campaign_folders.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/campaign_folders.py new file mode 100644 index 000000000..74aa12717 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/campaign_folders.py @@ -0,0 +1,144 @@ +"""Commands for the Mailchimp /campaign-folders API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("campaign-folders") +@click.pass_context +def campaign_folders_group(ctx): + """campaign-folders resource commands.""" + +@campaign_folders_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List campaign folders""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaign-folders" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaign_folders_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add campaign folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaign-folders" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaign_folders_group.command("delete") +@click.argument("FOLDER_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, folder_id, extra_params): + """Delete campaign folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaign-folders/{folder_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@campaign_folders_group.command("get") +@click.argument("FOLDER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, folder_id, fields, exclude_fields, extra_params): + """Get campaign folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaign-folders/{folder_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaign_folders_group.command("update") +@click.argument("FOLDER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, folder_id, data, extra_params): + """Update campaign folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaign-folders/{folder_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/campaigns.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/campaigns.py new file mode 100644 index 000000000..68152bc05 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/campaigns.py @@ -0,0 +1,553 @@ +"""Commands for the Mailchimp /campaigns API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("campaigns") +@click.pass_context +def campaigns_group(ctx): + """campaigns resource commands.""" + +@campaigns_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="The campaign type.") +@click.option("--status", "status", default=None, help="The status of the campaign.") +@click.option("--before-send-time", "before_send_time", default=None, help="Restrict the response to campaigns sent before the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-send-time", "since_send_time", default=None, help="Restrict the response to campaigns sent after the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-create-time", "before_create_time", default=None, help="Restrict the response to campaigns created before the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-create-time", "since_create_time", default=None, help="Restrict the response to campaigns created after the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--list-id", "list_id", default=None, help="The unique id for the list.") +@click.option("--folder-id", "folder_id", default=None, help="The unique folder id.") +@click.option("--member-id", "member_id", default=None, help="Retrieve campaigns sent to a particular list member. Member ID is The MD5 hash of the lowercase version of the list memberโ€™s email address.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--include-resend-shortcut-eligibility", "include_resend_shortcut_eligibility", default=None, type=bool, help="Return the `resend_shortcut_eligibility` field in the response, which tells you if the campaign is eligible for the various Campaign Resend Shortcuts offered.") +@click.option("--include-resend-shortcut-usage", "include_resend_shortcut_usage", default=None, type=bool, help="Return the `resend_shortcut_usage` field in the response. This includes information about campaigns related by a shortcut.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, type_, status, before_send_time, since_send_time, before_create_time, since_create_time, list_id, folder_id, member_id, sort_field, sort_dir, include_resend_shortcut_eligibility, include_resend_shortcut_usage, extra_params): + """List campaigns""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "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, + "member_id": member_id, + "sort_field": sort_field, + "sort_dir": sort_dir, + "include_resend_shortcut_eligibility": include_resend_shortcut_eligibility, + "include_resend_shortcut_usage": include_resend_shortcut_usage, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("delete") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, campaign_id, extra_params): + """Delete campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@campaigns_group.command("get") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--include-resend-shortcut-eligibility", "include_resend_shortcut_eligibility", default=None, type=bool, help="Return the `resend_shortcut_eligibility` field in the response, which tells you if the campaign is eligible for the various Campaign Resend Shortcuts offered.") +@click.option("--include-resend-shortcut-usage", "include_resend_shortcut_usage", default=None, type=bool, help="Return the `resend_shortcut_usage` field in the response. This includes information about campaigns related by a shortcut.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, campaign_id, fields, exclude_fields, include_resend_shortcut_eligibility, include_resend_shortcut_usage, extra_params): + """Get campaign info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "include_resend_shortcut_eligibility": include_resend_shortcut_eligibility, + "include_resend_shortcut_usage": include_resend_shortcut_usage, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("update") +@click.argument("CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, campaign_id, data, extra_params): + """Update campaign settings""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("cancel-send") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_cancel_send(ctx, campaign_id, extra_params): + """Cancel campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/cancel-send" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("create-resend") +@click.argument("CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_resend(ctx, campaign_id, data, extra_params): + """Resend campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/create-resend" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("pause") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_pause(ctx, campaign_id, extra_params): + """Pause rss campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/pause" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("replicate") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_replicate(ctx, campaign_id, extra_params): + """Replicate campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/replicate" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("resume") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_resume(ctx, campaign_id, extra_params): + """Resume rss campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/resume" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("schedule") +@click.argument("CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_schedule(ctx, campaign_id, data, extra_params): + """Schedule campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/schedule" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("send") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_send(ctx, campaign_id, extra_params): + """Send campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/send" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("test") +@click.argument("CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_test(ctx, campaign_id, data, extra_params): + """Send test email""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/test" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("unschedule") +@click.argument("CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_unschedule(ctx, campaign_id, extra_params): + """Unschedule campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/actions/unschedule" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("list-campaigns-id-content") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_campaigns_id_content(ctx, campaign_id, fields, exclude_fields, extra_params): + """Get campaign content""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/content" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +campaigns_group.add_command(_cmd_list_campaigns_id_content, "list-content") + +@campaigns_group.command("update-campaigns-id-content") +@click.argument("CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_campaigns_id_content(ctx, campaign_id, data, extra_params): + """Set campaign content""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/content" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("list-campaigns-id-feedback") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_campaigns_id_feedback(ctx, campaign_id, fields, exclude_fields, extra_params): + """List campaign feedback""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/feedback" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("create-campaigns-id-feedback") +@click.argument("CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_campaigns_id_feedback(ctx, campaign_id, data, extra_params): + """Add campaign feedback""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/feedback" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("delete-campaigns-id-feedback-id") +@click.argument("CAMPAIGN_ID") +@click.argument("FEEDBACK_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_campaigns_id_feedback_id(ctx, campaign_id, feedback_id, extra_params): + """Delete campaign feedback message""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/feedback/{feedback_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@campaigns_group.command("get-campaigns-id-feedback-id") +@click.argument("CAMPAIGN_ID") +@click.argument("FEEDBACK_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_campaigns_id_feedback_id(ctx, campaign_id, feedback_id, fields, exclude_fields, extra_params): + """Get campaign feedback message""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/feedback/{feedback_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("update-campaigns-id-feedback-id") +@click.argument("CAMPAIGN_ID") +@click.argument("FEEDBACK_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_campaigns_id_feedback_id(ctx, campaign_id, feedback_id, data, extra_params): + """Update campaign feedback message""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/feedback/{feedback_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@campaigns_group.command("list-campaigns-id-send-checklist") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_campaigns_id_send_checklist(ctx, campaign_id, fields, exclude_fields, extra_params): + """Get campaign send checklist""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/campaigns/{campaign_id}/send-checklist" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +campaigns_group.add_command(_cmd_list_campaigns_id_send_checklist, "list-send-checklist") diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/connected_sites.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/connected_sites.py new file mode 100644 index 000000000..d3b0a0d1b --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/connected_sites.py @@ -0,0 +1,142 @@ +"""Commands for the Mailchimp /connected-sites API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("connected-sites") +@click.pass_context +def connected_sites_group(ctx): + """connected-sites resource commands.""" + +@connected_sites_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List connected sites""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/connected-sites" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@connected_sites_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add connected site""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/connected-sites" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@connected_sites_group.command("delete") +@click.argument("CONNECTED_SITE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, connected_site_id, extra_params): + """Delete connected site""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/connected-sites/{connected_site_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@connected_sites_group.command("get") +@click.argument("CONNECTED_SITE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, connected_site_id, fields, exclude_fields, extra_params): + """Get connected site""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/connected-sites/{connected_site_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@connected_sites_group.command("verify-script-installation") +@click.argument("CONNECTED_SITE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_verify_script_installation(ctx, connected_site_id, extra_params): + """Verify connected site script""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/connected-sites/{connected_site_id}/actions/verify-script-installation" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/contacts.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/contacts.py new file mode 100644 index 000000000..ce446aece --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/contacts.py @@ -0,0 +1,123 @@ +"""Commands for the Mailchimp /contacts API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("contacts") +@click.pass_context +def contacts_group(ctx): + """contacts resource commands.""" + +@contacts_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """Get a list of audiences""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@contacts_group.command("get") +@click.argument("AUDIENCE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, audience_id, fields, exclude_fields, extra_params): + """Get audience info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@contacts_group.command("archive") +@click.argument("AUDIENCE_ID") +@click.argument("CONTACT_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_archive(ctx, audience_id, contact_id, extra_params): + """Archive Contact""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}/contacts/{contact_id}/actions/archive" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@contacts_group.command("forget") +@click.argument("AUDIENCE_ID") +@click.argument("CONTACT_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_forget(ctx, audience_id, contact_id, extra_params): + """Forget Contact""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/audiences/{audience_id}/contacts/{contact_id}/actions/forget" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/conversations.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/conversations.py new file mode 100644 index 000000000..2742c6e3c --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/conversations.py @@ -0,0 +1,144 @@ +"""Commands for the Mailchimp /conversations API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("conversations") +@click.pass_context +def conversations_group(ctx): + """conversations resource commands.""" + +@conversations_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--has-unread-messages", "has_unread_messages", default=None, help="Whether the conversation has any unread messages.") +@click.option("--list-id", "list_id", default=None, help="The unique id for the list.") +@click.option("--campaign-id", "campaign_id", default=None, help="The unique id for the campaign.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, has_unread_messages, list_id, campaign_id, extra_params): + """List conversations""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/conversations" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "has_unread_messages": has_unread_messages, + "list_id": list_id, + "campaign_id": campaign_id, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@conversations_group.command("get") +@click.argument("CONVERSATION_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, conversation_id, fields, exclude_fields, extra_params): + """Get conversation""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/conversations/{conversation_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@conversations_group.command("list-conversations-id-messages") +@click.argument("CONVERSATION_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--is-read", "is_read", default=None, help="Whether a conversation message has been marked as read.") +@click.option("--before-timestamp", "before_timestamp", default=None, help="Restrict the response to messages created before the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-timestamp", "since_timestamp", default=None, help="Restrict the response to messages created after the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_conversations_id_messages(ctx, conversation_id, fields, exclude_fields, is_read, before_timestamp, since_timestamp, extra_params): + """List messages""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/conversations/{conversation_id}/messages" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "is_read": is_read, + "before_timestamp": before_timestamp, + "since_timestamp": since_timestamp, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@conversations_group.command("get-conversations-id-messages-id") +@click.argument("CONVERSATION_ID") +@click.argument("MESSAGE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_conversations_id_messages_id(ctx, conversation_id, message_id, fields, exclude_fields, extra_params): + """Get message""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/conversations/{conversation_id}/messages/{message_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/customer_journeys.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/customer_journeys.py new file mode 100644 index 000000000..4366cbc86 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/customer_journeys.py @@ -0,0 +1,51 @@ +"""Commands for the Mailchimp /customer-journeys API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("customer-journeys") +@click.pass_context +def customer_journeys_group(ctx): + """customer-journeys resource commands.""" + +@customer_journeys_group.command("trigger") +@click.argument("JOURNEY_ID") +@click.argument("STEP_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_trigger(ctx, journey_id, step_id, data, extra_params): + """Customer Journeys API trigger for a contact""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/customer-journeys/journeys/{journey_id}/steps/{step_id}/actions/trigger" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/ecommerce.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/ecommerce.py new file mode 100644 index 000000000..862efe287 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/ecommerce.py @@ -0,0 +1,1518 @@ +"""Commands for the Mailchimp /ecommerce API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("ecommerce") +@click.pass_context +def ecommerce_group(ctx): + """ecommerce resource commands.""" + +@ecommerce_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--campaign-id", "campaign_id", default=None, help="Restrict results to orders with a specific `campaign_id` value.") +@click.option("--outreach-id", "outreach_id", default=None, help="Restrict results to orders with a specific `outreach_id` value.") +@click.option("--customer-id", "customer_id", default=None, help="Restrict results to orders made by a specific customer.") +@click.option("--has-outreach", "has_outreach", default=None, type=bool, help="Restrict results to orders that have an outreach attached. For example, an email campaign or Facebook ad.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, campaign_id, outreach_id, customer_id, has_outreach, extra_params): + """List account orders""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/orders" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "campaign_id": campaign_id, + "outreach_id": outreach_id, + "customer_id": customer_id, + "has_outreach": has_outreach, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores(ctx, fields, exclude_fields, count, offset, extra_params): + """List stores""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add store""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete") +@click.argument("STORE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, store_id, extra_params): + """Delete store""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, store_id, fields, exclude_fields, extra_params): + """Get store info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update") +@click.argument("STORE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, store_id, data, extra_params): + """Update store""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-carts") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_carts(ctx, store_id, fields, exclude_fields, count, offset, extra_params): + """List carts""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-carts") +@click.argument("STORE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_carts(ctx, store_id, data, extra_params): + """Add cart""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-carts-id") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_carts_id(ctx, store_id, cart_id, extra_params): + """Delete cart""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-carts-id") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_carts_id(ctx, store_id, cart_id, fields, exclude_fields, extra_params): + """Get cart info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-carts-id") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_carts_id(ctx, store_id, cart_id, data, extra_params): + """Update cart""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-carts-id-lines") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_carts_id_lines(ctx, store_id, cart_id, fields, exclude_fields, count, offset, extra_params): + """List cart line items""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}/lines" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-carts-id-lines") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_carts_id_lines(ctx, store_id, cart_id, data, extra_params): + """Add cart line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}/lines" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-carts-lines-id") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.argument("LINE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_carts_lines_id(ctx, store_id, cart_id, line_id, extra_params): + """Delete cart line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}/lines/{line_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-carts-id-lines-id") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.argument("LINE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_carts_id_lines_id(ctx, store_id, cart_id, line_id, fields, exclude_fields, extra_params): + """Get cart line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}/lines/{line_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-carts-id-lines-id") +@click.argument("STORE_ID") +@click.argument("CART_ID") +@click.argument("LINE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_carts_id_lines_id(ctx, store_id, cart_id, line_id, data, extra_params): + """Update cart line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/carts/{cart_id}/lines/{line_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-customers") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--email-address", "email_address", default=None, help="Restrict the response to customers with the email address.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_customers(ctx, store_id, fields, exclude_fields, count, offset, email_address, extra_params): + """List customers""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/customers" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "email_address": email_address, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-customers") +@click.argument("STORE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_customers(ctx, store_id, data, extra_params): + """Add customer""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/customers" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-customers-id") +@click.argument("STORE_ID") +@click.argument("CUSTOMER_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_customers_id(ctx, store_id, customer_id, extra_params): + """Delete customer""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/customers/{customer_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-customers-id") +@click.argument("STORE_ID") +@click.argument("CUSTOMER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_customers_id(ctx, store_id, customer_id, fields, exclude_fields, extra_params): + """Get customer info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/customers/{customer_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-customers-id") +@click.argument("STORE_ID") +@click.argument("CUSTOMER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_customers_id(ctx, store_id, customer_id, data, extra_params): + """Update customer""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/customers/{customer_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-3") +@click.argument("STORE_ID") +@click.argument("CUSTOMER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_3(ctx, store_id, customer_id, data, extra_params): + """Add or update customer""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/customers/{customer_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-orders") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--customer-id", "customer_id", default=None, help="Restrict results to orders made by a specific customer.") +@click.option("--has-outreach", "has_outreach", default=None, type=bool, help="Restrict results to orders that have an outreach attached. For example, an email campaign or Facebook ad.") +@click.option("--campaign-id", "campaign_id", default=None, help="Restrict results to orders with a specific `campaign_id` value.") +@click.option("--outreach-id", "outreach_id", default=None, help="Restrict results to orders with a specific `outreach_id` value.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_orders(ctx, store_id, fields, exclude_fields, count, offset, customer_id, has_outreach, campaign_id, outreach_id, extra_params): + """List orders""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "customer_id": customer_id, + "has_outreach": has_outreach, + "campaign_id": campaign_id, + "outreach_id": outreach_id, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-orders") +@click.argument("STORE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_orders(ctx, store_id, data, extra_params): + """Add order""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-orders-id") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_orders_id(ctx, store_id, order_id, extra_params): + """Delete order""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-orders-id") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_orders_id(ctx, store_id, order_id, fields, exclude_fields, extra_params): + """Get order info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-orders-id") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_orders_id(ctx, store_id, order_id, data, extra_params): + """Update order""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-4") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_4(ctx, store_id, order_id, data, extra_params): + """Add or update order""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-orders-id-lines") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_orders_id_lines(ctx, store_id, order_id, fields, exclude_fields, count, offset, extra_params): + """List order line items""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}/lines" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-orders-id-lines") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_orders_id_lines(ctx, store_id, order_id, data, extra_params): + """Add order line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}/lines" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-orders-id-lines-id") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.argument("LINE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_orders_id_lines_id(ctx, store_id, order_id, line_id, extra_params): + """Delete order line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}/lines/{line_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-orders-id-lines-id") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.argument("LINE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_orders_id_lines_id(ctx, store_id, order_id, line_id, fields, exclude_fields, extra_params): + """Get order line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}/lines/{line_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-orders-id-lines-id") +@click.argument("STORE_ID") +@click.argument("ORDER_ID") +@click.argument("LINE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_orders_id_lines_id(ctx, store_id, order_id, line_id, data, extra_params): + """Update order line item""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/orders/{order_id}/lines/{line_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-products") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_products(ctx, store_id, fields, exclude_fields, count, offset, extra_params): + """List product""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-products") +@click.argument("STORE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_products(ctx, store_id, data, extra_params): + """Add product""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-products-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_products_id(ctx, store_id, product_id, extra_params): + """Delete product""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-products-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_products_id(ctx, store_id, product_id, fields, exclude_fields, extra_params): + """Get product info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-products-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_products_id(ctx, store_id, product_id, data, extra_params): + """Update product""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-5") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_5(ctx, store_id, product_id, data, extra_params): + """Create or update product""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-products-id-images") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_products_id_images(ctx, store_id, product_id, fields, exclude_fields, count, offset, extra_params): + """List product images""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/images" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-products-id-images") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_products_id_images(ctx, store_id, product_id, data, extra_params): + """Add product image""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/images" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-products-id-images-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("IMAGE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_products_id_images_id(ctx, store_id, product_id, image_id, extra_params): + """Delete product image""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/images/{image_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-products-id-images-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("IMAGE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_products_id_images_id(ctx, store_id, product_id, image_id, fields, exclude_fields, extra_params): + """Get product image info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/images/{image_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-products-id-images-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("IMAGE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_products_id_images_id(ctx, store_id, product_id, image_id, data, extra_params): + """Update product image""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/images/{image_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-products-id-variants") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_products_id_variants(ctx, store_id, product_id, fields, exclude_fields, count, offset, extra_params): + """List product variants""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/variants" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-products-id-variants") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_products_id_variants(ctx, store_id, product_id, data, extra_params): + """Add product variant""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/variants" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-products-id-variants-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("VARIANT_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_products_id_variants_id(ctx, store_id, product_id, variant_id, extra_params): + """Delete product variant""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/variants/{variant_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-products-id-variants-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("VARIANT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_products_id_variants_id(ctx, store_id, product_id, variant_id, fields, exclude_fields, extra_params): + """Get product variant info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/variants/{variant_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-products-id-variants-id") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("VARIANT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_products_id_variants_id(ctx, store_id, product_id, variant_id, data, extra_params): + """Update product variant""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/variants/{variant_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-6") +@click.argument("STORE_ID") +@click.argument("PRODUCT_ID") +@click.argument("VARIANT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_6(ctx, store_id, product_id, variant_id, data, extra_params): + """Add or update product variant""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/products/{product_id}/variants/{variant_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-promorules") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_promorules(ctx, store_id, fields, exclude_fields, count, offset, extra_params): + """List promo rules""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-promorules") +@click.argument("STORE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_promorules(ctx, store_id, data, extra_params): + """Add promo rule""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-promorules-id") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_promorules_id(ctx, store_id, promo_rule_id, extra_params): + """Delete promo rule""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-promorules-id") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_promorules_id(ctx, store_id, promo_rule_id, fields, exclude_fields, extra_params): + """Get promo rule""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-promorules-id") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_promorules_id(ctx, store_id, promo_rule_id, data, extra_params): + """Update promo rule""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("list-ecommerce-stores-id-promocodes") +@click.argument("PROMO_RULE_ID") +@click.argument("STORE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_ecommerce_stores_id_promocodes(ctx, promo_rule_id, store_id, fields, exclude_fields, count, offset, extra_params): + """List promo codes""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}/promo-codes" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("create-ecommerce-stores-id-promocodes") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_ecommerce_stores_id_promocodes(ctx, store_id, promo_rule_id, data, extra_params): + """Add promo code""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}/promo-codes" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("delete-ecommerce-stores-id-promocodes-id") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.argument("PROMO_CODE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_ecommerce_stores_id_promocodes_id(ctx, store_id, promo_rule_id, promo_code_id, extra_params): + """Delete promo code""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}/promo-codes/{promo_code_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@ecommerce_group.command("get-ecommerce-stores-id-promocodes-id") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.argument("PROMO_CODE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_ecommerce_stores_id_promocodes_id(ctx, store_id, promo_rule_id, promo_code_id, fields, exclude_fields, extra_params): + """Get promo code""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}/promo-codes/{promo_code_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@ecommerce_group.command("update-ecommerce-stores-id-promocodes-id") +@click.argument("STORE_ID") +@click.argument("PROMO_RULE_ID") +@click.argument("PROMO_CODE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_ecommerce_stores_id_promocodes_id(ctx, store_id, promo_rule_id, promo_code_id, data, extra_params): + """Update promo code""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ecommerce/stores/{store_id}/promo-rules/{promo_rule_id}/promo-codes/{promo_code_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/facebook_ads.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/facebook_ads.py new file mode 100644 index 000000000..012edeb79 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/facebook_ads.py @@ -0,0 +1,85 @@ +"""Commands for the Mailchimp /facebook-ads API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("facebook-ads") +@click.pass_context +def facebook_ads_group(ctx): + """facebook-ads resource commands.""" + +@facebook_ads_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, sort_field, sort_dir, extra_params): + """List facebook ads""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/facebook-ads" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@facebook_ads_group.command("get") +@click.argument("OUTREACH_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, outreach_id, fields, exclude_fields, extra_params): + """Get facebook ad info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/facebook-ads/{outreach_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/file_manager.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/file_manager.py new file mode 100644 index 000000000..69935e077 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/file_manager.py @@ -0,0 +1,319 @@ +"""Commands for the Mailchimp /file-manager API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("file-manager") +@click.pass_context +def file_manager_group(ctx): + """file-manager resource commands.""" + +@file_manager_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="The file type for the File Manager file.") +@click.option("--created-by", "created_by", default=None, help="The Mailchimp account user who created the File Manager file.") +@click.option("--before-created-at", "before_created_at", default=None, help="Restrict the response to files created before the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-created-at", "since_created_at", default=None, help="Restrict the response to files created after the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, type_, created_by, before_created_at, since_created_at, sort_field, sort_dir, extra_params): + """List stored files""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/files" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "type": type_, + "created_by": created_by, + "before_created_at": before_created_at, + "since_created_at": since_created_at, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add file""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/files" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("delete") +@click.argument("FILE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, file_id, extra_params): + """Delete file""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/files/{file_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@file_manager_group.command("get") +@click.argument("FILE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, file_id, fields, exclude_fields, extra_params): + """Get file""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/files/{file_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("update") +@click.argument("FILE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, file_id, data, extra_params): + """Update file""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/files/{file_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("list-file-manager-folders") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--created-by", "created_by", default=None, help="The Mailchimp account user who created the File Manager file.") +@click.option("--before-created-at", "before_created_at", default=None, help="Restrict the response to files created before the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-created-at", "since_created_at", default=None, help="Restrict the response to files created after the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_file_manager_folders(ctx, fields, exclude_fields, count, offset, created_by, before_created_at, since_created_at, extra_params): + """List folders""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/folders" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "created_by": created_by, + "before_created_at": before_created_at, + "since_created_at": since_created_at, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("create-file-manager-folders") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_file_manager_folders(ctx, data, extra_params): + """Add folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/folders" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("delete-file-manager-folders-id") +@click.argument("FOLDER_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_file_manager_folders_id(ctx, folder_id, extra_params): + """Delete folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/folders/{folder_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@file_manager_group.command("get-file-manager-folders-id") +@click.argument("FOLDER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_file_manager_folders_id(ctx, folder_id, fields, exclude_fields, extra_params): + """Get folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/folders/{folder_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("update-file-manager-folders-id") +@click.argument("FOLDER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_file_manager_folders_id(ctx, folder_id, data, extra_params): + """Update folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/folders/{folder_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@file_manager_group.command("list-file-manager-folders-files") +@click.argument("FOLDER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="The file type for the File Manager file.") +@click.option("--created-by", "created_by", default=None, help="The Mailchimp account user who created the File Manager file.") +@click.option("--before-created-at", "before_created_at", default=None, help="Restrict the response to files created before the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-created-at", "since_created_at", default=None, help="Restrict the response to files created after the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_file_manager_folders_files(ctx, folder_id, fields, exclude_fields, count, offset, type_, created_by, before_created_at, since_created_at, sort_field, sort_dir, extra_params): + """List stored files""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/file-manager/folders/{folder_id}/files" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "type": type_, + "created_by": created_by, + "before_created_at": before_created_at, + "since_created_at": since_created_at, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/landing_pages.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/landing_pages.py new file mode 100644 index 000000000..616e64079 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/landing_pages.py @@ -0,0 +1,214 @@ +"""Commands for the Mailchimp /landing-pages API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("landing-pages") +@click.pass_context +def landing_pages_group(ctx): + """landing-pages resource commands.""" + +@landing_pages_group.command("list") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, sort_dir, sort_field, fields, exclude_fields, count, extra_params): + """List landing pages""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages" + params = {k: v for k, v in { + "sort_dir": sort_dir, + "sort_field": sort_field, + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@landing_pages_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--use-default-list", "use_default_list", default=None, type=bool, help="Will create the Landing Page using the account's Default List instead of requiring a list_id.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, use_default_list, extra_params): + """Add landing page""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages" + params = {k: v for k, v in { + "use_default_list": use_default_list, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@landing_pages_group.command("delete") +@click.argument("PAGE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, page_id, extra_params): + """Delete landing page""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages/{page_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@landing_pages_group.command("get") +@click.argument("PAGE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, page_id, fields, exclude_fields, extra_params): + """Get landing page info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages/{page_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@landing_pages_group.command("update") +@click.argument("PAGE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, page_id, data, extra_params): + """Update landing page""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages/{page_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@landing_pages_group.command("publish") +@click.argument("PAGE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_publish(ctx, page_id, extra_params): + """Publish landing page""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages/{page_id}/actions/publish" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@landing_pages_group.command("unpublish") +@click.argument("PAGE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_unpublish(ctx, page_id, extra_params): + """Unpublish landing page""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages/{page_id}/actions/unpublish" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@landing_pages_group.command("list-landing-page-id-content") +@click.argument("PAGE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_landing_page_id_content(ctx, page_id, fields, exclude_fields, extra_params): + """Get landing page content""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/landing-pages/{page_id}/content" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/lists.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/lists.py new file mode 100644 index 000000000..9638617cc --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/lists.py @@ -0,0 +1,1758 @@ +"""Commands for the Mailchimp /lists API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("lists") +@click.pass_context +def lists_group(ctx): + """lists resource commands.""" + +@lists_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--before-date-created", "before_date_created", default=None, help="Restrict response to lists created before the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-date-created", "since_date_created", default=None, help="Restrict results to lists created after the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-campaign-last-sent", "before_campaign_last_sent", default=None, help="Restrict results to lists created before the last campaign send date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-campaign-last-sent", "since_campaign_last_sent", default=None, help="Restrict results to lists created after the last campaign send date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--email", "email", default=None, help="Restrict results to lists that include a specific subscriber's email address.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--has-ecommerce-store", "has_ecommerce_store", default=None, type=bool, help="Restrict results to lists that contain an active, connected, undeleted ecommerce store.") +@click.option("--include-total-contacts", "include_total_contacts", default=None, type=bool, help="Return the total_contacts field in the stats response, which contains an approximate count of all contacts in any state.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, before_date_created, since_date_created, before_campaign_last_sent, since_campaign_last_sent, email, sort_field, sort_dir, has_ecommerce_store, include_total_contacts, extra_params): + """Get lists info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "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, + "has_ecommerce_store": has_ecommerce_store, + "include_total_contacts": include_total_contacts, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add list""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete") +@click.argument("LIST_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, list_id, extra_params): + """Delete list""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--include-total-contacts", "include_total_contacts", default=None, type=bool, help="Return the total_contacts field in the stats response, which contains an approximate count of all contacts in any state.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, list_id, fields, exclude_fields, include_total_contacts, extra_params): + """Get list info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "include_total_contacts": include_total_contacts, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, list_id, data, extra_params): + """Update lists""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--skip-merge-validation", "skip_merge_validation", default=None, type=bool, help="If skip_merge_validation is true, member data will be accepted without merge field values, even if the merge field is usually required. This defaults to false.") +@click.option("--skip-duplicate-check", "skip_duplicate_check", default=None, type=bool, help="If skip_duplicate_check is true, we will ignore duplicates sent in the request when using the batch sub/unsub on the lists endpoint. The status of the first appearance in the request will be saved. This defaults to false.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id(ctx, list_id, data, skip_merge_validation, skip_duplicate_check, extra_params): + """Batch subscribe or unsubscribe""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}" + params = {k: v for k, v in { + "skip_merge_validation": skip_merge_validation, + "skip_duplicate_check": skip_duplicate_check, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-abuse-reports") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_abuse_reports(ctx, list_id, fields, exclude_fields, count, offset, extra_params): + """List abuse reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/abuse-reports" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("get-lists-id-abuse-reports-id") +@click.argument("LIST_ID") +@click.argument("REPORT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_abuse_reports_id(ctx, list_id, report_id, fields, exclude_fields, count, offset, extra_params): + """Get abuse report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/abuse-reports/{report_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-activity") +@click.argument("LIST_ID") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_activity(ctx, list_id, count, offset, fields, exclude_fields, extra_params): + """List recent activity""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/activity" + params = {k: v for k, v in { + "count": count, + "offset": offset, + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-clients") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_clients(ctx, list_id, fields, exclude_fields, extra_params): + """List top email clients""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/clients" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-growth-history") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_growth_history(ctx, list_id, fields, exclude_fields, count, offset, sort_field, sort_dir, extra_params): + """List growth history data""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/growth-history" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("get-lists-id-growth-history-id") +@click.argument("LIST_ID") +@click.argument("MONTH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_growth_history_id(ctx, list_id, month, fields, exclude_fields, extra_params): + """Get growth history by month""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/growth-history/{month}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-interest-categories") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="Restrict results a type of interest group") +@click.option("--sort-field", "sort_field", default=None, help="Returns interest categories sorted by the specified field. Defaults to display_order.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_interest_categories(ctx, list_id, fields, exclude_fields, count, offset, type_, sort_field, sort_dir, extra_params): + """List interest categories""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "type": type_, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-interest-categories") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_interest_categories(ctx, list_id, data, extra_params): + """Add interest category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-interest-categories-id") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_interest_categories_id(ctx, list_id, interest_category_id, extra_params): + """Delete interest category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-interest-categories-id") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_interest_categories_id(ctx, list_id, interest_category_id, fields, exclude_fields, extra_params): + """Get interest category info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-interest-categories-id") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_interest_categories_id(ctx, list_id, interest_category_id, data, extra_params): + """Update interest category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-interest-categories-id-interests") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_interest_categories_id_interests(ctx, list_id, interest_category_id, fields, exclude_fields, count, offset, extra_params): + """List interests in category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}/interests" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-interest-categories-id-interests") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_interest_categories_id_interests(ctx, list_id, interest_category_id, data, extra_params): + """Add interest in category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}/interests" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-interest-categories-id-interests-id") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.argument("INTEREST_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_interest_categories_id_interests_id(ctx, list_id, interest_category_id, interest_id, extra_params): + """Delete interest in category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}/interests/{interest_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-interest-categories-id-interests-id") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.argument("INTEREST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_interest_categories_id_interests_id(ctx, list_id, interest_category_id, interest_id, fields, exclude_fields, extra_params): + """Get interest in category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}/interests/{interest_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-interest-categories-id-interests-id") +@click.argument("LIST_ID") +@click.argument("INTEREST_CATEGORY_ID") +@click.argument("INTEREST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_interest_categories_id_interests_id(ctx, list_id, interest_category_id, interest_id, data, extra_params): + """Update interest in category""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/interest-categories/{interest_category_id}/interests/{interest_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-locations") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_locations(ctx, list_id, fields, exclude_fields, extra_params): + """List locations""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/locations" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-members") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--email-type", "email_type", default=None, help="The email type.") +@click.option("--status", "status", default=None, help="The subscriber's status.") +@click.option("--since-timestamp-opt", "since_timestamp_opt", default=None, help="Restrict results to subscribers who opted-in after the set timeframe. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-timestamp-opt", "before_timestamp_opt", default=None, help="Restrict results to subscribers who opted-in before the set timeframe. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-last-changed", "since_last_changed", default=None, help="Restrict results to subscribers whose information changed after the set timeframe. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-last-changed", "before_last_changed", default=None, help="Restrict results to subscribers whose information changed before the set timeframe. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--unique-email-id", "unique_email_id", default=None, help="A unique identifier for the email address across all Mailchimp lists.") +@click.option("--vip-only", "vip_only", default=None, type=bool, help="A filter to return only the list's VIP members. Passing `true` will restrict results to VIP list members, passing `false` will return all list members.") +@click.option("--interest-category-id", "interest_category_id", default=None, help="The unique id for the interest category.") +@click.option("--interest-ids", "interest_ids", default=None, help="Used to filter list members by interests. Must be accompanied by interest_category_id and interest_match. The value must be a comma separated list of interest ids present for any supplied interest categories.") +@click.option("--interest-match", "interest_match", default=None, help="Used to filter list members by interests. Must be accompanied by interest_category_id and interest_ids. \"any\" will match a member with any of the interest supplied, \"all\" will only match members with every interest supplied, and \"none\" will match members without any of the interest supplied.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--since-last-campaign", "since_last_campaign", default=None, type=bool, help="Filter subscribers by those subscribed/unsubscribed/pending/cleaned since last email campaign send. Member status is required to use this filter.") +@click.option("--unsubscribed-since", "unsubscribed_since", default=None, help="Filter subscribers by those unsubscribed since a specific date. Using any status other than unsubscribed with this filter will result in an error.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_members(ctx, list_id, fields, exclude_fields, count, offset, email_type, status, since_timestamp_opt, before_timestamp_opt, since_last_changed, before_last_changed, unique_email_id, vip_only, interest_category_id, interest_ids, interest_match, sort_field, sort_dir, since_last_campaign, unsubscribed_since, extra_params): + """List members info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "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, + "since_last_campaign": since_last_campaign, + "unsubscribed_since": unsubscribed_since, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-members") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--skip-merge-validation", "skip_merge_validation", default=None, type=bool, help="If skip_merge_validation is true, member data will be accepted without merge field values, even if the merge field is usually required. This defaults to false.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_members(ctx, list_id, data, skip_merge_validation, extra_params): + """Add member to list""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members" + params = {k: v for k, v in { + "skip_merge_validation": skip_merge_validation, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +lists_group.add_command(_cmd_create_lists_id_members, "create-members") + +@lists_group.command("delete-lists-id-members-id") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_members_id(ctx, list_id, subscriber_hash, extra_params): + """Archive list member""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-members-id") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_members_id(ctx, list_id, subscriber_hash, fields, exclude_fields, extra_params): + """Get member info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-members-id") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--skip-merge-validation", "skip_merge_validation", default=None, type=bool, help="If skip_merge_validation is true, member data will be accepted without merge field values, even if the merge field is usually required. This defaults to false.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_members_id(ctx, list_id, subscriber_hash, data, skip_merge_validation, extra_params): + """Update list member""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}" + params = {k: v for k, v in { + "skip_merge_validation": skip_merge_validation, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-3") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--skip-merge-validation", "skip_merge_validation", default=None, type=bool, help="If skip_merge_validation is true, member data will be accepted without merge field values, even if the merge field is usually required. This defaults to false.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_3(ctx, list_id, subscriber_hash, data, skip_merge_validation, extra_params): + """Add or update list member""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}" + params = {k: v for k, v in { + "skip_merge_validation": skip_merge_validation, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-permanent") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_permanent(ctx, list_id, subscriber_hash, extra_params): + """Delete list member""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/actions/delete-permanent" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-members-id-activity") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--action", "action", default=None, help="A comma seperated list of actions to return.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_members_id_activity(ctx, list_id, subscriber_hash, fields, exclude_fields, action, extra_params): + """View recent activity 50""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/activity" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "action": action, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-members-id-activity-feed") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--activity-filters", "activity_filters", default=None, help="A comma-separated list of activity filters that correspond to a set of activity types, e.g \"?activity_filters=open,bounce,click\".") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_members_id_activity_feed(ctx, list_id, subscriber_hash, fields, exclude_fields, count, offset, activity_filters, extra_params): + """View recent activity""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/activity-feed" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "activity_filters": activity_filters, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-members-id-events") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_members_id_events(ctx, list_id, subscriber_hash, count, offset, fields, exclude_fields, extra_params): + """List member events""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/events" + params = {k: v for k, v in { + "count": count, + "offset": offset, + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-list-member-events") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_list_member_events(ctx, list_id, subscriber_hash, data, extra_params): + """Add event""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/events" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-members-id-goals") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_members_id_goals(ctx, list_id, subscriber_hash, fields, exclude_fields, extra_params): + """List member goal events""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/goals" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-members-id-notes") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--sort-field", "sort_field", default=None, help="Returns notes sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_members_id_notes(ctx, list_id, subscriber_hash, sort_field, sort_dir, fields, exclude_fields, count, offset, extra_params): + """List recent member notes""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/notes" + params = {k: v for k, v in { + "sort_field": sort_field, + "sort_dir": sort_dir, + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-members-id-notes") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_members_id_notes(ctx, list_id, subscriber_hash, data, extra_params): + """Add member note""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/notes" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-members-id-notes-id") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.argument("NOTE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_members_id_notes_id(ctx, list_id, subscriber_hash, note_id, extra_params): + """Delete note""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/notes/{note_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-members-id-notes-id") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.argument("NOTE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_members_id_notes_id(ctx, list_id, subscriber_hash, note_id, fields, exclude_fields, extra_params): + """Get member note""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/notes/{note_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-members-id-notes-id") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.argument("NOTE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_members_id_notes_id(ctx, list_id, subscriber_hash, note_id, data, extra_params): + """Update note""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/notes/{note_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-list-member-tags") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_list_member_tags(ctx, list_id, subscriber_hash, fields, exclude_fields, count, offset, extra_params): + """List member tags""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/tags" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-list-member-tags") +@click.argument("LIST_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_list_member_tags(ctx, list_id, subscriber_hash, data, extra_params): + """Add or remove member tags""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/members/{subscriber_hash}/tags" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-merge-fields") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="The merge field type.") +@click.option("--required", "required", default=None, type=bool, help="Whether it's a required merge field.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_merge_fields(ctx, list_id, fields, exclude_fields, count, offset, type_, required, extra_params): + """List merge fields""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/merge-fields" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "type": type_, + "required": required, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-merge-fields") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_merge_fields(ctx, list_id, data, extra_params): + """Add merge field""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/merge-fields" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-merge-fields-id") +@click.argument("LIST_ID") +@click.argument("MERGE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_merge_fields_id(ctx, list_id, merge_id, extra_params): + """Delete merge field""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/merge-fields/{merge_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-merge-fields-id") +@click.argument("LIST_ID") +@click.argument("MERGE_ID") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_merge_fields_id(ctx, list_id, merge_id, exclude_fields, fields, extra_params): + """Get merge field""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/merge-fields/{merge_id}" + params = {k: v for k, v in { + "exclude_fields": exclude_fields, + "fields": fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-merge-fields-id") +@click.argument("LIST_ID") +@click.argument("MERGE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_merge_fields_id(ctx, list_id, merge_id, data, extra_params): + """Update merge field""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/merge-fields/{merge_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-preview-a-segment") +@click.argument("LIST_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="Limit results based on segment type.") +@click.option("--since-created-at", "since_created_at", default=None, help="Restrict results to segments created after the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-created-at", "before_created_at", default=None, help="Restrict results to segments created before the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--include-cleaned", "include_cleaned", default=None, type=bool, help="Include cleaned members in response") +@click.option("--include-transactional", "include_transactional", default=None, type=bool, help="Include transactional members in response") +@click.option("--include-unsubscribed", "include_unsubscribed", default=None, type=bool, help="Include unsubscribed members in response") +@click.option("--since-updated-at", "since_updated_at", default=None, help="Restrict results to segments update after the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-updated-at", "before_updated_at", default=None, help="Restrict results to segments update before the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--exclude-type", "exclude_type", default=None, help="Exclude results based on segment type. For example, use `exclude_type=static` to exclude tags from the response.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_preview_a_segment(ctx, list_id, fields, exclude_fields, count, offset, type_, since_created_at, before_created_at, include_cleaned, include_transactional, include_unsubscribed, since_updated_at, before_updated_at, exclude_type, extra_params): + """List segments""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "type": type_, + "since_created_at": since_created_at, + "before_created_at": before_created_at, + "include_cleaned": include_cleaned, + "include_transactional": include_transactional, + "include_unsubscribed": include_unsubscribed, + "since_updated_at": since_updated_at, + "before_updated_at": before_updated_at, + "exclude_type": exclude_type, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +lists_group.add_command(_cmd_list_preview_a_segment, "list-lists-id-segments") + +@lists_group.command("create-lists-id-segments") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_segments(ctx, list_id, data, extra_params): + """Add segment""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-segments-id") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_segments_id(ctx, list_id, segment_id, extra_params): + """Delete segment""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-segments-id") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--include-cleaned", "include_cleaned", default=None, type=bool, help="Include cleaned members in response") +@click.option("--include-transactional", "include_transactional", default=None, type=bool, help="Include transactional members in response") +@click.option("--include-unsubscribed", "include_unsubscribed", default=None, type=bool, help="Include unsubscribed members in response") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_segments_id(ctx, list_id, segment_id, fields, exclude_fields, include_cleaned, include_transactional, include_unsubscribed, extra_params): + """Get segment info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "include_cleaned": include_cleaned, + "include_transactional": include_transactional, + "include_unsubscribed": include_unsubscribed, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-segments-id") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_segments_id(ctx, list_id, segment_id, data, extra_params): + """Update segment""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-segments-id") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_segments_id(ctx, list_id, segment_id, data, extra_params): + """Batch add or remove members""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-segments-id-members") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--include-cleaned", "include_cleaned", default=None, type=bool, help="Include cleaned members in response") +@click.option("--include-transactional", "include_transactional", default=None, type=bool, help="Include transactional members in response") +@click.option("--include-unsubscribed", "include_unsubscribed", default=None, type=bool, help="Include unsubscribed members in response") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_segments_id_members(ctx, list_id, segment_id, fields, exclude_fields, count, offset, include_cleaned, include_transactional, include_unsubscribed, extra_params): + """List members in segment""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}/members" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "include_cleaned": include_cleaned, + "include_transactional": include_transactional, + "include_unsubscribed": include_unsubscribed, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-segments-id-members") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_segments_id_members(ctx, list_id, segment_id, data, extra_params): + """Add member to segment""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}/members" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-segments-id-members-id") +@click.argument("LIST_ID") +@click.argument("SEGMENT_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_segments_id_members_id(ctx, list_id, segment_id, subscriber_hash, extra_params): + """Remove list member from segment""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/segments/{segment_id}/members/{subscriber_hash}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("list-lists-id-signup-forms") +@click.argument("LIST_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_signup_forms(ctx, list_id, extra_params): + """List signup forms""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/signup-forms" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-signup-forms") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_signup_forms(ctx, list_id, data, extra_params): + """Customize signup form""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/signup-forms" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-surveys") +@click.argument("LIST_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_surveys(ctx, list_id, extra_params): + """Get information about all surveys for a list""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/surveys" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("get-lists-id-surveys-id") +@click.argument("LIST_ID") +@click.argument("SURVEY_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_surveys_id(ctx, list_id, survey_id, extra_params): + """Get survey""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/surveys/{survey_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-search-tags-by-name") +@click.argument("LIST_ID") +@click.option("--name", "name", default=None, help="The search query used to filter tags. The search query will be compared to each tag as a prefix, so all tags that have a name starting with this field will be returned.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_search_tags_by_name(ctx, list_id, name, extra_params): + """Search for tags on a list by name.""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/tag-search" + params = {k: v for k, v in { + "name": name, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("list-lists-id-webhooks") +@click.argument("LIST_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_lists_id_webhooks(ctx, list_id, extra_params): + """List webhooks""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/webhooks" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("create-lists-id-webhooks") +@click.argument("LIST_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_lists_id_webhooks(ctx, list_id, data, extra_params): + """Add webhook""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/webhooks" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("delete-lists-id-webhooks-id") +@click.argument("LIST_ID") +@click.argument("WEBHOOK_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete_lists_id_webhooks_id(ctx, list_id, webhook_id, extra_params): + """Delete webhook""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/webhooks/{webhook_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@lists_group.command("get-lists-id-webhooks-id") +@click.argument("LIST_ID") +@click.argument("WEBHOOK_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_lists_id_webhooks_id(ctx, list_id, webhook_id, extra_params): + """Get webhook info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/webhooks/{webhook_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@lists_group.command("update-lists-id-webhooks-id") +@click.argument("LIST_ID") +@click.argument("WEBHOOK_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_lists_id_webhooks_id(ctx, list_id, webhook_id, data, extra_params): + """Update webhook""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/webhooks/{webhook_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/ping.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/ping.py new file mode 100644 index 000000000..a0f97c1c7 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/ping.py @@ -0,0 +1,49 @@ +"""Commands for the Mailchimp /ping API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("ping", invoke_without_command=True) +@click.pass_context +def ping_group(ctx): + """ping resource commands.""" + if ctx.invoked_subcommand is None: + ctx.invoke(_cmd_list_) + +@ping_group.command("list") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, extra_params): + """Ping""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/ping" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/reporting.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/reporting.py new file mode 100644 index 000000000..4f2642a0e --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/reporting.py @@ -0,0 +1,353 @@ +"""Commands for the Mailchimp /reporting API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("reporting") +@click.pass_context +def reporting_group(ctx): + """reporting resource commands.""" + +@reporting_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, sort_field, sort_dir, extra_params): + """List facebook ads reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/facebook-ads" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("get") +@click.argument("OUTREACH_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, outreach_id, fields, exclude_fields, extra_params): + """Get facebook ad report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/facebook-ads/{outreach_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("list-reporting-facebook-ads-id-ecommerce-product-activity") +@click.argument("OUTREACH_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reporting_facebook_ads_id_ecommerce_product_activity(ctx, outreach_id, fields, exclude_fields, count, offset, sort_field, extra_params): + """List facebook ecommerce report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/facebook-ads/{outreach_id}/ecommerce-product-activity" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "sort_field": sort_field, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("list-reporting-landing-pages") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reporting_landing_pages(ctx, fields, exclude_fields, count, offset, extra_params): + """List landing pages reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/landing-pages" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("get-reporting-landing-pages-id") +@click.argument("OUTREACH_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reporting_landing_pages_id(ctx, outreach_id, fields, exclude_fields, extra_params): + """Get landing page report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/landing-pages/{outreach_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("list-reporting-surveys") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reporting_surveys(ctx, fields, exclude_fields, count, offset, extra_params): + """List survey reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("get-reporting-surveys-id") +@click.argument("SURVEY_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reporting_surveys_id(ctx, survey_id, fields, exclude_fields, extra_params): + """Get survey report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys/{survey_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("list-reporting-surveys-id-questions") +@click.argument("SURVEY_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reporting_surveys_id_questions(ctx, survey_id, fields, exclude_fields, extra_params): + """List survey question reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys/{survey_id}/questions" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("get-reporting-surveys-id-questions-id") +@click.argument("SURVEY_ID") +@click.argument("QUESTION_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reporting_surveys_id_questions_id(ctx, survey_id, question_id, fields, exclude_fields, extra_params): + """Get survey question report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys/{survey_id}/questions/{question_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("list-reporting-surveys-id-questions-id-answers") +@click.argument("SURVEY_ID") +@click.argument("QUESTION_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--respondent-familiarity-is", "respondent_familiarity_is", default=None, help="Filter survey responses by familiarity of the respondents.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reporting_surveys_id_questions_id_answers(ctx, survey_id, question_id, fields, exclude_fields, respondent_familiarity_is, extra_params): + """List answers for question""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys/{survey_id}/questions/{question_id}/answers" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "respondent_familiarity_is": respondent_familiarity_is, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("list-reporting-surveys-id-responses") +@click.argument("SURVEY_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--answered-question", "answered_question", default=None, type=int, help="The ID of the question that was answered.") +@click.option("--chose-answer", "chose_answer", default=None, help="The ID of the option chosen to filter responses on.") +@click.option("--respondent-familiarity-is", "respondent_familiarity_is", default=None, help="Filter survey responses by familiarity of the respondents.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reporting_surveys_id_responses(ctx, survey_id, fields, exclude_fields, answered_question, chose_answer, respondent_familiarity_is, extra_params): + """List survey responses""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys/{survey_id}/responses" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "answered_question": answered_question, + "chose_answer": chose_answer, + "respondent_familiarity_is": respondent_familiarity_is, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reporting_group.command("get-reporting-surveys-id-responses-id") +@click.argument("SURVEY_ID") +@click.argument("RESPONSE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reporting_surveys_id_responses_id(ctx, survey_id, response_id, extra_params): + """Get survey response""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reporting/surveys/{survey_id}/responses/{response_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/reports.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/reports.py new file mode 100644 index 000000000..466341e2c --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/reports.py @@ -0,0 +1,656 @@ +"""Commands for the Mailchimp /reports API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("reports") +@click.pass_context +def reports_group(ctx): + """reports resource commands.""" + +@reports_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--type", "type_", default=None, help="The campaign type.") +@click.option("--before-send-time", "before_send_time", default=None, help="Restrict the response to campaigns sent before the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--since-send-time", "since_send_time", default=None, help="Restrict the response to campaigns sent after the set time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, type_, before_send_time, since_send_time, extra_params): + """List campaign reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "type": type_, + "before_send_time": before_send_time, + "since_send_time": since_send_time, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("get") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, campaign_id, fields, exclude_fields, extra_params): + """Get campaign report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-abuse-reports-id") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_abuse_reports_id(ctx, campaign_id, fields, exclude_fields, extra_params): + """List abuse reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/abuse-reports" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("get-reports-id-abuse-reports-id-id") +@click.argument("CAMPAIGN_ID") +@click.argument("REPORT_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_abuse_reports_id_id(ctx, campaign_id, report_id, fields, exclude_fields, extra_params): + """Get abuse report""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/abuse-reports/{report_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-advice") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_advice(ctx, campaign_id, fields, exclude_fields, extra_params): + """List campaign feedback""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/advice" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-click-details") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--sort-field", "sort_field", default=None, help="Returns click reports sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_click_details(ctx, campaign_id, fields, exclude_fields, count, offset, sort_field, sort_dir, extra_params): + """List campaign details""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/click-details" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +reports_group.add_command(_cmd_list_reports_id_click_details, "list-click-details") + +@reports_group.command("get-reports-id-click-details-id") +@click.argument("CAMPAIGN_ID") +@click.argument("LINK_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_click_details_id(ctx, campaign_id, link_id, fields, exclude_fields, extra_params): + """Get campaign link details""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/click-details/{link_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-click-details-id-members") +@click.argument("CAMPAIGN_ID") +@click.argument("LINK_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_click_details_id_members(ctx, campaign_id, link_id, fields, exclude_fields, count, offset, extra_params): + """List clicked link subscribers""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/click-details/{link_id}/members" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("get-reports-id-click-details-id-members-id") +@click.argument("CAMPAIGN_ID") +@click.argument("LINK_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_click_details_id_members_id(ctx, campaign_id, link_id, subscriber_hash, fields, exclude_fields, extra_params): + """Get clicked link subscriber""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/click-details/{link_id}/members/{subscriber_hash}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-domain-performance") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_domain_performance(ctx, campaign_id, fields, exclude_fields, extra_params): + """List domain performance stats""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/domain-performance" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +reports_group.add_command(_cmd_list_reports_id_domain_performance, "list-domain-performance") + +@reports_group.command("list-reports-id-ecommerce-product-activity") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--sort-field", "sort_field", default=None, help="Returns files sorted by the specified field.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_ecommerce_product_activity(ctx, campaign_id, fields, exclude_fields, count, offset, sort_field, extra_params): + """List campaign product activity""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/ecommerce-product-activity" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "sort_field": sort_field, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-eepurl") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_eepurl(ctx, campaign_id, fields, exclude_fields, extra_params): + """List EepURL activity""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/eepurl" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-email-activity") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--since", "since", default=None, help="Restrict results to email activity events that occur after a specific time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_email_activity(ctx, campaign_id, fields, exclude_fields, count, offset, since, extra_params): + """List email activity""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/email-activity" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "since": since, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +reports_group.add_command(_cmd_list_reports_id_email_activity, "list-email-activity") + +@reports_group.command("get-reports-id-email-activity-id") +@click.argument("CAMPAIGN_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--since", "since", default=None, help="Restrict results to email activity events that occur after a specific time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_email_activity_id(ctx, campaign_id, subscriber_hash, fields, exclude_fields, since, extra_params): + """Get subscriber email activity""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/email-activity/{subscriber_hash}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "since": since, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-locations") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_locations(ctx, campaign_id, fields, exclude_fields, count, offset, extra_params): + """List top open activities""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/locations" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +reports_group.add_command(_cmd_list_reports_id_locations, "list-locations") + +@reports_group.command("list-reports-id-open-details") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--since", "since", default=None, help="Restrict results to campaign open events that occur after a specific time. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--sort-field", "sort_field", default=None, help="Returns open reports sorted by the specified field.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_open_details(ctx, campaign_id, fields, exclude_fields, count, offset, since, sort_field, sort_dir, extra_params): + """List campaign open details""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/open-details" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "since": since, + "sort_field": sort_field, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +reports_group.add_command(_cmd_list_reports_id_open_details, "list-open-details") + +@reports_group.command("get-reports-id-open-details-id-members-id") +@click.argument("CAMPAIGN_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_open_details_id_members_id(ctx, campaign_id, subscriber_hash, fields, exclude_fields, extra_params): + """Get opened campaign subscriber""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/open-details/{subscriber_hash}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-sent-to") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_sent_to(ctx, campaign_id, fields, exclude_fields, count, offset, extra_params): + """List campaign recipients""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/sent-to" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("get-reports-id-sent-to-id") +@click.argument("CAMPAIGN_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_sent_to_id(ctx, campaign_id, subscriber_hash, fields, exclude_fields, extra_params): + """Get campaign recipient info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/sent-to/{subscriber_hash}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-sub-reports-id") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_sub_reports_id(ctx, campaign_id, fields, exclude_fields, extra_params): + """List child campaign reports""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/sub-reports" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@reports_group.command("list-reports-id-unsubscribed") +@click.argument("CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_reports_id_unsubscribed(ctx, campaign_id, fields, exclude_fields, count, offset, extra_params): + """List unsubscribed members""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/unsubscribed" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +reports_group.add_command(_cmd_list_reports_id_unsubscribed, "list-unsubscribed") + +@reports_group.command("get-reports-id-unsubscribed-id") +@click.argument("CAMPAIGN_ID") +@click.argument("SUBSCRIBER_HASH") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get_reports_id_unsubscribed_id(ctx, campaign_id, subscriber_hash, fields, exclude_fields, extra_params): + """Get unsubscribed member""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/reports/{campaign_id}/unsubscribed/{subscriber_hash}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/root.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/root.py new file mode 100644 index 000000000..e5c012410 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/root.py @@ -0,0 +1,52 @@ +"""Commands for the Mailchimp /root API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("root") +@click.pass_context +def root_group(ctx): + """root resource commands.""" + +@root_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, extra_params): + """List api root resources""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/search_campaigns.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/search_campaigns.py new file mode 100644 index 000000000..a28ad6eeb --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/search_campaigns.py @@ -0,0 +1,54 @@ +"""Commands for the Mailchimp /search-campaigns API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("search-campaigns") +@click.pass_context +def search_campaigns_group(ctx): + """search-campaigns resource commands.""" + +@search_campaigns_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--query", "query", default=None, help="The search query used to filter results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, query, extra_params): + """Search campaigns""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/search-campaigns" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "query": query, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/search_members.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/search_members.py new file mode 100644 index 000000000..6ac8ec940 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/search_members.py @@ -0,0 +1,56 @@ +"""Commands for the Mailchimp /search-members API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("search-members") +@click.pass_context +def search_members_group(ctx): + """search-members resource commands.""" + +@search_members_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--query", "query", default=None, help="The search query used to filter results. Query should be a valid email, or a string representing a contact's first or last name.") +@click.option("--list-id", "list_id", default=None, help="The unique id for the list.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, query, list_id, extra_params): + """Search members""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/search-members" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "query": query, + "list_id": list_id, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/sms_campaigns.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/sms_campaigns.py new file mode 100644 index 000000000..a30d5373c --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/sms_campaigns.py @@ -0,0 +1,253 @@ +"""Commands for the Mailchimp /sms-campaigns API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("sms-campaigns") +@click.pass_context +def sms_campaigns_group(ctx): + """sms-campaigns resource commands.""" + +@sms_campaigns_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List SMS campaigns""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add SMS campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("delete") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, sms_campaign_id, extra_params): + """Delete SMS campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@sms_campaigns_group.command("get") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, sms_campaign_id, fields, exclude_fields, extra_params): + """Get SMS campaign info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("update") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, sms_campaign_id, data, extra_params): + """Update SMS campaign settings""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("cancel-send") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_cancel_send(ctx, sms_campaign_id, extra_params): + """Cancel SMS campaign send""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}/actions/cancel-send" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("schedule") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_schedule(ctx, sms_campaign_id, data, extra_params): + """Schedule SMS campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}/actions/schedule" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("send") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_send(ctx, sms_campaign_id, extra_params): + """Send SMS campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}/actions/send" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("list-sms-campaigns-id-content") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_sms_campaigns_id_content(ctx, sms_campaign_id, fields, exclude_fields, extra_params): + """Get SMS campaign content""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}/content" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@sms_campaigns_group.command("update-sms-campaigns-id-content") +@click.argument("SMS_CAMPAIGN_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update_sms_campaigns_id_content(ctx, sms_campaign_id, data, extra_params): + """Set SMS campaign content""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/sms-campaigns/{sms_campaign_id}/content" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.put(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/surveys.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/surveys.py new file mode 100644 index 000000000..6d7ef7704 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/surveys.py @@ -0,0 +1,91 @@ +"""Commands for the Mailchimp /surveys API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("surveys") +@click.pass_context +def surveys_group(ctx): + """surveys resource commands.""" + +@surveys_group.command("create-email") +@click.argument("LIST_ID") +@click.argument("SURVEY_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create_email(ctx, list_id, survey_id, extra_params): + """Create a Survey Campaign""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/surveys/{survey_id}/actions/create-email" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@surveys_group.command("publish") +@click.argument("LIST_ID") +@click.argument("SURVEY_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_publish(ctx, list_id, survey_id, extra_params): + """Publish a Survey""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/surveys/{survey_id}/actions/publish" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@surveys_group.command("unpublish") +@click.argument("LIST_ID") +@click.argument("SURVEY_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_unpublish(ctx, list_id, survey_id, extra_params): + """Unpublish a Survey""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/lists/{list_id}/surveys/{survey_id}/actions/unpublish" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.post(path, json=None, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/template_folders.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/template_folders.py new file mode 100644 index 000000000..afefc23ad --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/template_folders.py @@ -0,0 +1,144 @@ +"""Commands for the Mailchimp /template-folders API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("template-folders") +@click.pass_context +def template_folders_group(ctx): + """template-folders resource commands.""" + +@template_folders_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, extra_params): + """List template folders""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/template-folders" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@template_folders_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add template folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/template-folders" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@template_folders_group.command("delete") +@click.argument("FOLDER_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, folder_id, extra_params): + """Delete template folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/template-folders/{folder_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@template_folders_group.command("get") +@click.argument("FOLDER_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, folder_id, fields, exclude_fields, extra_params): + """Get template folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/template-folders/{folder_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@template_folders_group.command("update") +@click.argument("FOLDER_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, folder_id, data, extra_params): + """Update template folder""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/template-folders/{folder_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/templates.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/templates.py new file mode 100644 index 000000000..face49459 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/templates.py @@ -0,0 +1,187 @@ +"""Commands for the Mailchimp /templates API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("templates") +@click.pass_context +def templates_group(ctx): + """templates resource commands.""" + +@templates_group.command("list") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--count", "count", default=None, type=int, help="The number of records to return. Default value is 10. Maximum value is 1000") +@click.option("--offset", "offset", default=None, type=int, help="Used for [pagination](https://mailchimp.com/developer/marketing/docs/methods-parameters/#pagination), this is the number of records from a collection to skip. Default value is 0.") +@click.option("--created-by", "created_by", default=None, help="The Mailchimp account user who created the template.") +@click.option("--since-date-created", "since_date_created", default=None, help="Restrict the response to templates created after the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--before-date-created", "before_date_created", default=None, help="Restrict the response to templates created before the set date. Uses ISO 8601 time format: 2015-10-21T15:41:36+00:00.") +@click.option("--type", "type_", default=None, help="Limit results based on template type.") +@click.option("--category", "category", default=None, help="Limit results based on category.") +@click.option("--folder-id", "folder_id", default=None, help="The unique folder id.") +@click.option("--sort-field", "sort_field", default=None, help="Returns user templates sorted by the specified field.") +@click.option("--content-type", "content_type", default=None, help="Limit results based on how the template's content is put together. Only templates of type `user` can be filtered by `content_type`. If you want to retrieve saved templates created with the legacy email editor, then filter `content_type` to `template`. If you'd rather pull your saved templates for the new editor, filter to `multichannel`. For code your own templates, filter to `html`.") +@click.option("--sort-dir", "sort_dir", default=None, help="Determines the order direction for sorted results.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, fields, exclude_fields, count, offset, created_by, since_date_created, before_date_created, type_, category, folder_id, sort_field, content_type, sort_dir, extra_params): + """List templates""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/templates" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + "count": count, + "offset": offset, + "created_by": created_by, + "since_date_created": since_date_created, + "before_date_created": before_date_created, + "type": type_, + "category": category, + "folder_id": folder_id, + "sort_field": sort_field, + "content_type": content_type, + "sort_dir": sort_dir, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@templates_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add template""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/templates" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@templates_group.command("delete") +@click.argument("TEMPLATE_ID") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, template_id, extra_params): + """Delete template""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/templates/{template_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@templates_group.command("get") +@click.argument("TEMPLATE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, template_id, fields, exclude_fields, extra_params): + """Get template info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/templates/{template_id}" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@templates_group.command("update") +@click.argument("TEMPLATE_ID") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_update(ctx, template_id, data, extra_params): + """Update template""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/templates/{template_id}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.patch(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@templates_group.command("list-templates-id-default-content") +@click.argument("TEMPLATE_ID") +@click.option("--fields", "fields", default=None, help="A comma-separated list of fields to return. Reference parameters of sub-objects with dot notation.") +@click.option("--exclude-fields", "exclude_fields", default=None, help="A comma-separated list of fields to exclude. Reference parameters of sub-objects with dot notation.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_templates_id_default_content(ctx, template_id, fields, exclude_fields, extra_params): + """View default content""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/templates/{template_id}/default-content" + params = {k: v for k, v in { + "fields": fields, + "exclude_fields": exclude_fields, + }.items() if v is not None} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/commands/verified_domains.py b/mailchimp/agent-harness/cli_anything/mailchimp/commands/verified_domains.py new file mode 100644 index 000000000..c6902adfa --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/commands/verified_domains.py @@ -0,0 +1,130 @@ +"""Commands for the Mailchimp /verified-domains API resource. + +Auto-generated by cli_anything/mailchimp/_codegen/generate.py. +Do not edit manually โ€” re-run the generator to update. +""" + +import json + +import click + + +def _parse_json_option(value, option_name, require_object=False): + try: + parsed = json.loads(value) + except json.JSONDecodeError as exc: + raise click.BadParameter( + f"must be valid JSON ({exc.msg})", + param_hint=option_name, + ) from exc + if require_object and not isinstance(parsed, dict): + raise click.BadParameter("must be a JSON object", param_hint=option_name) + return parsed + + +@click.group("verified-domains") +@click.pass_context +def verified_domains_group(ctx): + """verified-domains resource commands.""" + +@verified_domains_group.command("list") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_list_(ctx, extra_params): + """List sending domains""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/verified-domains" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@verified_domains_group.command("create") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_create(ctx, data, extra_params): + """Add domain to account""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/verified-domains" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@verified_domains_group.command("delete") +@click.argument("DOMAIN_NAME") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_delete(ctx, domain_name, extra_params): + """Delete domain""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/verified-domains/{domain_name}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.delete(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out_ok("Deleted.") + +@verified_domains_group.command("get") +@click.argument("DOMAIN_NAME") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_get(ctx, domain_name, extra_params): + """Get domain info""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/verified-domains/{domain_name}" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + client = get_client() + try: + result = client.get(path, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) + +@verified_domains_group.command("verify") +@click.argument("DOMAIN_NAME") +@click.option("--data", default=None, help="Request body as JSON string.") +@click.option("--extra-params", default=None, help="Extra query params as JSON object, e.g. '{\"key\":\"val\"}'") +@click.pass_context +def _cmd_verify(ctx, domain_name, data, extra_params): + """Verify domain""" + from cli_anything.mailchimp.core.client import get_client, MailchimpError + from cli_anything.mailchimp.utils.output import _out, _out_ok, _out_err + path = f"/verified-domains/{domain_name}/actions/verify" + params = {} + if extra_params: + params.update(_parse_json_option(extra_params, "--extra-params", require_object=True)) + body = _parse_json_option(data, "--data") if data else None + client = get_client() + try: + result = client.post(path, json=body, params=params or None) + except MailchimpError as e: + _out_err(e.status, e.title, e.detail, e.raw) + return + _out(result) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/core/__init__.py b/mailchimp/agent-harness/cli_anything/mailchimp/core/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/core/__init__.py @@ -0,0 +1 @@ + diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/core/client.py b/mailchimp/agent-harness/cli_anything/mailchimp/core/client.py new file mode 100644 index 000000000..47348ae13 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/core/client.py @@ -0,0 +1,128 @@ +"""Mailchimp Marketing API v3.0 HTTP client.""" + +from __future__ import annotations + +import hashlib +import os +import sys +from typing import Any + +import requests + +_BASE = "https://{dc}.api.mailchimp.com/3.0" +_DEFAULT_TIMEOUT = 30 + + +def _server_prefix(api_key: str) -> str: + """Derive the data-centre prefix from the API key suffix (e.g. 'us8').""" + if "-" not in api_key: + raise ValueError( + "MAILCHIMP_API_KEY must include the data-centre suffix, " + "e.g. 'abc123-us8'." + ) + return api_key.rsplit("-", 1)[-1] + + +def subscriber_hash(email: str) -> str: + """MD5 hash of the lowercased email โ€” Mailchimp's subscriber identifier.""" + return hashlib.md5(email.strip().lower().encode()).hexdigest() + + +class MailchimpAuthError(Exception): + """Raised when no API key is available.""" + + +class MailchimpError(Exception): + def __init__(self, status: int, title: str, detail: str, raw: dict): + super().__init__(f"HTTP {status}: {title} โ€” {detail}") + self.status = status + self.title = title + self.detail = detail + self.raw = raw + + +class MailchimpClient: + def __init__(self, api_key: str | None = None): + key = api_key or os.environ.get("MAILCHIMP_API_KEY", "") + if not key: + raise MailchimpAuthError( + "MAILCHIMP_API_KEY is not set. " + "Export it before use: export MAILCHIMP_API_KEY=-" + ) + self._key = key + try: + self._dc = _server_prefix(key) + except ValueError as e: + raise MailchimpAuthError(str(e)) from e + self._base = _BASE.format(dc=self._dc) + self._session = requests.Session() + self._session.auth = ("anystring", key) + self._session.headers.update({"User-Agent": "cli-anything-mailchimp/0.1.0"}) + + # โ”€โ”€ Low-level request helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def _url(self, path: str) -> str: + return f"{self._base}/{path.lstrip('/')}" + + def _raise(self, resp: requests.Response) -> None: + if resp.ok: + return + try: + body = resp.json() + raise MailchimpError( + status=resp.status_code, + title=body.get("title", resp.reason), + detail=body.get("detail", ""), + raw=body, + ) + except ValueError: + raise MailchimpError( + status=resp.status_code, + title=resp.reason, + detail=resp.text[:200], + raw={}, + ) + + def get(self, path: str, params: dict | None = None) -> Any: + resp = self._session.get(self._url(path), params=params, timeout=_DEFAULT_TIMEOUT) + self._raise(resp) + return resp.json() + + def post(self, path: str, json: dict | None = None, params: dict | None = None) -> Any: + resp = self._session.post( + self._url(path), json=json, params=params, timeout=_DEFAULT_TIMEOUT + ) + self._raise(resp) + if resp.status_code == 204: + return {} + return resp.json() + + def patch(self, path: str, json: dict | None = None, params: dict | None = None) -> Any: + resp = self._session.patch( + self._url(path), json=json, params=params, timeout=_DEFAULT_TIMEOUT + ) + self._raise(resp) + return resp.json() + + def put(self, path: str, json: dict | None = None, params: dict | None = None) -> Any: + resp = self._session.put( + self._url(path), json=json, params=params, timeout=_DEFAULT_TIMEOUT + ) + self._raise(resp) + return resp.json() + + def delete(self, path: str, params: dict | None = None) -> dict: + resp = self._session.delete( + self._url(path), params=params, timeout=_DEFAULT_TIMEOUT + ) + self._raise(resp) + return {"ok": True} + + +def get_client() -> MailchimpClient: + """Return a client instance, printing an error and exiting if key is missing.""" + try: + return MailchimpClient() + except MailchimpAuthError as e: + print(f"Error: {e}", file=sys.stderr) + raise SystemExit(1) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/core/pagination.py b/mailchimp/agent-harness/cli_anything/mailchimp/core/pagination.py new file mode 100644 index 000000000..e4ed7e557 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/core/pagination.py @@ -0,0 +1,68 @@ +"""Generic count/offset paginator for the Mailchimp API.""" + +from __future__ import annotations + +from typing import Generator + +_PAGE_SIZE = 1000 + + +def paginate( + client, + path: str, + result_key: str, + params: dict | None = None, + page_size: int = _PAGE_SIZE, +) -> Generator[dict, None, None]: + """Yield all items from a paginated Mailchimp endpoint. + + Args: + client: MailchimpClient instance. + path: API path, e.g. "/lists". + result_key: Key inside the response that holds the item array. + params: Extra query params (count/offset will be added automatically). + page_size: Items per page. + """ + params = dict(params or {}) + params["count"] = page_size + offset = 0 + total: int | None = None + + while True: + params["offset"] = offset + data = client.get(path, params=params) + items: list = data.get(result_key, []) + + if total is None: + total = data.get("total_items", None) + + yield from items + + offset += len(items) + # Stop when we have fetched all items or got an empty page + if not items or (total is not None and offset >= total): + break + + +def collect( + client, + path: str, + result_key: str, + params: dict | None = None, + page_size: int = _PAGE_SIZE, +) -> tuple[list[dict], int]: + """Return (items, total_items) โ€” fetches a single page by default. + + When the caller passes explicit count/offset in params those are respected; + otherwise a single page of page_size is fetched. + """ + params = dict(params or {}) + if "count" not in params: + params["count"] = page_size + if "offset" not in params: + params["offset"] = 0 + + data = client.get(path, params=params) + items = data.get(result_key, []) + total = data.get("total_items", len(items)) + return items, total diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/mailchimp_cli.py b/mailchimp/agent-harness/cli_anything/mailchimp/mailchimp_cli.py new file mode 100644 index 000000000..7587e8467 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/mailchimp_cli.py @@ -0,0 +1,93 @@ +"""cli-anything harness for the Mailchimp Marketing API v3.0.""" + +from __future__ import annotations + +import click + +import cli_anything.mailchimp.utils.output as _output_mod +from cli_anything.mailchimp.commands import ALL_GROUPS + + +@click.group(invoke_without_command=True) +@click.option("--json", "use_json", is_flag=True, default=False, help="Output as JSON.") +@click.version_option("0.1.0", prog_name="cli-anything-mailchimp") +@click.pass_context +def cli(ctx: click.Context, use_json: bool) -> None: + """cli-anything harness for the Mailchimp Marketing API v3.0. + + Set MAILCHIMP_API_KEY before use: + + export MAILCHIMP_API_KEY=- + + Run without arguments to enter the interactive REPL. + """ + ctx.ensure_object(dict) + _output_mod.USE_JSON = use_json + if ctx.invoked_subcommand is None: + _start_repl() + + +# Register all generated resource groups +for _group in ALL_GROUPS: + cli.add_command(_group) + + +def main() -> None: + """Entry point for the Click CLI.""" + cli() + + +def _start_repl() -> None: + """Interactive REPL using prompt_toolkit.""" + from cli_anything.mailchimp.utils.repl_skin import ReplSkin + import shlex + + skin = ReplSkin("mailchimp", version="0.1.0") + skin.print_banner() + + pt_session = skin.create_prompt_session() + + while True: + try: + raw = skin.get_input(pt_session) + except (KeyboardInterrupt, EOFError): + skin.print_goodbye() + break + + line = raw.strip() + if not line: + continue + if line in ("quit", "exit", "q"): + skin.print_goodbye() + break + if line in ("help", "?"): + _print_repl_help(skin) + continue + + try: + args = shlex.split(line) + except ValueError as e: + skin.error(f"Parse error: {e}") + continue + + try: + cli.main(args=args, standalone_mode=False) + except SystemExit: + pass + except click.UsageError as e: + skin.error(str(e)) + except Exception as e: + skin.error(str(e)) + + +def _print_repl_help(skin: object) -> None: + from cli_anything.mailchimp.commands import ALL_GROUPS + + commands = {g.name: (g.help or "").split("\n")[0] for g in ALL_GROUPS} + commands["--help"] = "Show help for any command" + commands["quit"] = "Exit the REPL" + skin.help(commands) # type: ignore[attr-defined] + + +if __name__ == "__main__": + main() diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/skills/SKILL.md b/mailchimp/agent-harness/cli_anything/mailchimp/skills/SKILL.md new file mode 100644 index 000000000..c730e9f6c --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/skills/SKILL.md @@ -0,0 +1,228 @@ +--- +name: cli-anything-mailchimp +description: CLI harness for the Mailchimp Marketing API v3.0 โ€” 303 commands across 30 resource groups (lists, campaigns, reports, automations, ecommerce, templates, and more). Supports JSON output and interactive REPL mode. +--- + +# cli-anything-mailchimp + +## Identity + +An agent-native CLI for the [Mailchimp Marketing API v3.0](https://mailchimp.com/developer/marketing/docs/fundamentals/), built on the [CLI-Anything](https://github.com/HKUDS/CLI-Anything) framework. + +## What This CLI Does + +- Manage **audiences (lists)** โ€” create, update, delete lists; add/update/archive members; manage merge fields, segments, tags, and webhooks. +- Run **campaigns** โ€” create, schedule, send, pause, replicate, and analyse email campaigns. +- Read **reports** โ€” open rates, click rates, bounce stats, unsubscribes, email activity, geographic data. +- Control **automations** โ€” create and manage automated email workflows. +- Manage **e-commerce** โ€” stores, orders, customers, products, carts, and promo codes. +- Use **templates, file manager, landing pages, SMS campaigns, surveys**, and all other Marketing API resources. + +## Prerequisites + +- Python 3.10+ +- `MAILCHIMP_API_KEY` environment variable set to your API key (including datacenter suffix, e.g. `abc123-us8`) + +## Installation + +```bash +# From the CLI-Anything repo (once merged): +pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=mailchimp/agent-harness + +# During development: +cd mailchimp/agent-harness && pip install -e . +``` + +## Command Reference + +### Root + +| Command | Description | +|---|---| +| `cli-anything-mailchimp ping` | Health check โ€” confirms API connectivity | +| `cli-anything-mailchimp root list` | Get account info | +| `cli-anything-mailchimp --json ` | Output any command as JSON | +| `cli-anything-mailchimp` | Launch interactive REPL | + +### Lists (Audiences) + +| Command | Description | +|---|---| +| `lists list` | List all audiences | +| `lists get ` | Get audience info | +| `lists create --data ''` | Create audience | +| `lists update --data ''` | Update audience | +| `lists delete ` | Delete audience | +| `lists list-lists-id-members ` | List members | +| `lists get-lists-id-members-id ` | Get member by MD5 hash | +| `lists create-lists-id-members --data ''` | Add member | +| `lists list-lists-id-merge-fields ` | List merge fields | +| `lists create-lists-id-merge-fields --data ''` | Add merge field | +| `lists list-lists-id-segments ` | List segments | +| `lists list-list-member-tags ` | List member tags | +| `lists create-list-member-tags --data ''` | Add/remove member tags | +| `lists list-lists-id-webhooks ` | List webhooks | +| `lists create-lists-id-webhooks --data ''` | Add webhook | + +### Campaigns + +| Command | Description | +|---|---| +| `campaigns list` | List campaigns | +| `campaigns get ` | Get campaign info | +| `campaigns create --data ''` | Create campaign | +| `campaigns update --data ''` | Update campaign settings | +| `campaigns delete ` | Delete campaign | +| `campaigns send ` | Send campaign immediately | +| `campaigns schedule --data ''` | Schedule campaign | +| `campaigns cancel-send ` | Cancel scheduled send | +| `campaigns pause ` | Pause RSS campaign | +| `campaigns resume ` | Resume RSS campaign | +| `campaigns replicate ` | Duplicate campaign | +| `campaigns list-content ` | Get campaign content | +| `campaigns list-send-checklist ` | Pre-send checklist | + +### Reports + +| Command | Description | +|---|---| +| `reports list` | List all campaign reports | +| `reports get ` | Get campaign summary report | +| `reports list-email-activity ` | Per-subscriber open/click activity | +| `reports list-click-details ` | Link click breakdown | +| `reports list-open-details ` | Per-subscriber opens | +| `reports list-unsubscribed ` | Unsubscribers | +| `reports list-locations ` | Geographic breakdown | +| `reports list-domain-performance ` | Per-domain stats | + +### Automations + +| Command | Description | +|---|---| +| `automations list` | List automations | +| `automations get ` | Get automation info | +| `automations create --data ''` | Create automation | +| `automations pause ` | Pause automation | +| `automations start ` | Start automation | +| `automations archive ` | Archive automation | +| `automations list-emails ` | List automation emails | + +### E-commerce + +| Command | Description | +|---|---| +| `ecommerce list-ecommerce-stores` | List stores | +| `ecommerce get ` | Get store info | +| `ecommerce create --data ''` | Add store | +| `ecommerce list-ecommerce-stores-id-orders ` | List orders | +| `ecommerce list-ecommerce-stores-id-products ` | List products | +| `ecommerce list-ecommerce-stores-id-customers ` | List customers | +| `ecommerce list-ecommerce-stores-id-carts ` | List carts | +| `ecommerce list-ecommerce-stores-id-promocodes ` | List promo codes | + +### Other Resources + +| Group | Description | +|---|---| +| `templates` | Email templates (list, get, create, update, delete) | +| `template-folders` | Template folders | +| `campaign-folders` | Campaign folders | +| `file-manager` | Files and folders in the file manager | +| `landing-pages` | Landing pages (list, create, publish, unpublish) | +| `sms-campaigns` | SMS campaigns (10 operations) | +| `surveys` | Surveys (list, get, publish) | +| `reporting` | Facebook ad and landing page reporting | +| `search-campaigns` | Search campaigns by query | +| `search-members` | Search members across all audiences | +| `batches` | Batch API operations | +| `batch-webhooks` | Batch operation webhooks | +| `verified-domains` | Email domain verification | +| `authorized-apps` | OAuth connected apps | +| `connected-sites` | Connected site integrations | +| `conversations` | Inbox conversations | +| `activity-feed` | Account activity feed | +| `account-exports` | Account data exports | + +## JSON Output + +All commands support `--json` at the root level: + +```bash +# List all audiences as JSON +cli-anything-mailchimp --json lists list + +# Get a campaign report as JSON +cli-anything-mailchimp --json reports get abc123def + +# Pipe to jq โ€” use the native Mailchimp field name for the resource +cli-anything-mailchimp --json lists list | jq '.lists[].name' +cli-anything-mailchimp --json campaigns list | jq '.campaigns[].id' +``` + +**Envelope shapes** (native Mailchimp API response โ€” use the resource-specific key): + +```json +// List endpoints โ€” key matches the resource name (lists, campaigns, members, etc.) +{"lists": [...], "total_items": 42, "_links": [...]} +{"campaigns": [...], "total_items": 10, "_links": [...]} + +// Single resource GET / POST / PATCH +{"id": "abc123", "name": "My List", ...} + +// DELETE +{"ok": true, "message": "Deleted."} + +// Error +{"ok": false, "message": "Resource Not Found: ...", "data": {...}} +``` + +## Common Agent Patterns + +```bash +# Get account health +cli-anything-mailchimp --json ping | jq '.health_status' + +# List all audience IDs and names +cli-anything-mailchimp --json lists list | jq '.lists[] | {id, name}' + +# Find all subscribed members in an audience +cli-anything-mailchimp --json lists list-lists-id-members --status subscribed | jq '.members[].email_address' + +# Create a campaign and get its send checklist +cli-anything-mailchimp --json campaigns create --data '{"type":"regular","settings":{"subject_line":"Hello","from_name":"Me","reply_to":"me@example.com"}}' | jq '.id' +cli-anything-mailchimp --json campaigns list-send-checklist | jq '.items[] | select(.result == false)' + +# Get unsubscribes for a sent campaign +cli-anything-mailchimp --json reports list-unsubscribed | jq '.unsubscribes[].email_address' + +# Add a member to an audience (subscriber hash = MD5 of lowercased email) +cli-anything-mailchimp --json lists create-members --data '{"email_address":"user@example.com","status":"subscribed"}' + +# Search for a member across all audiences +cli-anything-mailchimp --json search-members list --query "user@example.com" | jq '.exact_matches.members[]' +``` + +## Interactive REPL + +Run `cli-anything-mailchimp` with no arguments to enter the REPL: + +``` +โ—† cli-anything ยท Mailchimp + v0.1.0 + Type help for commands, quit to exit + +โ—† mailchimp โฏ ping + โœ“ {"health_status": "Everything's Chimpy!"} + +โ—† mailchimp โฏ --json lists list +{"lists": [...], "total_items": 3, "_links": [...]} + +โ—† mailchimp โฏ quit +``` + +## Notes + +- **Subscriber hash**: Mailchimp identifies members by the MD5 hash of their lowercased email. Compute with `python -c "import hashlib; email='email@example.com'; print(hashlib.md5(email.strip().lower().encode()).hexdigest())"`. +- **Body payloads**: All POST/PATCH/PUT commands accept `--data ''`. See [Mailchimp API docs](https://mailchimp.com/developer/marketing/api/) for the schema of each endpoint. +- **Datacenter**: Your API key ends in `-us8`, `-eu2`, etc. The CLI extracts this automatically โ€” include it in `MAILCHIMP_API_KEY`. +- **Rate limits**: The Marketing API rate-limits at 10 concurrent connections and a rolling per-account limit. For bulk operations, use the `batches` group. diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/tests/TEST.md b/mailchimp/agent-harness/cli_anything/mailchimp/tests/TEST.md new file mode 100644 index 000000000..06cb3bda9 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/tests/TEST.md @@ -0,0 +1,39 @@ +# Test Guide โ€” cli-anything-mailchimp + +## Prerequisites + +```bash +pip install -e ".[dev]" +# dev extras: pytest, pytest-cov, responses +``` + +## Unit tests (no API key needed) + +```bash +cd mailchimp/agent-harness +pytest cli_anything/mailchimp/tests/test_core.py -v +``` + +Expected: all collected tests pass. Runtime < 5 seconds. + +## Live E2E tests (requires MAILCHIMP_API_KEY) + +```bash +export MAILCHIMP_API_KEY=- +pytest cli_anything/mailchimp/tests/test_full_e2e.py -v -s +``` + +Expected: 9 tests. The fixture creates a throwaway audience, runs member and +merge-field operations against it, then deletes it. Runtime ~15โ€“30 seconds. + +Cleanup is automatic (the `test_list` fixture deletes the audience in a +`finally` block). If a run is interrupted, delete the `cli-anything-test-*` +list from your Mailchimp account manually. + +## Coverage + +```bash +pytest cli_anything/mailchimp/tests/test_core.py --cov=cli_anything.mailchimp.core --cov-report=term-missing +``` + +Target: โ‰ฅ 80% line coverage on `core/`. diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/tests/test_core.py b/mailchimp/agent-harness/cli_anything/mailchimp/tests/test_core.py new file mode 100644 index 000000000..61a1f0b66 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/tests/test_core.py @@ -0,0 +1,566 @@ +"""Unit tests for cli-anything-mailchimp core modules.""" + +from __future__ import annotations + +import json +import sys +import unittest +from unittest.mock import MagicMock, patch + +import responses as resp_lib +import requests + +# โ”€โ”€ client tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + +class TestServerPrefix(unittest.TestCase): + def test_extracts_suffix(self): + from cli_anything.mailchimp.core.client import _server_prefix + + assert _server_prefix("abc123-us8") == "us8" + assert _server_prefix("xyz-eu2") == "eu2" + + def test_missing_suffix_raises(self): + from cli_anything.mailchimp.core.client import _server_prefix + + with self.assertRaises(ValueError): + _server_prefix("nodashinkey") + + +class TestSubscriberHash(unittest.TestCase): + def test_md5_lowercased(self): + from cli_anything.mailchimp.core.client import subscriber_hash + + # Known MD5 of "test@example.com" + assert subscriber_hash("test@example.com") == "55502f40dc8b7c769880b10874abc9d0" + # Should normalise to lowercase before hashing + assert subscriber_hash("TEST@EXAMPLE.COM") == subscriber_hash("test@example.com") + + def test_strips_whitespace(self): + from cli_anything.mailchimp.core.client import subscriber_hash + + assert subscriber_hash(" test@example.com ") == subscriber_hash("test@example.com") + + +class TestMailchimpClient(unittest.TestCase): + def _make_client(self, key: str = "testkey-us1"): + from cli_anything.mailchimp.core.client import MailchimpClient + + return MailchimpClient(api_key=key) + + def test_base_url(self): + client = self._make_client("abc-us8") + assert client._base == "https://us8.api.mailchimp.com/3.0" + + def test_auth_header(self): + client = self._make_client("abc-us8") + assert client._session.auth == ("anystring", "abc-us8") + + def test_missing_key_raises_auth_error(self): + from cli_anything.mailchimp.core.client import MailchimpClient, MailchimpAuthError + import os + + orig = os.environ.pop("MAILCHIMP_API_KEY", None) + try: + with self.assertRaises(MailchimpAuthError): + MailchimpClient(api_key=None) + finally: + if orig: + os.environ["MAILCHIMP_API_KEY"] = orig + + def test_get_client_exits_on_missing_key(self): + from cli_anything.mailchimp.core.client import get_client + import os + + orig = os.environ.pop("MAILCHIMP_API_KEY", None) + try: + with self.assertRaises(SystemExit): + get_client() + finally: + if orig: + os.environ["MAILCHIMP_API_KEY"] = orig + + def test_get_client_exits_cleanly_on_key_without_suffix(self): + from cli_anything.mailchimp.core.client import get_client + import os + + orig = os.environ.get("MAILCHIMP_API_KEY") + os.environ["MAILCHIMP_API_KEY"] = "invalid" + try: + with self.assertRaises(SystemExit): + get_client() + finally: + if orig is None: + os.environ.pop("MAILCHIMP_API_KEY", None) + else: + os.environ["MAILCHIMP_API_KEY"] = orig + + @resp_lib.activate + def test_get_success(self): + from cli_anything.mailchimp.core.client import MailchimpClient + + client = MailchimpClient(api_key="key-us1") + resp_lib.add( + resp_lib.GET, + "https://us1.api.mailchimp.com/3.0/ping", + json={"health_status": "Everything's Chimpy!"}, + status=200, + ) + result = client.get("/ping") + assert result["health_status"] == "Everything's Chimpy!" + + @resp_lib.activate + def test_get_error_raises(self): + from cli_anything.mailchimp.core.client import MailchimpClient, MailchimpError + + client = MailchimpClient(api_key="key-us1") + resp_lib.add( + resp_lib.GET, + "https://us1.api.mailchimp.com/3.0/lists/bad", + json={"title": "Resource Not Found", "detail": "The requested resource could not be found.", "status": 404}, + status=404, + ) + with self.assertRaises(MailchimpError) as ctx: + client.get("/lists/bad") + assert ctx.exception.status == 404 + assert "Resource Not Found" in ctx.exception.title + + @resp_lib.activate + def test_post_success(self): + from cli_anything.mailchimp.core.client import MailchimpClient + + client = MailchimpClient(api_key="key-us1") + resp_lib.add( + resp_lib.POST, + "https://us1.api.mailchimp.com/3.0/lists", + json={"id": "abc123", "name": "My List"}, + status=200, + ) + result = client.post("/lists", json={"name": "My List"}) + assert result["id"] == "abc123" + + @resp_lib.activate + def test_delete_returns_ok(self): + from cli_anything.mailchimp.core.client import MailchimpClient + + client = MailchimpClient(api_key="key-us1") + resp_lib.add( + resp_lib.DELETE, + "https://us1.api.mailchimp.com/3.0/lists/abc123", + status=204, + ) + result = client.delete("/lists/abc123") + assert result == {"ok": True} + + def test_patch_forwards_query_params(self): + from cli_anything.mailchimp.core.client import MailchimpClient + + client = MailchimpClient(api_key="key-us1") + client._session.patch = MagicMock() + client._session.patch.return_value.ok = True + client._session.patch.return_value.json.return_value = {"id": "contact-1"} + + result = client.patch( + "/audiences/audience-1/contacts/contact-1", + json={"email_address": "user@example.com"}, + params={"data_mode": "sync"}, + ) + + assert result == {"id": "contact-1"} + client._session.patch.assert_called_once_with( + "https://us1.api.mailchimp.com/3.0/audiences/audience-1/contacts/contact-1", + json={"email_address": "user@example.com"}, + params={"data_mode": "sync"}, + timeout=30, + ) + + def test_put_forwards_query_params(self): + from cli_anything.mailchimp.core.client import MailchimpClient + + client = MailchimpClient(api_key="key-us1") + client._session.put = MagicMock() + client._session.put.return_value.ok = True + client._session.put.return_value.json.return_value = {"id": "member-1"} + + result = client.put( + "/lists/list-1/members/hash-1", + json={"email_address": "user@example.com"}, + params={"skip_merge_validation": True}, + ) + + assert result == {"id": "member-1"} + client._session.put.assert_called_once_with( + "https://us1.api.mailchimp.com/3.0/lists/list-1/members/hash-1", + json={"email_address": "user@example.com"}, + params={"skip_merge_validation": True}, + timeout=30, + ) + + def test_delete_forwards_query_params(self): + from cli_anything.mailchimp.core.client import MailchimpClient + + client = MailchimpClient(api_key="key-us1") + client._session.delete = MagicMock() + client._session.delete.return_value.ok = True + + result = client.delete("/lists/list-1", params={"force": True}) + + assert result == {"ok": True} + client._session.delete.assert_called_once_with( + "https://us1.api.mailchimp.com/3.0/lists/list-1", + params={"force": True}, + timeout=30, + ) + + +# โ”€โ”€ pagination tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + +class TestPagination(unittest.TestCase): + def _mock_client(self, pages: list[list]) -> MagicMock: + client = MagicMock() + side_effects = [ + {"lists": page, "total_items": sum(len(p) for p in pages)} + for page in pages + ] + client.get.side_effect = side_effects + return client + + def test_single_page(self): + from cli_anything.mailchimp.core.pagination import paginate + + client = self._mock_client([[{"id": "1"}, {"id": "2"}]]) + items = list(paginate(client, "/lists", "lists", page_size=100)) + assert items == [{"id": "1"}, {"id": "2"}] + assert client.get.call_count == 1 + + def test_multiple_pages(self): + from cli_anything.mailchimp.core.pagination import paginate + + page1 = [{"id": str(i)} for i in range(5)] + page2 = [{"id": str(i)} for i in range(5, 8)] + client = self._mock_client([page1, page2]) + items = list(paginate(client, "/lists", "lists", page_size=5)) + assert len(items) == 8 + assert client.get.call_count == 2 + + def test_empty_result(self): + from cli_anything.mailchimp.core.pagination import paginate + + client = self._mock_client([[]]) + items = list(paginate(client, "/lists", "lists")) + assert items == [] + + def test_exact_page_boundary_no_extra_fetch(self): + """When total_items == page_size, paginator must not fetch a second empty page (I6 fix).""" + from cli_anything.mailchimp.core.pagination import paginate + + page = [{"id": str(i)} for i in range(5)] + client = MagicMock() + # First call returns exactly page_size items with total_items matching + client.get.return_value = {"lists": page, "total_items": 5} + items = list(paginate(client, "/lists", "lists", page_size=5)) + assert len(items) == 5 + assert client.get.call_count == 1 # must not make a second call + + def test_collect_returns_total(self): + from cli_anything.mailchimp.core.pagination import collect + + client = MagicMock() + client.get.return_value = {"lists": [{"id": "1"}], "total_items": 42} + items, total = collect(client, "/lists", "lists") + assert items == [{"id": "1"}] + assert total == 42 + + +# โ”€โ”€ output tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + +class TestOutput(unittest.TestCase): + def setUp(self): + import cli_anything.mailchimp.utils.output as out + self._orig = out.USE_JSON + out.USE_JSON = False + + def tearDown(self): + import cli_anything.mailchimp.utils.output as out + out.USE_JSON = self._orig + + def test_json_mode_outputs_json(self): + import cli_anything.mailchimp.utils.output as out + import io + + out.USE_JSON = True + captured = io.StringIO() + with patch("builtins.print", lambda *a, **kw: captured.write(str(a[0]) + "\n")): + out._out({"key": "value"}) + + parsed = json.loads(captured.getvalue()) + assert parsed["key"] == "value" + +# โ”€โ”€ smoke import tests โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + +class TestGeneratedCommandsImport(unittest.TestCase): + """Verify every generated command module imports cleanly and registers commands. + + This catches codegen regressions like C1 (builtin shadowing) which would + cause Click to fail silently or raise at import time. + """ + + def test_all_groups_importable(self): + from cli_anything.mailchimp.commands import ALL_GROUPS + + assert len(ALL_GROUPS) == 30, f"Expected 30 groups, got {len(ALL_GROUPS)}" + for group in ALL_GROUPS: + assert group.name is not None + assert len(group.commands) > 0, f"Group {group.name!r} has no commands" + + def test_generator_preserves_complete_first_line_help(self): + from cli_anything.mailchimp._codegen.generate import _click_help_text + + description = ( + "Used for [pagination](https://mailchimp.com/developer/marketing/docs/fundamentals/#pagination) " + "with enough context to exceed eighty characters.\nSecond line omitted." + ) + + help_text = _click_help_text(description) + + assert help_text.endswith("eighty characters.") + assert "\n" not in help_text + + def test_no_builtin_shadowing_in_function_names(self): + """Ensure generated functions are prefixed with _cmd_ (not builtins).""" + import glob + import ast + import builtins as _builtins + + builtin_names = set(dir(_builtins)) + issues = [] + + for path in glob.glob("cli_anything/mailchimp/commands/*.py"): + tree = ast.parse(open(path).read()) + for node in ast.walk(tree): + if isinstance(node, ast.FunctionDef): + if node.name in builtin_names: + issues.append(f"{path}: def {node.name}()") + + assert not issues, "Builtin shadowing in generated code:\n" + "\n".join(issues) + + def test_all_commands_have_extra_params(self): + """Every generated command must accept --extra-params (I3 fix).""" + from cli_anything.mailchimp.commands import ALL_GROUPS + import click + + missing = [] + for group in ALL_GROUPS: + for cmd_name, cmd in group.commands.items(): + if isinstance(cmd, click.Group): + continue + param_names = [p.name for p in cmd.params] + if "extra_params" not in param_names: + missing.append(f"{group.name} {cmd_name}") + + assert not missing, "--extra-params missing on:\n" + "\n".join(missing) + + def test_generated_patch_command_forwards_query_params(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.audiences import audiences_group + + client = MagicMock() + client.patch.return_value = {"id": "contact-1"} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + result = CliRunner().invoke( + audiences_group, + [ + "update", + "audience-1", + "contact-1", + "--data", + '{"email_address":"user@example.com"}', + "--data-mode", + "sync", + ], + ) + + assert result.exit_code == 0, result.output + client.patch.assert_called_once_with( + "/audiences/audience-1/contacts/contact-1", + json={"email_address": "user@example.com"}, + params={"data_mode": "sync"}, + ) + + def test_generated_put_command_forwards_query_params(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.lists import lists_group + + client = MagicMock() + client.put.return_value = {"id": "member-1"} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + result = CliRunner().invoke( + lists_group, + [ + "update-3", + "list-1", + "hash-1", + "--data", + '{"email_address":"user@example.com"}', + "--skip-merge-validation", + "true", + ], + ) + + assert result.exit_code == 0, result.output + client.put.assert_called_once_with( + "/lists/list-1/members/hash-1", + json={"email_address": "user@example.com"}, + params={"skip_merge_validation": True}, + ) + + def test_generated_keyword_query_option_uses_safe_callback_name(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.templates import templates_group + + client = MagicMock() + client.get.return_value = {"templates": []} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + result = CliRunner().invoke(templates_group, ["list", "--type", "user"]) + + assert result.exit_code == 0, result.output + client.get.assert_called_once_with("/templates", params={"type": "user"}) + + def test_campaign_shortcut_aliases_match_generated_commands(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.campaigns import campaigns_group + + client = MagicMock() + client.get.return_value = {"items": []} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + content = CliRunner().invoke(campaigns_group, ["list-content", "campaign-1"]) + checklist = CliRunner().invoke(campaigns_group, ["list-send-checklist", "campaign-1"]) + + assert content.exit_code == 0, content.output + assert checklist.exit_code == 0, checklist.output + client.get.assert_any_call("/campaigns/campaign-1/content", params=None) + client.get.assert_any_call("/campaigns/campaign-1/send-checklist", params=None) + + def test_report_shortcut_aliases_match_generated_commands(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.reports import reports_group + + client = MagicMock() + client.get.return_value = {"items": []} + + shortcuts = { + "list-email-activity": "/reports/campaign-1/email-activity", + "list-click-details": "/reports/campaign-1/click-details", + "list-open-details": "/reports/campaign-1/open-details", + "list-unsubscribed": "/reports/campaign-1/unsubscribed", + "list-locations": "/reports/campaign-1/locations", + "list-domain-performance": "/reports/campaign-1/domain-performance", + } + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + for command in shortcuts: + result = CliRunner().invoke(reports_group, [command, "campaign-1"]) + assert result.exit_code == 0, result.output + + for path in shortcuts.values(): + client.get.assert_any_call(path, params=None) + + def test_automation_and_segment_shortcut_aliases_match_generated_commands(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.automations import automations_group + from cli_anything.mailchimp.commands.lists import lists_group + + client = MagicMock() + client.get.return_value = {"items": []} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + emails = CliRunner().invoke(automations_group, ["list-emails", "workflow-1"]) + segments = CliRunner().invoke(lists_group, ["list-lists-id-segments", "list-1"]) + + assert emails.exit_code == 0, emails.output + assert segments.exit_code == 0, segments.output + client.get.assert_any_call("/automations/workflow-1/emails", params=None) + client.get.assert_any_call("/lists/list-1/segments", params=None) + + def test_ping_group_invokes_health_check_without_list_subcommand(self): + from click.testing import CliRunner + from cli_anything.mailchimp.mailchimp_cli import cli + + client = MagicMock() + client.get.return_value = {"health_status": "Everything's Chimpy!"} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + result = CliRunner().invoke(cli, ["ping"]) + + assert result.exit_code == 0, result.output + client.get.assert_called_once_with("/ping", params=None) + + def test_create_members_alias_matches_generated_command(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.lists import lists_group + + client = MagicMock() + client.post.return_value = {"id": "member-1"} + + with patch("cli_anything.mailchimp.core.client.get_client", return_value=client): + result = CliRunner().invoke( + lists_group, + [ + "create-members", + "list-1", + "--data", + '{"email_address":"user@example.com","status":"subscribed"}', + "--skip-merge-validation", + "true", + ], + ) + + assert result.exit_code == 0, result.output + client.post.assert_called_once_with( + "/lists/list-1/members", + json={"email_address": "user@example.com", "status": "subscribed"}, + params={"skip_merge_validation": True}, + ) + + def test_invalid_data_json_reports_click_error(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.lists import lists_group + + result = CliRunner().invoke(lists_group, ["create", "--data", "{bad"]) + + assert result.exit_code == 2 + assert "Invalid value for --data" in result.output + assert "valid JSON" in result.output + assert "Traceback" not in result.output + + def test_extra_params_must_be_json_object(self): + from click.testing import CliRunner + from cli_anything.mailchimp.commands.lists import lists_group + + result = CliRunner().invoke(lists_group, ["list", "--extra-params", "[]"]) + + assert result.exit_code == 2 + assert "Invalid value for --extra-params" in result.output + assert "JSON object" in result.output + assert "Traceback" not in result.output + + def test_cli_without_subcommand_starts_repl_through_click(self): + from click.testing import CliRunner + import cli_anything.mailchimp.mailchimp_cli as mailchimp_cli + + with patch.object(mailchimp_cli, "_start_repl") as start_repl: + result = CliRunner().invoke(mailchimp_cli.cli, []) + + assert result.exit_code == 0, result.output + start_repl.assert_called_once_with() + + +if __name__ == "__main__": + unittest.main() diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/tests/test_full_e2e.py b/mailchimp/agent-harness/cli_anything/mailchimp/tests/test_full_e2e.py new file mode 100644 index 000000000..db85dabc1 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/tests/test_full_e2e.py @@ -0,0 +1,127 @@ +"""End-to-end tests against the live Mailchimp API. + +Skipped unless MAILCHIMP_API_KEY is set. Creates a throwaway audience, +exercises member and merge-field operations, then cleans up. + +Run: + MAILCHIMP_API_KEY=- pytest tests/test_full_e2e.py -v -s +""" + +from __future__ import annotations + +import os +import uuid +import pytest + +pytestmark = pytest.mark.skipif( + not os.environ.get("MAILCHIMP_API_KEY"), + reason="MAILCHIMP_API_KEY not set โ€” skipping live API tests", +) + +TEST_LIST_NAME = f"cli-anything-test-{uuid.uuid4().hex[:8]}" +TEST_EMAIL = f"cli-test-{uuid.uuid4().hex[:8]}@example.com" + + +@pytest.fixture(scope="module") +def client(): + from cli_anything.mailchimp.core.client import MailchimpClient + + return MailchimpClient() + + +@pytest.fixture(scope="module") +def test_list(client): + """Create a throwaway Mailchimp audience, yield its ID, then delete it.""" + body = { + "name": TEST_LIST_NAME, + "contact": { + "company": "CLI-Anything Test", + "address1": "123 Test St", + "city": "Testville", + "state": "CA", + "zip": "90210", + "country": "US", + }, + "permission_reminder": "test permission reminder", + "email_type_option": False, + "campaign_defaults": { + "from_name": "CLI Test", + "from_email": "test@example.com", + "subject": "Test", + "language": "en", + }, + } + result = client.post("/lists", json=body) + list_id = result["id"] + yield list_id + # Cleanup โ€” delete the test list + try: + client.delete(f"/lists/{list_id}") + except Exception: + pass + + +class TestPing: + def test_ping(self, client): + result = client.get("/ping") + assert "health_status" in result + + +class TestLists: + def test_get_lists(self, client): + result = client.get("/lists", params={"count": 1}) + assert "lists" in result + assert isinstance(result["lists"], list) + + def test_create_and_get_list(self, client, test_list): + result = client.get(f"/lists/{test_list}") + assert result["id"] == test_list + assert result["name"] == TEST_LIST_NAME + + def test_update_list(self, client, test_list): + new_name = TEST_LIST_NAME + "-updated" + result = client.patch(f"/lists/{test_list}", json={"name": new_name}) + assert result["name"] == new_name + # Restore + client.patch(f"/lists/{test_list}", json={"name": TEST_LIST_NAME}) + + +class TestMembers: + def test_add_member(self, client, test_list): + body = { + "email_address": TEST_EMAIL, + "status": "subscribed", + } + result = client.post(f"/lists/{test_list}/members", json=body) + assert result["email_address"] == TEST_EMAIL + assert result["status"] == "subscribed" + + def test_get_member(self, client, test_list): + from cli_anything.mailchimp.core.client import subscriber_hash + + h = subscriber_hash(TEST_EMAIL) + result = client.get(f"/lists/{test_list}/members/{h}") + assert result["email_address"] == TEST_EMAIL + + def test_list_members(self, client, test_list): + result = client.get(f"/lists/{test_list}/members", params={"count": 10}) + emails = [m["email_address"] for m in result.get("members", [])] + assert TEST_EMAIL in emails + + def test_archive_member(self, client, test_list): + from cli_anything.mailchimp.core.client import subscriber_hash + + h = subscriber_hash(TEST_EMAIL) + result = client.delete(f"/lists/{test_list}/members/{h}") + assert result == {"ok": True} + + +class TestMergeFields: + def test_create_and_list_merge_fields(self, client, test_list): + body = {"tag": "TESTFIELD", "name": "Test Field", "type": "text"} + result = client.post(f"/lists/{test_list}/merge-fields", json=body) + assert result["tag"] == "TESTFIELD" + + fields = client.get(f"/lists/{test_list}/merge-fields") + tags = [f["tag"] for f in fields.get("merge_fields", [])] + assert "TESTFIELD" in tags diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/utils/__init__.py b/mailchimp/agent-harness/cli_anything/mailchimp/utils/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/utils/__init__.py @@ -0,0 +1 @@ + diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/utils/output.py b/mailchimp/agent-harness/cli_anything/mailchimp/utils/output.py new file mode 100644 index 000000000..1b5bc8fe8 --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/utils/output.py @@ -0,0 +1,86 @@ +"""JSON / human output helpers for cli-anything-mailchimp.""" + +from __future__ import annotations + +import json +import sys +from typing import Any + +# Module-level flag set by the root CLI group's --json option. +USE_JSON: bool = False + + +def _out(data: Any) -> None: + """Print data as JSON (when --json) or human-readable text.""" + if USE_JSON: + print(json.dumps(data, indent=2, default=str)) + elif isinstance(data, dict): + _print_dict(data) + elif isinstance(data, list): + _print_list(data) + else: + print(data) + + +def _out_ok(message: str, data: dict | None = None) -> None: + """Print a success/mutation result. + + JSON shape: {"ok": true, "message": ""} or {"ok": true, "message": "...", "data": {...}} + """ + if USE_JSON: + payload: dict = {"ok": True, "message": message} + if data: + payload["data"] = data + print(json.dumps(payload, indent=2, default=str)) + else: + print(f" \033[38;5;78mโœ“\033[0m {message}") + if data: + _print_dict(data) + + +def _out_err(status: int, title: str, detail: str, raw: dict | None = None) -> None: + """Print an error and exit non-zero.""" + if USE_JSON: + print( + json.dumps( + {"ok": False, "message": f"{title}: {detail}", "data": raw or {}}, + indent=2, + ), + file=sys.stderr, + ) + else: + print(f" \033[38;5;196mโœ—\033[0m HTTP {status}: {title}", file=sys.stderr) + if detail: + print(f" {detail}", file=sys.stderr) + sys.exit(1) + + +# โ”€โ”€ Formatting helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + +_GRAY = "\033[38;5;245m" +_WHITE = "\033[97m" +_CYAN = "\033[38;5;80m" +_RESET = "\033[0m" + + +def _print_dict(d: dict, indent: int = 2) -> None: + prefix = " " * indent + for k, v in d.items(): + key = f"{_GRAY}{k}:{_RESET}" + if isinstance(v, dict): + print(f"{prefix}{key}") + _print_dict(v, indent + 2) + elif isinstance(v, list): + print(f"{prefix}{key} [{len(v)} items]") + else: + print(f"{prefix}{key} {_WHITE}{v}{_RESET}") + + +def _print_list(items: list, indent: int = 2) -> None: + for item in items: + if isinstance(item, dict): + _print_dict(item, indent) + print() + else: + print(" " * indent + str(item)) diff --git a/mailchimp/agent-harness/cli_anything/mailchimp/utils/repl_skin.py b/mailchimp/agent-harness/cli_anything/mailchimp/utils/repl_skin.py new file mode 100644 index 000000000..bc1fb6d1d --- /dev/null +++ b/mailchimp/agent-harness/cli_anything/mailchimp/utils/repl_skin.py @@ -0,0 +1,567 @@ +"""cli-anything REPL Skin โ€” Unified terminal interface for all CLI harnesses. + +Copy this file into your CLI package at: + cli_anything//utils/repl_skin.py + +Usage: + from cli_anything..utils.repl_skin import ReplSkin + + skin = ReplSkin("shotcut", version="1.0.0") + skin.print_banner() # auto-detects repo-root or packaged SKILL.md + prompt_text = skin.prompt(project_name="my_video.mlt", modified=True) + skin.success("Project saved") + skin.error("File not found") + skin.warning("Unsaved changes") + skin.info("Processing 24 clips...") + skin.status("Track 1", "3 clips, 00:02:30") + skin.table(headers, rows) + skin.print_goodbye() +""" + +import os +import sys +from pathlib import Path + +# โ”€โ”€ ANSI color codes (no external deps for core styling) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +_RESET = "\033[0m" +_BOLD = "\033[1m" +_DIM = "\033[2m" +_ITALIC = "\033[3m" +_UNDERLINE = "\033[4m" + +# Brand colors +_CYAN = "\033[38;5;80m" # cli-anything brand cyan +_CYAN_BG = "\033[48;5;80m" +_WHITE = "\033[97m" +_GRAY = "\033[38;5;245m" +_DARK_GRAY = "\033[38;5;240m" +_LIGHT_GRAY = "\033[38;5;250m" + +# Software accent colors โ€” each software gets a unique accent +_ACCENT_COLORS = { + "gimp": "\033[38;5;214m", # warm orange + "blender": "\033[38;5;208m", # deep orange + "inkscape": "\033[38;5;39m", # bright blue + "audacity": "\033[38;5;33m", # navy blue + "libreoffice": "\033[38;5;40m", # green + "obs_studio": "\033[38;5;55m", # purple + "kdenlive": "\033[38;5;69m", # slate blue + "shotcut": "\033[38;5;35m", # teal green +} +_DEFAULT_ACCENT = "\033[38;5;75m" # default sky blue + +# Status colors +_GREEN = "\033[38;5;78m" +_YELLOW = "\033[38;5;220m" +_RED = "\033[38;5;196m" +_BLUE = "\033[38;5;75m" +_MAGENTA = "\033[38;5;176m" + +_SKILL_SOURCE_REPO = os.environ.get("CLI_ANYTHING_SKILL_REPO", "HKUDS/CLI-Anything") + +# โ”€โ”€ Brand icon โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +# The cli-anything icon: a small colored diamond/chevron mark +_ICON = f"{_CYAN}{_BOLD}โ—†{_RESET}" +_ICON_SMALL = f"{_CYAN}โ–ธ{_RESET}" + +# โ”€โ”€ Box drawing characters โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +_H_LINE = "โ”€" +_V_LINE = "โ”‚" +_TL = "โ•ญ" +_TR = "โ•ฎ" +_BL = "โ•ฐ" +_BR = "โ•ฏ" +_T_DOWN = "โ”ฌ" +_T_UP = "โ”ด" +_T_RIGHT = "โ”œ" +_T_LEFT = "โ”ค" +_CROSS = "โ”ผ" + + +def _strip_ansi(text: str) -> str: + """Remove ANSI escape codes for length calculation.""" + import re + return re.sub(r"\033\[[^m]*m", "", text) + + +def _visible_len(text: str) -> int: + """Get visible length of text (excluding ANSI codes).""" + return len(_strip_ansi(text)) + + +def _display_home_path(path: str) -> str: + """Display a path relative to the home directory when possible.""" + expanded = Path(path).expanduser().resolve() + home = Path.home().resolve() + try: + relative = expanded.relative_to(home) + return f"~/{relative.as_posix()}" + except ValueError: + return str(expanded) + + +class ReplSkin: + """Unified REPL skin for cli-anything CLIs. + + Provides consistent branding, prompts, and message formatting + across all CLI harnesses built with the cli-anything methodology. + """ + + def __init__(self, software: str, version: str = "1.0.0", + history_file: str | None = None, skill_path: str | None = None): + """Initialize the REPL skin. + + Args: + software: Software name (e.g., "gimp", "shotcut", "blender"). + version: CLI version string. + history_file: Path for persistent command history. + Defaults to ~/.cli-anything-/history + skill_path: Path to the SKILL.md file for agent discovery. + Auto-detected from the repo-root skills/ tree when present, + otherwise from the package's skills/ directory. + Displayed in banner for AI agents to know where to read skill info. + """ + self.software = software.lower().replace("-", "_") + self.display_name = software.replace("_", " ").title() + self.version = version + software_aliases = {"iterm2_ctl": "iterm2"} + self.skill_slug = software_aliases.get(self.software, self.software).replace("_", "-") + self.skill_id = f"cli-anything-{self.skill_slug}" + self.skill_install_cmd = ( + f"npx skills add {_SKILL_SOURCE_REPO} --skill {self.skill_id} -g -y" + ) + global_skill_root = Path( + os.environ.get("CLI_ANYTHING_GLOBAL_SKILLS_DIR", str(Path.home() / ".agents" / "skills")) + ).expanduser() + self.global_skill_path = str(global_skill_root / self.skill_id / "SKILL.md") + + # Prefer repo-root canonical skills//SKILL.md when running + # inside the CLI-Anything monorepo. Fall back to the packaged + # cli_anything//skills/SKILL.md for installed harnesses. + if skill_path is None: + package_skill = Path(__file__).resolve().parent.parent / "skills" / "SKILL.md" + repo_skill = None + for parent in Path(__file__).resolve().parents: + candidate = parent / "skills" / self.skill_id / "SKILL.md" + if candidate.is_file(): + repo_skill = candidate + break + if repo_skill and repo_skill.is_file(): + skill_path = str(repo_skill) + elif package_skill.is_file(): + skill_path = str(package_skill) + self.skill_path = skill_path + self.accent = _ACCENT_COLORS.get(self.software, _DEFAULT_ACCENT) + + # History file + if history_file is None: + hist_dir = Path.home() / f".cli-anything-{self.software}" + hist_dir.mkdir(parents=True, exist_ok=True) + self.history_file = str(hist_dir / "history") + else: + self.history_file = history_file + + # Detect terminal capabilities + self._color = self._detect_color_support() + + def _detect_color_support(self) -> bool: + """Check if terminal supports color.""" + if os.environ.get("NO_COLOR"): + return False + if os.environ.get("CLI_ANYTHING_NO_COLOR"): + return False + if not hasattr(sys.stdout, "isatty"): + return False + return sys.stdout.isatty() + + def _c(self, code: str, text: str) -> str: + """Apply color code if colors are supported.""" + if not self._color: + return text + return f"{code}{text}{_RESET}" + + # โ”€โ”€ Banner โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def print_banner(self): + """Print the startup banner with branding.""" + import textwrap + + inner = 72 + + def _box_line(content: str) -> str: + """Wrap content in box drawing, padding to inner width.""" + pad = inner - _visible_len(content) + vl = self._c(_DARK_GRAY, _V_LINE) + return f"{vl}{content}{' ' * max(0, pad)}{vl}" + + def _meta_lines(label: str, value: str) -> list[str]: + """Wrap a metadata line for the banner box.""" + icon = self._c(_MAGENTA, "โ—‡") + label_text = self._c(_DARK_GRAY, label) + prefix = f" {icon} {label_text} " + available = max(12, inner - _visible_len(prefix)) + wrapped = textwrap.wrap( + value, + width=available, + break_long_words=True, + break_on_hyphens=False, + ) or [""] + lines = [f"{prefix}{self._c(_LIGHT_GRAY, wrapped[0])}"] + continuation_prefix = " " * _visible_len(prefix) + for chunk in wrapped[1:]: + lines.append(f"{continuation_prefix}{self._c(_LIGHT_GRAY, chunk)}") + return lines + + top = self._c(_DARK_GRAY, f"{_TL}{_H_LINE * inner}{_TR}") + bot = self._c(_DARK_GRAY, f"{_BL}{_H_LINE * inner}{_BR}") + + # Title: โ—† cli-anything ยท Shotcut + icon = self._c(_CYAN + _BOLD, "โ—†") + brand = self._c(_CYAN + _BOLD, "cli-anything") + dot = self._c(_DARK_GRAY, "ยท") + name = self._c(self.accent + _BOLD, self.display_name) + title = f" {icon} {brand} {dot} {name}" + + ver = f" {self._c(_DARK_GRAY, f' v{self.version}')}" + tip = f" {self._c(_DARK_GRAY, ' Type help for commands, quit to exit')}" + empty = "" + + meta_lines: list[str] = [] + meta_lines.extend(_meta_lines("Install:", self.skill_install_cmd)) + meta_lines.extend(_meta_lines("Global skill:", _display_home_path(self.global_skill_path))) + print(top) + print(_box_line(title)) + print(_box_line(ver)) + for line in meta_lines: + print(_box_line(line)) + print(_box_line(empty)) + print(_box_line(tip)) + print(bot) + print() + + # โ”€โ”€ Prompt โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def prompt(self, project_name: str = "", modified: bool = False, + context: str = "") -> str: + """Build a styled prompt string for prompt_toolkit or input(). + + Args: + project_name: Current project name (empty if none open). + modified: Whether the project has unsaved changes. + context: Optional extra context to show in prompt. + + Returns: + Formatted prompt string. + """ + parts = [] + + # Icon + if self._color: + parts.append(f"{_CYAN}โ—†{_RESET} ") + else: + parts.append("> ") + + # Software name + parts.append(self._c(self.accent + _BOLD, self.software)) + + # Project context + if project_name or context: + ctx = context or project_name + mod = "*" if modified else "" + parts.append(f" {self._c(_DARK_GRAY, '[')}") + parts.append(self._c(_LIGHT_GRAY, f"{ctx}{mod}")) + parts.append(self._c(_DARK_GRAY, ']')) + + parts.append(self._c(_GRAY, " โฏ ")) + + return "".join(parts) + + def prompt_tokens(self, project_name: str = "", modified: bool = False, + context: str = ""): + """Build prompt_toolkit formatted text tokens for the prompt. + + Use with prompt_toolkit's FormattedText for proper ANSI handling. + + Returns: + list of (style, text) tuples for prompt_toolkit. + """ + accent_hex = _ANSI_256_TO_HEX.get(self.accent, "#5fafff") + tokens = [] + + tokens.append(("class:icon", "โ—† ")) + tokens.append(("class:software", self.software)) + + if project_name or context: + ctx = context or project_name + mod = "*" if modified else "" + tokens.append(("class:bracket", " [")) + tokens.append(("class:context", f"{ctx}{mod}")) + tokens.append(("class:bracket", "]")) + + tokens.append(("class:arrow", " โฏ ")) + + return tokens + + def get_prompt_style(self): + """Get a prompt_toolkit Style object matching the skin. + + Returns: + prompt_toolkit.styles.Style + """ + try: + from prompt_toolkit.styles import Style + except ImportError: + return None + + accent_hex = _ANSI_256_TO_HEX.get(self.accent, "#5fafff") + + return Style.from_dict({ + "icon": "#5fdfdf bold", # cyan brand color + "software": f"{accent_hex} bold", + "bracket": "#585858", + "context": "#bcbcbc", + "arrow": "#808080", + # Completion menu + "completion-menu.completion": "bg:#303030 #bcbcbc", + "completion-menu.completion.current": f"bg:{accent_hex} #000000", + "completion-menu.meta.completion": "bg:#303030 #808080", + "completion-menu.meta.completion.current": f"bg:{accent_hex} #000000", + # Auto-suggest + "auto-suggest": "#585858", + # Bottom toolbar + "bottom-toolbar": "bg:#1c1c1c #808080", + "bottom-toolbar.text": "#808080", + }) + + # โ”€โ”€ Messages โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def success(self, message: str): + """Print a success message with green checkmark.""" + icon = self._c(_GREEN + _BOLD, "โœ“") + print(f" {icon} {self._c(_GREEN, message)}") + + def error(self, message: str): + """Print an error message with red cross.""" + icon = self._c(_RED + _BOLD, "โœ—") + print(f" {icon} {self._c(_RED, message)}", file=sys.stderr) + + def warning(self, message: str): + """Print a warning message with yellow triangle.""" + icon = self._c(_YELLOW + _BOLD, "โš ") + print(f" {icon} {self._c(_YELLOW, message)}") + + def info(self, message: str): + """Print an info message with blue dot.""" + icon = self._c(_BLUE, "โ—") + print(f" {icon} {self._c(_LIGHT_GRAY, message)}") + + def hint(self, message: str): + """Print a subtle hint message.""" + print(f" {self._c(_DARK_GRAY, message)}") + + def section(self, title: str): + """Print a section header.""" + print() + print(f" {self._c(self.accent + _BOLD, title)}") + print(f" {self._c(_DARK_GRAY, _H_LINE * len(title))}") + + # โ”€โ”€ Status display โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def status(self, label: str, value: str): + """Print a key-value status line.""" + lbl = self._c(_GRAY, f" {label}:") + val = self._c(_WHITE, f" {value}") + print(f"{lbl}{val}") + + def status_block(self, items: dict[str, str], title: str = ""): + """Print a block of status key-value pairs. + + Args: + items: Dict of label -> value pairs. + title: Optional title for the block. + """ + if title: + self.section(title) + + max_key = max(len(k) for k in items) if items else 0 + for label, value in items.items(): + lbl = self._c(_GRAY, f" {label:<{max_key}}") + val = self._c(_WHITE, f" {value}") + print(f"{lbl}{val}") + + def progress(self, current: int, total: int, label: str = ""): + """Print a simple progress indicator. + + Args: + current: Current step number. + total: Total number of steps. + label: Optional label for the progress. + """ + pct = int(current / total * 100) if total > 0 else 0 + bar_width = 20 + filled = int(bar_width * current / total) if total > 0 else 0 + bar = "โ–ˆ" * filled + "โ–‘" * (bar_width - filled) + text = f" {self._c(_CYAN, bar)} {self._c(_GRAY, f'{pct:3d}%')}" + if label: + text += f" {self._c(_LIGHT_GRAY, label)}" + print(text) + + # โ”€โ”€ Table display โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def table(self, headers: list[str], rows: list[list[str]], + max_col_width: int = 40): + """Print a formatted table with box-drawing characters. + + Args: + headers: Column header strings. + rows: List of rows, each a list of cell strings. + max_col_width: Maximum column width before truncation. + """ + if not headers: + return + + # Calculate column widths + col_widths = [min(len(h), max_col_width) for h in headers] + for row in rows: + for i, cell in enumerate(row): + if i < len(col_widths): + col_widths[i] = min( + max(col_widths[i], len(str(cell))), max_col_width + ) + + def pad(text: str, width: int) -> str: + t = str(text)[:width] + return t + " " * (width - len(t)) + + # Header + header_cells = [ + self._c(_CYAN + _BOLD, pad(h, col_widths[i])) + for i, h in enumerate(headers) + ] + sep = self._c(_DARK_GRAY, f" {_V_LINE} ") + header_line = f" {sep.join(header_cells)}" + print(header_line) + + # Separator + sep_parts = [self._c(_DARK_GRAY, _H_LINE * w) for w in col_widths] + sep_line = self._c(_DARK_GRAY, f" {'โ”€โ”€โ”€'.join([_H_LINE * w for w in col_widths])}") + print(sep_line) + + # Rows + for row in rows: + cells = [] + for i, cell in enumerate(row): + if i < len(col_widths): + cells.append(self._c(_LIGHT_GRAY, pad(str(cell), col_widths[i]))) + row_sep = self._c(_DARK_GRAY, f" {_V_LINE} ") + print(f" {row_sep.join(cells)}") + + # โ”€โ”€ Help display โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def help(self, commands: dict[str, str]): + """Print a formatted help listing. + + Args: + commands: Dict of command -> description pairs. + """ + self.section("Commands") + max_cmd = max(len(c) for c in commands) if commands else 0 + for cmd, desc in commands.items(): + cmd_styled = self._c(self.accent, f" {cmd:<{max_cmd}}") + desc_styled = self._c(_GRAY, f" {desc}") + print(f"{cmd_styled}{desc_styled}") + print() + + # โ”€โ”€ Goodbye โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def print_goodbye(self): + """Print a styled goodbye message.""" + print(f"\n {_ICON_SMALL} {self._c(_GRAY, 'Goodbye!')}\n") + + # โ”€โ”€ Prompt toolkit session factory โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def create_prompt_session(self): + """Create a prompt_toolkit PromptSession with skin styling. + + Returns: + A configured PromptSession, or None if prompt_toolkit unavailable. + """ + try: + from prompt_toolkit import PromptSession + from prompt_toolkit.history import FileHistory + from prompt_toolkit.auto_suggest import AutoSuggestFromHistory + from prompt_toolkit.formatted_text import FormattedText + + style = self.get_prompt_style() + + session = PromptSession( + history=FileHistory(self.history_file), + auto_suggest=AutoSuggestFromHistory(), + style=style, + enable_history_search=True, + ) + return session + except ImportError: + return None + + def get_input(self, pt_session, project_name: str = "", + modified: bool = False, context: str = "") -> str: + """Get input from user using prompt_toolkit or fallback. + + Args: + pt_session: A prompt_toolkit PromptSession (or None). + project_name: Current project name. + modified: Whether project has unsaved changes. + context: Optional context string. + + Returns: + User input string (stripped). + """ + if pt_session is not None: + from prompt_toolkit.formatted_text import FormattedText + tokens = self.prompt_tokens(project_name, modified, context) + return pt_session.prompt(FormattedText(tokens)).strip() + else: + raw_prompt = self.prompt(project_name, modified, context) + return input(raw_prompt).strip() + + # โ”€โ”€ Toolbar builder โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + + def bottom_toolbar(self, items: dict[str, str]): + """Create a bottom toolbar callback for prompt_toolkit. + + Args: + items: Dict of label -> value pairs to show in toolbar. + + Returns: + A callable that returns FormattedText for the toolbar. + """ + def toolbar(): + from prompt_toolkit.formatted_text import FormattedText + parts = [] + for i, (k, v) in enumerate(items.items()): + if i > 0: + parts.append(("class:bottom-toolbar.text", " โ”‚ ")) + parts.append(("class:bottom-toolbar.text", f" {k}: ")) + parts.append(("class:bottom-toolbar", v)) + return FormattedText(parts) + return toolbar + + +# โ”€โ”€ ANSI 256-color to hex mapping (for prompt_toolkit styles) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +_ANSI_256_TO_HEX = { + "\033[38;5;33m": "#0087ff", # audacity navy blue + "\033[38;5;35m": "#00af5f", # shotcut teal + "\033[38;5;39m": "#00afff", # inkscape bright blue + "\033[38;5;40m": "#00d700", # libreoffice green + "\033[38;5;55m": "#5f00af", # obs purple + "\033[38;5;69m": "#5f87ff", # kdenlive slate blue + "\033[38;5;75m": "#5fafff", # default sky blue + "\033[38;5;80m": "#5fd7d7", # brand cyan + "\033[38;5;208m": "#ff8700", # blender deep orange + "\033[38;5;214m": "#ffaf00", # gimp warm orange +} diff --git a/mailchimp/agent-harness/setup.py b/mailchimp/agent-harness/setup.py new file mode 100644 index 000000000..b9e3c1d64 --- /dev/null +++ b/mailchimp/agent-harness/setup.py @@ -0,0 +1,38 @@ +import os +from setuptools import setup, find_namespace_packages + +_here = os.path.abspath(os.path.dirname(__file__)) + +with open(os.path.join(_here, "cli_anything/mailchimp/README.md"), encoding="utf-8") as fh: + long_description = fh.read() + +setup( + name="cli-anything-mailchimp", + version="0.1.0", + description="cli-anything harness for the Mailchimp Marketing API v3.0", + long_description=long_description, + long_description_content_type="text/markdown", + author="cli-anything contributors", + license="Apache-2.0", + python_requires=">=3.10", + packages=find_namespace_packages(include=["cli_anything.*"]), + package_data={"cli_anything.mailchimp": ["skills/SKILL.md", "README.md"]}, + install_requires=[ + "click>=8.0", + "requests>=2.28", + "prompt-toolkit>=3.0", + ], + extras_require={ + "dev": ["pytest>=7.0", "pytest-cov", "responses>=0.23"], + }, + entry_points={ + "console_scripts": [ + "cli-anything-mailchimp=cli_anything.mailchimp.mailchimp_cli:main", + ], + }, + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + ], +) diff --git a/registry.json b/registry.json index bc84bf449..9c9390b7b 100644 --- a/registry.json +++ b/registry.json @@ -1086,6 +1086,25 @@ "url": "https://github.com/collectivewinca" } ] + }, + { + "name": "mailchimp", + "display_name": "Mailchimp", + "version": "0.1.0", + "description": "Mailchimp Marketing API v3.0 โ€” manage audiences, campaigns, reports, automations, ecommerce, templates, and more from an agent-native CLI", + "requires": "MAILCHIMP_API_KEY", + "homepage": "https://mailchimp.com/developer/marketing/", + "source_url": null, + "install_cmd": "pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=mailchimp/agent-harness", + "entry_point": "cli-anything-mailchimp", + "skill_md": "skills/cli-anything-mailchimp/SKILL.md", + "category": "web", + "contributors": [ + { + "name": "iGodly", + "url": "https://github.com/iGodly" + } + ] } ] } diff --git a/skills/cli-anything-mailchimp/SKILL.md b/skills/cli-anything-mailchimp/SKILL.md new file mode 100644 index 000000000..c730e9f6c --- /dev/null +++ b/skills/cli-anything-mailchimp/SKILL.md @@ -0,0 +1,228 @@ +--- +name: cli-anything-mailchimp +description: CLI harness for the Mailchimp Marketing API v3.0 โ€” 303 commands across 30 resource groups (lists, campaigns, reports, automations, ecommerce, templates, and more). Supports JSON output and interactive REPL mode. +--- + +# cli-anything-mailchimp + +## Identity + +An agent-native CLI for the [Mailchimp Marketing API v3.0](https://mailchimp.com/developer/marketing/docs/fundamentals/), built on the [CLI-Anything](https://github.com/HKUDS/CLI-Anything) framework. + +## What This CLI Does + +- Manage **audiences (lists)** โ€” create, update, delete lists; add/update/archive members; manage merge fields, segments, tags, and webhooks. +- Run **campaigns** โ€” create, schedule, send, pause, replicate, and analyse email campaigns. +- Read **reports** โ€” open rates, click rates, bounce stats, unsubscribes, email activity, geographic data. +- Control **automations** โ€” create and manage automated email workflows. +- Manage **e-commerce** โ€” stores, orders, customers, products, carts, and promo codes. +- Use **templates, file manager, landing pages, SMS campaigns, surveys**, and all other Marketing API resources. + +## Prerequisites + +- Python 3.10+ +- `MAILCHIMP_API_KEY` environment variable set to your API key (including datacenter suffix, e.g. `abc123-us8`) + +## Installation + +```bash +# From the CLI-Anything repo (once merged): +pip install git+https://github.com/HKUDS/CLI-Anything.git#subdirectory=mailchimp/agent-harness + +# During development: +cd mailchimp/agent-harness && pip install -e . +``` + +## Command Reference + +### Root + +| Command | Description | +|---|---| +| `cli-anything-mailchimp ping` | Health check โ€” confirms API connectivity | +| `cli-anything-mailchimp root list` | Get account info | +| `cli-anything-mailchimp --json ` | Output any command as JSON | +| `cli-anything-mailchimp` | Launch interactive REPL | + +### Lists (Audiences) + +| Command | Description | +|---|---| +| `lists list` | List all audiences | +| `lists get ` | Get audience info | +| `lists create --data ''` | Create audience | +| `lists update --data ''` | Update audience | +| `lists delete ` | Delete audience | +| `lists list-lists-id-members ` | List members | +| `lists get-lists-id-members-id ` | Get member by MD5 hash | +| `lists create-lists-id-members --data ''` | Add member | +| `lists list-lists-id-merge-fields ` | List merge fields | +| `lists create-lists-id-merge-fields --data ''` | Add merge field | +| `lists list-lists-id-segments ` | List segments | +| `lists list-list-member-tags ` | List member tags | +| `lists create-list-member-tags --data ''` | Add/remove member tags | +| `lists list-lists-id-webhooks ` | List webhooks | +| `lists create-lists-id-webhooks --data ''` | Add webhook | + +### Campaigns + +| Command | Description | +|---|---| +| `campaigns list` | List campaigns | +| `campaigns get ` | Get campaign info | +| `campaigns create --data ''` | Create campaign | +| `campaigns update --data ''` | Update campaign settings | +| `campaigns delete ` | Delete campaign | +| `campaigns send ` | Send campaign immediately | +| `campaigns schedule --data ''` | Schedule campaign | +| `campaigns cancel-send ` | Cancel scheduled send | +| `campaigns pause ` | Pause RSS campaign | +| `campaigns resume ` | Resume RSS campaign | +| `campaigns replicate ` | Duplicate campaign | +| `campaigns list-content ` | Get campaign content | +| `campaigns list-send-checklist ` | Pre-send checklist | + +### Reports + +| Command | Description | +|---|---| +| `reports list` | List all campaign reports | +| `reports get ` | Get campaign summary report | +| `reports list-email-activity ` | Per-subscriber open/click activity | +| `reports list-click-details ` | Link click breakdown | +| `reports list-open-details ` | Per-subscriber opens | +| `reports list-unsubscribed ` | Unsubscribers | +| `reports list-locations ` | Geographic breakdown | +| `reports list-domain-performance ` | Per-domain stats | + +### Automations + +| Command | Description | +|---|---| +| `automations list` | List automations | +| `automations get ` | Get automation info | +| `automations create --data ''` | Create automation | +| `automations pause ` | Pause automation | +| `automations start ` | Start automation | +| `automations archive ` | Archive automation | +| `automations list-emails ` | List automation emails | + +### E-commerce + +| Command | Description | +|---|---| +| `ecommerce list-ecommerce-stores` | List stores | +| `ecommerce get ` | Get store info | +| `ecommerce create --data ''` | Add store | +| `ecommerce list-ecommerce-stores-id-orders ` | List orders | +| `ecommerce list-ecommerce-stores-id-products ` | List products | +| `ecommerce list-ecommerce-stores-id-customers ` | List customers | +| `ecommerce list-ecommerce-stores-id-carts ` | List carts | +| `ecommerce list-ecommerce-stores-id-promocodes ` | List promo codes | + +### Other Resources + +| Group | Description | +|---|---| +| `templates` | Email templates (list, get, create, update, delete) | +| `template-folders` | Template folders | +| `campaign-folders` | Campaign folders | +| `file-manager` | Files and folders in the file manager | +| `landing-pages` | Landing pages (list, create, publish, unpublish) | +| `sms-campaigns` | SMS campaigns (10 operations) | +| `surveys` | Surveys (list, get, publish) | +| `reporting` | Facebook ad and landing page reporting | +| `search-campaigns` | Search campaigns by query | +| `search-members` | Search members across all audiences | +| `batches` | Batch API operations | +| `batch-webhooks` | Batch operation webhooks | +| `verified-domains` | Email domain verification | +| `authorized-apps` | OAuth connected apps | +| `connected-sites` | Connected site integrations | +| `conversations` | Inbox conversations | +| `activity-feed` | Account activity feed | +| `account-exports` | Account data exports | + +## JSON Output + +All commands support `--json` at the root level: + +```bash +# List all audiences as JSON +cli-anything-mailchimp --json lists list + +# Get a campaign report as JSON +cli-anything-mailchimp --json reports get abc123def + +# Pipe to jq โ€” use the native Mailchimp field name for the resource +cli-anything-mailchimp --json lists list | jq '.lists[].name' +cli-anything-mailchimp --json campaigns list | jq '.campaigns[].id' +``` + +**Envelope shapes** (native Mailchimp API response โ€” use the resource-specific key): + +```json +// List endpoints โ€” key matches the resource name (lists, campaigns, members, etc.) +{"lists": [...], "total_items": 42, "_links": [...]} +{"campaigns": [...], "total_items": 10, "_links": [...]} + +// Single resource GET / POST / PATCH +{"id": "abc123", "name": "My List", ...} + +// DELETE +{"ok": true, "message": "Deleted."} + +// Error +{"ok": false, "message": "Resource Not Found: ...", "data": {...}} +``` + +## Common Agent Patterns + +```bash +# Get account health +cli-anything-mailchimp --json ping | jq '.health_status' + +# List all audience IDs and names +cli-anything-mailchimp --json lists list | jq '.lists[] | {id, name}' + +# Find all subscribed members in an audience +cli-anything-mailchimp --json lists list-lists-id-members --status subscribed | jq '.members[].email_address' + +# Create a campaign and get its send checklist +cli-anything-mailchimp --json campaigns create --data '{"type":"regular","settings":{"subject_line":"Hello","from_name":"Me","reply_to":"me@example.com"}}' | jq '.id' +cli-anything-mailchimp --json campaigns list-send-checklist | jq '.items[] | select(.result == false)' + +# Get unsubscribes for a sent campaign +cli-anything-mailchimp --json reports list-unsubscribed | jq '.unsubscribes[].email_address' + +# Add a member to an audience (subscriber hash = MD5 of lowercased email) +cli-anything-mailchimp --json lists create-members --data '{"email_address":"user@example.com","status":"subscribed"}' + +# Search for a member across all audiences +cli-anything-mailchimp --json search-members list --query "user@example.com" | jq '.exact_matches.members[]' +``` + +## Interactive REPL + +Run `cli-anything-mailchimp` with no arguments to enter the REPL: + +``` +โ—† cli-anything ยท Mailchimp + v0.1.0 + Type help for commands, quit to exit + +โ—† mailchimp โฏ ping + โœ“ {"health_status": "Everything's Chimpy!"} + +โ—† mailchimp โฏ --json lists list +{"lists": [...], "total_items": 3, "_links": [...]} + +โ—† mailchimp โฏ quit +``` + +## Notes + +- **Subscriber hash**: Mailchimp identifies members by the MD5 hash of their lowercased email. Compute with `python -c "import hashlib; email='email@example.com'; print(hashlib.md5(email.strip().lower().encode()).hexdigest())"`. +- **Body payloads**: All POST/PATCH/PUT commands accept `--data ''`. See [Mailchimp API docs](https://mailchimp.com/developer/marketing/api/) for the schema of each endpoint. +- **Datacenter**: Your API key ends in `-us8`, `-eu2`, etc. The CLI extracts this automatically โ€” include it in `MAILCHIMP_API_KEY`. +- **Rate limits**: The Marketing API rate-limits at 10 concurrent connections and a rolling per-account limit. For bulk operations, use the `batches` group.