onboard-domain runs POST /domains -> addresses/validate (gen E911 pidflo) -> addresses/create from one JSON body (domain fields + optional `emergency` block), gated --confirm. Reverse- engineered from the OITVOIP wizard screenshots; live-created the real client domain vwp.91912.service (Valley Wide Plastering) + E911 address, and proved the wrapper with a throwaway create->delete (no leftovers, vwp intact). Documented GUI->API mapping + the two manual gaps (voicemail user-defaults, email-send-from-address pending the packetdial.com mailbox) + the domain-type "no"-on-create quirk. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
417 lines
25 KiB
Python
417 lines
25 KiB
Python
#!/usr/bin/env python3
|
|
"""CLI for the packetdial skill — NetSapiens SNAPsolution API v2.
|
|
|
|
Read subcommands run freely. Write subcommands (create-*, update-*, delete-*,
|
|
raw with a non-GET method) refuse to run unless --confirm is passed; without it
|
|
they print what they WOULD do and exit non-zero.
|
|
|
|
Output: --json emits raw JSON (default for most commands); a few commands render
|
|
a readable table when --json is omitted.
|
|
|
|
Read examples:
|
|
python ns.py status
|
|
python ns.py whoami
|
|
python ns.py domains
|
|
python ns.py domain <domain>
|
|
python ns.py users <domain>
|
|
python ns.py user <domain> <user>
|
|
python ns.py phones <domain>
|
|
python ns.py dids <domain>
|
|
python ns.py devices <domain> <user>
|
|
python ns.py cdrs --domain <domain> --start 2026-06-01 --end 2026-06-02
|
|
python ns.py resellers
|
|
|
|
Write examples (all require --confirm):
|
|
python ns.py create-domain --body '{"domain":"acme","description":"Acme Inc"}' --confirm
|
|
python ns.py create-user <domain> --body '{"user":"101","name-first-name":"Jane"}' --confirm
|
|
python ns.py delete-user <domain> <user> --confirm
|
|
|
|
Escape hatch (raw request against any of the 239 v2 paths):
|
|
python ns.py raw GET domains/acme/users
|
|
python ns.py raw POST domains/acme/users --body '{...}' --confirm
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
from ns_client import NetSapiensClient, PacketDialError
|
|
|
|
|
|
def _log_skill_error(skill, msg, context=""):
|
|
"""Soft-fail: append a functional-error entry to errorlog.md (never throws)."""
|
|
try:
|
|
root = os.environ.get("CLAUDETOOLS_ROOT") or os.path.abspath(
|
|
os.path.join(os.path.dirname(__file__), "..", "..", "..", "..")
|
|
)
|
|
h = os.path.join(root, ".claude", "scripts", "log-skill-error.sh")
|
|
if not os.path.exists(h):
|
|
return
|
|
a = ["bash", h, skill, msg]
|
|
if context:
|
|
a += ["--context", context]
|
|
subprocess.run(a, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
timeout=10)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def _emit(obj) -> None:
|
|
print(json.dumps(obj, indent=2, ensure_ascii=False, default=str))
|
|
|
|
|
|
def _parse_body(raw: str | None) -> dict | None:
|
|
if raw is None:
|
|
return None
|
|
try:
|
|
parsed = json.loads(raw)
|
|
except json.JSONDecodeError as exc:
|
|
raise SystemExit(f"--body is not valid JSON: {exc}")
|
|
if not isinstance(parsed, dict):
|
|
raise SystemExit("--body must be a JSON object")
|
|
return parsed
|
|
|
|
|
|
def _require_confirm(args, action: str, detail: str) -> None:
|
|
if not getattr(args, "confirm", False):
|
|
print(f"[DRY RUN] Would {action}: {detail}")
|
|
print("Refusing to perform a write without --confirm. Re-run with --confirm.")
|
|
raise SystemExit(2)
|
|
|
|
|
|
def main(argv=None) -> int:
|
|
p = argparse.ArgumentParser(prog="ns.py", description="PacketDial / NetSapiens v2 CLI")
|
|
p.add_argument("--json", action="store_true", help="emit raw JSON (default for most)")
|
|
sub = p.add_subparsers(dest="cmd", required=True)
|
|
|
|
# --- read ---
|
|
sub.add_parser("status", help="API version + authenticated key identity")
|
|
sub.add_parser("whoami", help="details of the authenticated API key")
|
|
sub.add_parser("domains", help="list all domains")
|
|
sp = sub.add_parser("domain", help="one domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("users", help="users in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("user", help="one user"); sp.add_argument("domain"); sp.add_argument("user")
|
|
sp = sub.add_parser("phones", help="phones (devices) in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("dids", help="phone numbers in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("devices", help="devices for a user"); sp.add_argument("domain"); sp.add_argument("user")
|
|
sp = sub.add_parser("callqueues", help="ACD call queues in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("timeframes", help="time-based routing schedules in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("sites", help="multi-site definitions in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("contacts", help="shared/domain contacts"); sp.add_argument("domain")
|
|
sp = sub.add_parser("autoattendants", help="auto-attendants (IVR) in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("billing", help="domain limits + current usage counts"); sp.add_argument("domain")
|
|
sub.add_parser("resellers", help="list resellers")
|
|
sp = sub.add_parser("cdrs", help="call detail records")
|
|
sp.add_argument("--domain"); sp.add_argument("--start"); sp.add_argument("--end")
|
|
sp.add_argument("--limit", type=int, default=100)
|
|
|
|
# --- write (gated) ---
|
|
sp = sub.add_parser("create-domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-user"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-user"); sp.add_argument("domain"); sp.add_argument("user"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-user"); sp.add_argument("domain"); sp.add_argument("user"); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-phone"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-did"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# call queue edits (gated)
|
|
sp = sub.add_parser("create-callqueue"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-callqueue"); sp.add_argument("domain"); sp.add_argument("callqueue"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-callqueue"); sp.add_argument("domain"); sp.add_argument("callqueue"); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("add-agent"); sp.add_argument("domain"); sp.add_argument("callqueue"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-agent"); sp.add_argument("domain"); sp.add_argument("callqueue"); sp.add_argument("agent_id"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("remove-agent"); sp.add_argument("domain"); sp.add_argument("callqueue"); sp.add_argument("agent_id"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# timeframe edits (gated) — body-discriminated variants, pass --body verbatim
|
|
sp = sub.add_parser("create-timeframe"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-timeframe"); sp.add_argument("domain"); sp.add_argument("tf_id"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-timeframe"); sp.add_argument("domain"); sp.add_argument("tf_id"); sp.add_argument("--body"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# more read wrappers
|
|
sp = sub.add_parser("addresses", help="E911 addresses in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("smsnumbers", help="SMS numbers in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("blocked-numbers", help="blocked-number filters in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("moh", help="music-on-hold entries in a domain"); sp.add_argument("domain")
|
|
sp = sub.add_parser("dialrules", help="dial rules in a dial plan"); sp.add_argument("domain"); sp.add_argument("dialplan")
|
|
sp = sub.add_parser("recording", help="get a recording by call id"); sp.add_argument("domain"); sp.add_argument("callid")
|
|
sp = sub.add_parser("transcriptions", help="call transcriptions in a domain"); sp.add_argument("domain")
|
|
|
|
# DID complete + device CRUD
|
|
sp = sub.add_parser("update-did"); sp.add_argument("domain"); sp.add_argument("phonenumber"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-did"); sp.add_argument("domain"); sp.add_argument("phonenumber"); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-device"); sp.add_argument("domain"); sp.add_argument("user"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-device"); sp.add_argument("domain"); sp.add_argument("user"); sp.add_argument("device"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-device"); sp.add_argument("domain"); sp.add_argument("user"); sp.add_argument("device"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# E911 address CRUD
|
|
sp = sub.add_parser("create-address"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-address"); sp.add_argument("domain"); sp.add_argument("address_id"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-address"); sp.add_argument("domain"); sp.add_argument("address_id"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# contact CRUD
|
|
sp = sub.add_parser("create-contact"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-contact"); sp.add_argument("domain"); sp.add_argument("contact_id"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-contact"); sp.add_argument("domain"); sp.add_argument("contact_id"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# sites + auto-attendants + sms + blocked numbers + moh (writes)
|
|
sp = sub.add_parser("create-site"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-site"); sp.add_argument("domain"); sp.add_argument("site"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-autoattendant"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-smsnumber"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("update-smsnumber"); sp.add_argument("domain"); sp.add_argument("smsnumber"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-smsnumber"); sp.add_argument("domain"); sp.add_argument("smsnumber"); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("block-numbers"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("unblock-numbers"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("create-moh"); sp.add_argument("domain"); sp.add_argument("--body", required=True); sp.add_argument("--confirm", action="store_true")
|
|
sp = sub.add_parser("delete-moh"); sp.add_argument("domain"); sp.add_argument("index"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# onboard a new client domain (wizard -> 3-call flow): domain + optional E911 address
|
|
sp = sub.add_parser("onboard-domain", help="create a domain (+ optional E911 address) from one JSON body")
|
|
sp.add_argument("--body"); sp.add_argument("--body-file"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
# --- raw escape hatch ---
|
|
sp = sub.add_parser("raw", help="raw request against any v2 path")
|
|
sp.add_argument("method", choices=["GET", "POST", "PUT", "PATCH", "DELETE"])
|
|
sp.add_argument("path", help="relative path, e.g. domains/acme/users")
|
|
sp.add_argument("--body"); sp.add_argument("--confirm", action="store_true")
|
|
|
|
args = p.parse_args(argv)
|
|
client = NetSapiensClient()
|
|
|
|
try:
|
|
if args.cmd == "status":
|
|
_emit({"version": client.version(), "apiKey": client.whoami()})
|
|
elif args.cmd == "whoami":
|
|
_emit(client.whoami())
|
|
elif args.cmd == "domains":
|
|
_emit(client.domains())
|
|
elif args.cmd == "domain":
|
|
_emit(client.domain(args.domain))
|
|
elif args.cmd == "users":
|
|
_emit(client.users(args.domain))
|
|
elif args.cmd == "user":
|
|
_emit(client.user(args.domain, args.user))
|
|
elif args.cmd == "phones":
|
|
_emit(client.phones(args.domain))
|
|
elif args.cmd == "dids":
|
|
_emit(client.phonenumbers(args.domain))
|
|
elif args.cmd == "devices":
|
|
_emit(client.devices(args.domain, args.user))
|
|
elif args.cmd == "callqueues":
|
|
_emit(client.callqueues(args.domain))
|
|
elif args.cmd == "timeframes":
|
|
_emit(client.timeframes(args.domain))
|
|
elif args.cmd == "sites":
|
|
_emit(client.sites(args.domain))
|
|
elif args.cmd == "contacts":
|
|
_emit(client.contacts(args.domain))
|
|
elif args.cmd == "autoattendants":
|
|
_emit(client.autoattendants(args.domain))
|
|
elif args.cmd == "billing":
|
|
_emit(client.billing(args.domain))
|
|
elif args.cmd == "resellers":
|
|
_emit(client.resellers())
|
|
elif args.cmd == "cdrs":
|
|
filters = {"limit": args.limit}
|
|
if args.start:
|
|
filters["start-date"] = args.start
|
|
if args.end:
|
|
filters["end-date"] = args.end
|
|
_emit(client.cdrs(domain=args.domain, **filters))
|
|
|
|
elif args.cmd == "create-domain":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create domain", json.dumps(body))
|
|
_emit(client.create_domain(body))
|
|
elif args.cmd == "create-user":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create user", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_user(args.domain, body))
|
|
elif args.cmd == "update-user":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update user", f"{args.domain}/{args.user}: {json.dumps(body)}")
|
|
_emit(client.update_user(args.domain, args.user, body))
|
|
elif args.cmd == "delete-user":
|
|
_require_confirm(args, "DELETE user", f"{args.domain}/{args.user}")
|
|
_emit(client.delete_user(args.domain, args.user))
|
|
elif args.cmd == "create-phone":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create phone", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_phone(args.domain, body))
|
|
elif args.cmd == "create-did":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create phone number", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_phonenumber(args.domain, body))
|
|
|
|
elif args.cmd == "create-callqueue":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create call queue", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_callqueue(args.domain, body))
|
|
elif args.cmd == "update-callqueue":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update call queue", f"{args.domain}/{args.callqueue}: {json.dumps(body)}")
|
|
_emit(client.update_callqueue(args.domain, args.callqueue, body))
|
|
elif args.cmd == "delete-callqueue":
|
|
_require_confirm(args, "DELETE call queue", f"{args.domain}/{args.callqueue}")
|
|
_emit(client.delete_callqueue(args.domain, args.callqueue))
|
|
elif args.cmd == "add-agent":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "add queue agent", f"{args.domain}/{args.callqueue}: {json.dumps(body)}")
|
|
_emit(client.add_callqueue_agent(args.domain, args.callqueue, body))
|
|
elif args.cmd == "update-agent":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update queue agent", f"{args.domain}/{args.callqueue}/{args.agent_id}: {json.dumps(body)}")
|
|
_emit(client.update_callqueue_agent(args.domain, args.callqueue, args.agent_id, body))
|
|
elif args.cmd == "remove-agent":
|
|
_require_confirm(args, "remove queue agent", f"{args.domain}/{args.callqueue}/{args.agent_id}")
|
|
_emit(client.remove_callqueue_agent(args.domain, args.callqueue, args.agent_id))
|
|
|
|
elif args.cmd == "create-timeframe":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create timeframe", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_timeframe(args.domain, body))
|
|
elif args.cmd == "update-timeframe":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update timeframe", f"{args.domain}/{args.tf_id}: {json.dumps(body)}")
|
|
_emit(client.update_timeframe(args.domain, args.tf_id, body))
|
|
elif args.cmd == "delete-timeframe":
|
|
body = _parse_body(args.body) if args.body else None
|
|
_require_confirm(args, "DELETE timeframe", f"{args.domain}/{args.tf_id}" + (f" {json.dumps(body)}" if body else ""))
|
|
_emit(client.delete_timeframe(args.domain, args.tf_id, body))
|
|
|
|
# --- additional reads ---
|
|
elif args.cmd == "addresses":
|
|
_emit(client.addresses(args.domain))
|
|
elif args.cmd == "smsnumbers":
|
|
_emit(client.smsnumbers(args.domain))
|
|
elif args.cmd == "blocked-numbers":
|
|
_emit(client.blocked_numbers(args.domain))
|
|
elif args.cmd == "moh":
|
|
_emit(client.moh(args.domain))
|
|
elif args.cmd == "dialrules":
|
|
_emit(client.dialrules(args.domain, args.dialplan))
|
|
elif args.cmd == "recording":
|
|
_emit(client.recording(args.domain, args.callid))
|
|
elif args.cmd == "transcriptions":
|
|
_emit(client.transcriptions(args.domain))
|
|
|
|
# --- DID complete + device CRUD ---
|
|
elif args.cmd == "update-did":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update DID", f"{args.domain}/{args.phonenumber}: {json.dumps(body)}")
|
|
_emit(client.update_phonenumber(args.domain, args.phonenumber, body))
|
|
elif args.cmd == "delete-did":
|
|
_require_confirm(args, "DELETE DID", f"{args.domain}/{args.phonenumber}")
|
|
_emit(client.delete_phonenumber(args.domain, args.phonenumber))
|
|
elif args.cmd == "create-device":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create device", f"{args.domain}/{args.user}: {json.dumps(body)}")
|
|
_emit(client.create_device(args.domain, args.user, body))
|
|
elif args.cmd == "update-device":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update device", f"{args.domain}/{args.user}/{args.device}: {json.dumps(body)}")
|
|
_emit(client.update_device(args.domain, args.user, args.device, body))
|
|
elif args.cmd == "delete-device":
|
|
_require_confirm(args, "DELETE device", f"{args.domain}/{args.user}/{args.device}")
|
|
_emit(client.delete_device(args.domain, args.user, args.device))
|
|
|
|
# --- E911 address CRUD ---
|
|
elif args.cmd == "create-address":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create E911 address", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_address(args.domain, body))
|
|
elif args.cmd == "update-address":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update E911 address", f"{args.domain}/{args.address_id}: {json.dumps(body)}")
|
|
_emit(client.update_address(args.domain, args.address_id, body))
|
|
elif args.cmd == "delete-address":
|
|
_require_confirm(args, "DELETE E911 address", f"{args.domain}/{args.address_id}")
|
|
_emit(client.delete_address(args.domain, args.address_id))
|
|
|
|
# --- contact CRUD ---
|
|
elif args.cmd == "create-contact":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create contact", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_contact(args.domain, body))
|
|
elif args.cmd == "update-contact":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update contact", f"{args.domain}/{args.contact_id}: {json.dumps(body)}")
|
|
_emit(client.update_contact(args.domain, args.contact_id, body))
|
|
elif args.cmd == "delete-contact":
|
|
_require_confirm(args, "DELETE contact", f"{args.domain}/{args.contact_id}")
|
|
_emit(client.delete_contact(args.domain, args.contact_id))
|
|
|
|
# --- sites / auto-attendants / sms / blocked numbers / moh ---
|
|
elif args.cmd == "create-site":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create site", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_site(args.domain, body))
|
|
elif args.cmd == "update-site":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update site", f"{args.domain}/{args.site}: {json.dumps(body)}")
|
|
_emit(client.update_site(args.domain, args.site, body))
|
|
elif args.cmd == "create-autoattendant":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create auto-attendant", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_autoattendant(args.domain, body))
|
|
elif args.cmd == "create-smsnumber":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create SMS number", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_smsnumber(args.domain, body))
|
|
elif args.cmd == "update-smsnumber":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "update SMS number", f"{args.domain}/{args.smsnumber}: {json.dumps(body)}")
|
|
_emit(client.update_smsnumber(args.domain, args.smsnumber, body))
|
|
elif args.cmd == "delete-smsnumber":
|
|
_require_confirm(args, "DELETE SMS number", f"{args.domain}/{args.smsnumber}")
|
|
_emit(client.delete_smsnumber(args.domain, args.smsnumber))
|
|
elif args.cmd == "block-numbers":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "block numbers", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.block_numbers(args.domain, body))
|
|
elif args.cmd == "unblock-numbers":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "unblock numbers", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.unblock_numbers(args.domain, body))
|
|
elif args.cmd == "create-moh":
|
|
body = _parse_body(args.body)
|
|
_require_confirm(args, "create MOH (TTS)", f"{args.domain}: {json.dumps(body)}")
|
|
_emit(client.create_moh(args.domain, body))
|
|
elif args.cmd == "delete-moh":
|
|
_require_confirm(args, "DELETE MOH", f"{args.domain}/{args.index}")
|
|
_emit(client.delete_moh(args.domain, args.index))
|
|
|
|
elif args.cmd == "onboard-domain":
|
|
if args.body_file:
|
|
with open(args.body_file, encoding="utf-8") as fh:
|
|
body = json.load(fh)
|
|
else:
|
|
body = _parse_body(args.body)
|
|
if not isinstance(body, dict) or not body.get("domain"):
|
|
print("[ERROR] onboard-domain needs a JSON body with 'domain'", file=sys.stderr); sys.exit(2)
|
|
has_em = "emergency" in body
|
|
_require_confirm(args, "ONBOARD domain",
|
|
f"{body['domain']} (reseller {body.get('reseller','?')})"
|
|
+ (" + E911 address" if has_em else " (no E911 block)"))
|
|
_emit(client.onboard_domain(body))
|
|
|
|
elif args.cmd == "raw":
|
|
body = _parse_body(args.body)
|
|
if args.method != "GET":
|
|
_require_confirm(args, f"{args.method} {args.path}", json.dumps(body))
|
|
_emit(client.request(args.method, args.path, json_body=body))
|
|
else:
|
|
p.error(f"unknown command {args.cmd}")
|
|
except PacketDialError as exc:
|
|
print(f"[ERROR] {exc}", file=sys.stderr)
|
|
_log_skill_error("packetdial", f"{exc}",
|
|
context=f"cmd={getattr(args, 'cmd', '?')}")
|
|
return 1
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|