wxcli 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. wxcli/__init__.py +4 -0
  2. wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
  3. wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
  4. wxcli/_playbook/.claude/rules/cleanup.md +29 -0
  5. wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
  6. wxcli/_playbook/.claude/rules/org-health.md +14 -0
  7. wxcli/_playbook/.claude/settings.json +8 -0
  8. wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
  9. wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
  10. wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
  11. wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
  12. wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
  13. wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
  14. wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
  15. wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
  16. wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
  17. wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
  18. wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
  19. wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
  20. wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
  21. wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
  22. wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
  23. wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
  24. wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
  25. wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
  26. wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
  27. wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
  28. wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
  29. wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
  30. wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
  31. wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
  32. wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
  33. wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
  34. wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
  35. wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
  36. wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
  37. wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
  38. wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
  39. wxcli/_playbook/CLAUDE.md +373 -0
  40. wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
  41. wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
  42. wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
  43. wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
  44. wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
  45. wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
  46. wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
  47. wxcli/_playbook/docs/reference/admin-partner.md +357 -0
  48. wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
  49. wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
  50. wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
  51. wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
  52. wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
  53. wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
  54. wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
  55. wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
  56. wxcli/_playbook/docs/reference/authentication.md +965 -0
  57. wxcli/_playbook/docs/reference/call-control.md +1205 -0
  58. wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
  59. wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
  60. wxcli/_playbook/docs/reference/call-routing.md +2304 -0
  61. wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
  62. wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
  63. wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
  64. wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
  65. wxcli/_playbook/docs/reference/devices-core.md +1869 -0
  66. wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
  67. wxcli/_playbook/docs/reference/devices-platform.md +467 -0
  68. wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
  69. wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
  70. wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
  71. wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
  72. wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
  73. wxcli/_playbook/docs/reference/meetings-content.md +473 -0
  74. wxcli/_playbook/docs/reference/meetings-core.md +903 -0
  75. wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
  76. wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
  77. wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
  78. wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
  79. wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
  80. wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
  81. wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
  82. wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
  83. wxcli/_playbook/docs/reference/provisioning.md +1366 -0
  84. wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
  85. wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
  86. wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
  87. wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
  88. wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
  89. wxcli/_version.py +24 -0
  90. wxcli/auth.py +137 -0
  91. wxcli/commands/__init__.py +0 -0
  92. wxcli/commands/_registry.py +181 -0
  93. wxcli/commands/activation_email.py +103 -0
  94. wxcli/commands/admin_recordings.py +585 -0
  95. wxcli/commands/analytics.py +105 -0
  96. wxcli/commands/announcement_playlists.py +219 -0
  97. wxcli/commands/announcements.py +519 -0
  98. wxcli/commands/archive_users.py +36 -0
  99. wxcli/commands/attachment_actions.py +60 -0
  100. wxcli/commands/audit_events.py +83 -0
  101. wxcli/commands/authorizations.py +113 -0
  102. wxcli/commands/auto_attendant.py +642 -0
  103. wxcli/commands/broadworks_billing_reports.py +126 -0
  104. wxcli/commands/broadworks_enterprises.py +160 -0
  105. wxcli/commands/broadworks_subscribers.py +319 -0
  106. wxcli/commands/broadworks_workspaces.py +108 -0
  107. wxcli/commands/call_controls.py +1304 -0
  108. wxcli/commands/call_park.py +494 -0
  109. wxcli/commands/call_pickup.py +229 -0
  110. wxcli/commands/call_queue.py +1878 -0
  111. wxcli/commands/call_recording.py +707 -0
  112. wxcli/commands/call_routing.py +1610 -0
  113. wxcli/commands/call_settings_for_me_phase_5.py +212 -0
  114. wxcli/commands/caller_reputation.py +169 -0
  115. wxcli/commands/calling_service.py +305 -0
  116. wxcli/commands/cc_address_book.py +770 -0
  117. wxcli/commands/cc_agent_greetings.py +242 -0
  118. wxcli/commands/cc_agent_summaries.py +39 -0
  119. wxcli/commands/cc_agent_wellbeing.py +216 -0
  120. wxcli/commands/cc_agents.py +425 -0
  121. wxcli/commands/cc_ai_assistant.py +55 -0
  122. wxcli/commands/cc_ai_feature.py +294 -0
  123. wxcli/commands/cc_audio_files.py +149 -0
  124. wxcli/commands/cc_auto_csat.py +311 -0
  125. wxcli/commands/cc_aux_code.py +458 -0
  126. wxcli/commands/cc_business_hour.py +353 -0
  127. wxcli/commands/cc_call_monitoring.py +228 -0
  128. wxcli/commands/cc_callbacks.py +194 -0
  129. wxcli/commands/cc_campaign.py +212 -0
  130. wxcli/commands/cc_captures.py +39 -0
  131. wxcli/commands/cc_contact_list.py +169 -0
  132. wxcli/commands/cc_contact_number.py +295 -0
  133. wxcli/commands/cc_data_sources.py +235 -0
  134. wxcli/commands/cc_desktop_layout.py +380 -0
  135. wxcli/commands/cc_desktop_profile.py +322 -0
  136. wxcli/commands/cc_dial_number.py +511 -0
  137. wxcli/commands/cc_dial_plan.py +347 -0
  138. wxcli/commands/cc_dnc.py +101 -0
  139. wxcli/commands/cc_entry_point.py +545 -0
  140. wxcli/commands/cc_ewt.py +51 -0
  141. wxcli/commands/cc_flow.py +477 -0
  142. wxcli/commands/cc_global_vars.py +430 -0
  143. wxcli/commands/cc_holiday_list.py +335 -0
  144. wxcli/commands/cc_journey.py +1261 -0
  145. wxcli/commands/cc_legacy_flows.py +49 -0
  146. wxcli/commands/cc_multimedia_profile.py +436 -0
  147. wxcli/commands/cc_notification.py +51 -0
  148. wxcli/commands/cc_outdial_ani.py +604 -0
  149. wxcli/commands/cc_overrides.py +341 -0
  150. wxcli/commands/cc_queue.py +1083 -0
  151. wxcli/commands/cc_queue_stats.py +55 -0
  152. wxcli/commands/cc_realtime.py +51 -0
  153. wxcli/commands/cc_resource_collection.py +312 -0
  154. wxcli/commands/cc_search.py +46 -0
  155. wxcli/commands/cc_site.py +400 -0
  156. wxcli/commands/cc_skill.py +350 -0
  157. wxcli/commands/cc_skill_profile.py +289 -0
  158. wxcli/commands/cc_subscriptions.py +426 -0
  159. wxcli/commands/cc_summaries.py +130 -0
  160. wxcli/commands/cc_tasks.py +844 -0
  161. wxcli/commands/cc_team.py +325 -0
  162. wxcli/commands/cc_user_profiles.py +349 -0
  163. wxcli/commands/cc_users.py +701 -0
  164. wxcli/commands/cc_work_types.py +363 -0
  165. wxcli/commands/cdr.py +89 -0
  166. wxcli/commands/classifications.py +38 -0
  167. wxcli/commands/cleanup.py +1427 -0
  168. wxcli/commands/client_settings.py +72 -0
  169. wxcli/commands/conference.py +328 -0
  170. wxcli/commands/configure.py +72 -0
  171. wxcli/commands/converged_recordings.py +347 -0
  172. wxcli/commands/converged_recordings_export.py +310 -0
  173. wxcli/commands/cq_playlists.py +42 -0
  174. wxcli/commands/cucm.py +2794 -0
  175. wxcli/commands/cucm_config.py +129 -0
  176. wxcli/commands/customer_assist.py +373 -0
  177. wxcli/commands/data_sources.py +227 -0
  178. wxcli/commands/dect_devices.py +787 -0
  179. wxcli/commands/device_configurations.py +77 -0
  180. wxcli/commands/device_dynamic_settings.py +320 -0
  181. wxcli/commands/device_settings.py +1489 -0
  182. wxcli/commands/devices.py +280 -0
  183. wxcli/commands/domains.py +142 -0
  184. wxcli/commands/ecm.py +178 -0
  185. wxcli/commands/emergency_services.py +827 -0
  186. wxcli/commands/events.py +83 -0
  187. wxcli/commands/external_voicemail.py +52 -0
  188. wxcli/commands/groups.py +206 -0
  189. wxcli/commands/guest_management.py +76 -0
  190. wxcli/commands/hds.py +340 -0
  191. wxcli/commands/hot_desk.py +67 -0
  192. wxcli/commands/hot_desking_members.py +118 -0
  193. wxcli/commands/hot_desking_portal.py +124 -0
  194. wxcli/commands/hunt_group.py +577 -0
  195. wxcli/commands/hybrid_clusters.py +71 -0
  196. wxcli/commands/hybrid_connectors.py +67 -0
  197. wxcli/commands/identity_org.py +159 -0
  198. wxcli/commands/init_playbook.py +155 -0
  199. wxcli/commands/licenses.py +106 -0
  200. wxcli/commands/live_monitoring.py +40 -0
  201. wxcli/commands/location_call_handling.py +577 -0
  202. wxcli/commands/location_schedules.py +341 -0
  203. wxcli/commands/location_settings.py +1297 -0
  204. wxcli/commands/location_voicemail.py +494 -0
  205. wxcli/commands/locations.py +336 -0
  206. wxcli/commands/meeting_captions.py +110 -0
  207. wxcli/commands/meeting_chats.py +63 -0
  208. wxcli/commands/meeting_invitees.py +234 -0
  209. wxcli/commands/meeting_messages.py +28 -0
  210. wxcli/commands/meeting_participants.py +278 -0
  211. wxcli/commands/meeting_polls.py +111 -0
  212. wxcli/commands/meeting_preferences.py +515 -0
  213. wxcli/commands/meeting_qa.py +78 -0
  214. wxcli/commands/meeting_qualities.py +43 -0
  215. wxcli/commands/meeting_reports.py +101 -0
  216. wxcli/commands/meeting_session_types.py +105 -0
  217. wxcli/commands/meeting_site.py +57 -0
  218. wxcli/commands/meeting_slido.py +44 -0
  219. wxcli/commands/meeting_summaries.py +92 -0
  220. wxcli/commands/meeting_tracking_codes.py +233 -0
  221. wxcli/commands/meeting_transcripts.py +230 -0
  222. wxcli/commands/meetings.py +1997 -0
  223. wxcli/commands/memberships.py +164 -0
  224. wxcli/commands/messages.py +213 -0
  225. wxcli/commands/mode_management.py +244 -0
  226. wxcli/commands/my_call_settings.py +3577 -0
  227. wxcli/commands/numbers.py +405 -0
  228. wxcli/commands/operating_modes.py +410 -0
  229. wxcli/commands/org_contacts.py +284 -0
  230. wxcli/commands/org_health_cli.py +55 -0
  231. wxcli/commands/org_settings.py +71 -0
  232. wxcli/commands/organizations.py +83 -0
  233. wxcli/commands/paging_group.py +257 -0
  234. wxcli/commands/partner_admins.py +141 -0
  235. wxcli/commands/partner_reports.py +188 -0
  236. wxcli/commands/partner_tags.py +216 -0
  237. wxcli/commands/people.py +279 -0
  238. wxcli/commands/person_call_settings.py +71 -0
  239. wxcli/commands/pstn.py +280 -0
  240. wxcli/commands/recording_report.py +154 -0
  241. wxcli/commands/report_templates.py +38 -0
  242. wxcli/commands/reports.py +144 -0
  243. wxcli/commands/resource_group_memberships.py +160 -0
  244. wxcli/commands/resource_groups.py +67 -0
  245. wxcli/commands/roles.py +63 -0
  246. wxcli/commands/room_tabs.py +160 -0
  247. wxcli/commands/rooms.py +225 -0
  248. wxcli/commands/scim_bulk.py +46 -0
  249. wxcli/commands/scim_groups.py +246 -0
  250. wxcli/commands/scim_schemas.py +82 -0
  251. wxcli/commands/scim_users.py +283 -0
  252. wxcli/commands/security_audit.py +54 -0
  253. wxcli/commands/service_apps.py +51 -0
  254. wxcli/commands/single_number_reach.py +209 -0
  255. wxcli/commands/team_memberships.py +155 -0
  256. wxcli/commands/teams.py +153 -0
  257. wxcli/commands/ucm_profile.py +42 -0
  258. wxcli/commands/update.py +219 -0
  259. wxcli/commands/user_settings.py +5116 -0
  260. wxcli/commands/video_mesh.py +1090 -0
  261. wxcli/commands/virtual_extensions.py +502 -0
  262. wxcli/commands/virtual_line_settings.py +2072 -0
  263. wxcli/commands/webhooks.py +176 -0
  264. wxcli/commands/wholesale_billing_reports.py +147 -0
  265. wxcli/commands/wholesale_provisioning.py +523 -0
  266. wxcli/commands/workspace_locations.py +339 -0
  267. wxcli/commands/workspace_metrics.py +103 -0
  268. wxcli/commands/workspace_personalization.py +70 -0
  269. wxcli/commands/workspace_settings.py +3347 -0
  270. wxcli/commands/workspaces.py +279 -0
  271. wxcli/commands/xapi.py +114 -0
  272. wxcli/config.py +139 -0
  273. wxcli/errors.py +77 -0
  274. wxcli/main.py +210 -0
  275. wxcli/migration/CLAUDE.md +106 -0
  276. wxcli/migration/__init__.py +1 -0
  277. wxcli/migration/advisory/CLAUDE.md +196 -0
  278. wxcli/migration/advisory/__init__.py +46 -0
  279. wxcli/migration/advisory/advisor.py +107 -0
  280. wxcli/migration/advisory/advisory_patterns.py +2552 -0
  281. wxcli/migration/advisory/recommendation_rules.py +835 -0
  282. wxcli/migration/cucm/CLAUDE.md +74 -0
  283. wxcli/migration/cucm/__init__.py +5 -0
  284. wxcli/migration/cucm/connection.py +265 -0
  285. wxcli/migration/cucm/discovery.py +225 -0
  286. wxcli/migration/cucm/extractors/__init__.py +1 -0
  287. wxcli/migration/cucm/extractors/announcements.py +92 -0
  288. wxcli/migration/cucm/extractors/base.py +90 -0
  289. wxcli/migration/cucm/extractors/device_profiles.py +98 -0
  290. wxcli/migration/cucm/extractors/devices.py +193 -0
  291. wxcli/migration/cucm/extractors/e911.py +103 -0
  292. wxcli/migration/cucm/extractors/features.py +309 -0
  293. wxcli/migration/cucm/extractors/helpers.py +73 -0
  294. wxcli/migration/cucm/extractors/informational.py +295 -0
  295. wxcli/migration/cucm/extractors/locations.py +221 -0
  296. wxcli/migration/cucm/extractors/moh.py +100 -0
  297. wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
  298. wxcli/migration/cucm/extractors/routing.py +493 -0
  299. wxcli/migration/cucm/extractors/shared_lines.py +146 -0
  300. wxcli/migration/cucm/extractors/templates.py +229 -0
  301. wxcli/migration/cucm/extractors/tier4.py +173 -0
  302. wxcli/migration/cucm/extractors/users.py +240 -0
  303. wxcli/migration/cucm/extractors/voicemail.py +243 -0
  304. wxcli/migration/cucm/extractors/workspaces.py +88 -0
  305. wxcli/migration/cucm/unity_connection.py +304 -0
  306. wxcli/migration/execute/CLAUDE.md +372 -0
  307. wxcli/migration/execute/__init__.py +303 -0
  308. wxcli/migration/execute/batch.py +277 -0
  309. wxcli/migration/execute/dependency.py +483 -0
  310. wxcli/migration/execute/engine.py +964 -0
  311. wxcli/migration/execute/handlers.py +2232 -0
  312. wxcli/migration/execute/planner.py +1939 -0
  313. wxcli/migration/execute/runtime.py +571 -0
  314. wxcli/migration/export/CLAUDE.md +49 -0
  315. wxcli/migration/export/__init__.py +8 -0
  316. wxcli/migration/export/csv_export.py +126 -0
  317. wxcli/migration/export/deployment_plan.py +479 -0
  318. wxcli/migration/export/json_export.py +60 -0
  319. wxcli/migration/models.py +941 -0
  320. wxcli/migration/phone_models.py +50 -0
  321. wxcli/migration/preflight/CLAUDE.md +52 -0
  322. wxcli/migration/preflight/__init__.py +89 -0
  323. wxcli/migration/preflight/checks.py +911 -0
  324. wxcli/migration/preflight/runner.py +293 -0
  325. wxcli/migration/rate_limiter.py +144 -0
  326. wxcli/migration/report/CLAUDE.md +245 -0
  327. wxcli/migration/report/__init__.py +7 -0
  328. wxcli/migration/report/appendix.py +2437 -0
  329. wxcli/migration/report/assembler.py +183 -0
  330. wxcli/migration/report/charts.py +263 -0
  331. wxcli/migration/report/executive.py +776 -0
  332. wxcli/migration/report/explainer.py +704 -0
  333. wxcli/migration/report/helpers.py +74 -0
  334. wxcli/migration/report/ingest.py +152 -0
  335. wxcli/migration/report/notice_templates.py +192 -0
  336. wxcli/migration/report/score.py +375 -0
  337. wxcli/migration/report/styles.py +1052 -0
  338. wxcli/migration/report/user_diff.py +1052 -0
  339. wxcli/migration/report/user_notice.py +425 -0
  340. wxcli/migration/state.py +139 -0
  341. wxcli/migration/store.py +860 -0
  342. wxcli/migration/transform/CLAUDE.md +107 -0
  343. wxcli/migration/transform/__init__.py +12 -0
  344. wxcli/migration/transform/analysis_pipeline.py +453 -0
  345. wxcli/migration/transform/analyzers/__init__.py +142 -0
  346. wxcli/migration/transform/analyzers/css_permission.py +189 -0
  347. wxcli/migration/transform/analyzers/css_routing.py +335 -0
  348. wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
  349. wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
  350. wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
  351. wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
  352. wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
  353. wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
  354. wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
  355. wxcli/migration/transform/analyzers/missing_data.py +300 -0
  356. wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
  357. wxcli/migration/transform/analyzers/shared_line.py +170 -0
  358. wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
  359. wxcli/migration/transform/analyzers/workspace_license.py +212 -0
  360. wxcli/migration/transform/cross_reference.py +1136 -0
  361. wxcli/migration/transform/cucm_pattern.py +246 -0
  362. wxcli/migration/transform/decisions.py +301 -0
  363. wxcli/migration/transform/e164.py +145 -0
  364. wxcli/migration/transform/engine.py +256 -0
  365. wxcli/migration/transform/mappers/CLAUDE.md +123 -0
  366. wxcli/migration/transform/mappers/__init__.py +76 -0
  367. wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
  368. wxcli/migration/transform/mappers/base.py +190 -0
  369. wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
  370. wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
  371. wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
  372. wxcli/migration/transform/mappers/css_mapper.py +868 -0
  373. wxcli/migration/transform/mappers/dect_mapper.py +367 -0
  374. wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
  375. wxcli/migration/transform/mappers/device_mapper.py +227 -0
  376. wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
  377. wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
  378. wxcli/migration/transform/mappers/e911_mapper.py +129 -0
  379. wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
  380. wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
  381. wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
  382. wxcli/migration/transform/mappers/line_mapper.py +310 -0
  383. wxcli/migration/transform/mappers/location_mapper.py +235 -0
  384. wxcli/migration/transform/mappers/moh_mapper.py +114 -0
  385. wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
  386. wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
  387. wxcli/migration/transform/mappers/routing_mapper.py +821 -0
  388. wxcli/migration/transform/mappers/snr_mapper.py +201 -0
  389. wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
  390. wxcli/migration/transform/mappers/user_mapper.py +264 -0
  391. wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
  392. wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
  393. wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
  394. wxcli/migration/transform/normalizers.py +2008 -0
  395. wxcli/migration/transform/pattern_converter.py +106 -0
  396. wxcli/migration/transform/pipeline.py +271 -0
  397. wxcli/migration/transform/rules.py +255 -0
  398. wxcli/org_health/CLAUDE.md +63 -0
  399. wxcli/org_health/__init__.py +7 -0
  400. wxcli/org_health/analyze.py +93 -0
  401. wxcli/org_health/checks.py +458 -0
  402. wxcli/org_health/collector.py +62 -0
  403. wxcli/org_health/models.py +78 -0
  404. wxcli/org_health/report.py +300 -0
  405. wxcli/output.py +101 -0
  406. wxcli-1.2.0.dist-info/METADATA +505 -0
  407. wxcli-1.2.0.dist-info/RECORD +413 -0
  408. wxcli-1.2.0.dist-info/WHEEL +5 -0
  409. wxcli-1.2.0.dist-info/entry_points.txt +2 -0
  410. wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
  411. wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
  412. wxcli-1.2.0.dist-info/scm_version.json +8 -0
  413. wxcli-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,194 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-callbacks.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ callback_number: str = typer.Option(None, "--callback-number", help="The callback customer number to filter the scheduled callbac"),
15
+ assignee_agent: str = typer.Option(None, "--assignee-agent", help="The unique identifier of the agent assigned to handle the ca"),
16
+ page: str = typer.Option(None, "--page", help="The page number to retrieve."),
17
+ page_size: str = typer.Option(None, "--page-size", help="The number of items per page."),
18
+ sort_by: str = typer.Option(None, "--sort-by", help="Choices: customerName, scheduledTime, assignedTime"),
19
+ sort_order: str = typer.Option(None, "--sort-order", help="Choices: asc, desc"),
20
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
21
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
22
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
23
+ debug: bool = typer.Option(False, "--debug"),
24
+ ):
25
+ """Get scheduled callbacks."""
26
+ api = get_api(debug=debug)
27
+ cc_base_url = get_cc_base_url()
28
+ org_id = get_cc_org_id(api.session)
29
+ url = f"{cc_base_url}/callbacks/organization/{org_id}/scheduled-callback"
30
+ params = {}
31
+ if callback_number is not None:
32
+ params["callbackNumber"] = callback_number
33
+ if assignee_agent is not None:
34
+ params["assigneeAgent"] = assignee_agent
35
+ if page is not None:
36
+ params["page"] = page
37
+ if page_size is not None:
38
+ params["pageSize"] = page_size
39
+ if sort_by is not None:
40
+ params["sortBy"] = sort_by
41
+ if sort_order is not None:
42
+ params["sortOrder"] = sort_order
43
+ if limit > 0:
44
+ params["max"] = limit
45
+ if offset > 0:
46
+ params["start"] = offset
47
+ result = None
48
+ try:
49
+ result = api.session.rest_get(url, params=params)
50
+ except WebexError as e:
51
+ handle_rest_error(e)
52
+ result = result or []
53
+ items = result.get("data", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
54
+ if output == "json":
55
+ print_json(items)
56
+ else:
57
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
58
+
59
+
60
+
61
+ @app.command("create")
62
+ def create(
63
+ customer_name: str = typer.Option(None, "--customer-name", help="(required) Name of the Customer for which callback has to be scheduled."),
64
+ callback_number: str = typer.Option(None, "--callback-number", help="(required) Customer's phone number for the callback. Allows an optional"),
65
+ timezone: str = typer.Option(None, "--timezone", help="(required) Valid IANA timezone name"),
66
+ schedule_date: str = typer.Option(None, "--schedule-date", help="(required) Scheduled date in ISO-8601 (YYYY-MM-DD) format. This must be"),
67
+ start_time: str = typer.Option(None, "--start-time", help="(required) Scheduled start time in ISO-8601 (HH:mm:ss) format. Start ti"),
68
+ end_time: str = typer.Option(None, "--end-time", help="(required) Scheduled end time in ISO-8601 (HH:mm:ss) format. End time m"),
69
+ queue_id: str = typer.Option(None, "--queue-id", help="(required) Unique identifier for the queue to which the callback is ass"),
70
+ callback_reason: str = typer.Option(None, "--callback-reason", help="Reason for the callback request. This is optional and can be"),
71
+ source_interaction: str = typer.Option(None, "--source-interaction", help="Source interaction ID for the callback. This is optional and"),
72
+ assignee_agent: str = typer.Option(None, "--assignee-agent", help="The unique identifier of the specific agent (CI userId), who"),
73
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
74
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
75
+ debug: bool = typer.Option(False, "--debug"),
76
+ ):
77
+ """Schedule a Callback."""
78
+ api = get_api(debug=debug)
79
+ cc_base_url = get_cc_base_url()
80
+ org_id = get_cc_org_id(api.session)
81
+ url = f"{cc_base_url}/callbacks/organization/{org_id}/scheduled-callback"
82
+ if json_body:
83
+ body = json.loads(json_body)
84
+ else:
85
+ body = {}
86
+ if customer_name is not None:
87
+ body["customerName"] = customer_name
88
+ if callback_number is not None:
89
+ body["callbackNumber"] = callback_number
90
+ if timezone is not None:
91
+ body["timezone"] = timezone
92
+ if schedule_date is not None:
93
+ body["scheduleDate"] = schedule_date
94
+ if start_time is not None:
95
+ body["startTime"] = start_time
96
+ if end_time is not None:
97
+ body["endTime"] = end_time
98
+ if queue_id is not None:
99
+ body["queueId"] = queue_id
100
+ if callback_reason is not None:
101
+ body["callbackReason"] = callback_reason
102
+ if source_interaction is not None:
103
+ body["sourceInteraction"] = source_interaction
104
+ if assignee_agent is not None:
105
+ body["assigneeAgent"] = assignee_agent
106
+ _missing = [f for f in ['customerName', 'callbackNumber', 'timezone', 'scheduleDate', 'startTime', 'endTime', 'queueId'] if f not in body or body[f] is None]
107
+ if _missing:
108
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
109
+ raise typer.Exit(1)
110
+ try:
111
+ result = api.session.rest_post(url, json=body)
112
+ except WebexError as e:
113
+ handle_rest_error(e)
114
+ if output == "json":
115
+ print_json(result)
116
+ elif isinstance(result, dict) and "id" in result:
117
+ typer.echo(f"Created: {result['id']}")
118
+ elif not result or result == {}:
119
+ typer.echo("Created.")
120
+ else:
121
+ print_json(result)
122
+
123
+
124
+
125
+ @app.command("show")
126
+ def show(
127
+ id: str = typer.Argument(help="id"),
128
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
129
+ debug: bool = typer.Option(False, "--debug"),
130
+ ):
131
+ """Get scheduled callback by Id."""
132
+ api = get_api(debug=debug)
133
+ cc_base_url = get_cc_base_url()
134
+ org_id = get_cc_org_id(api.session)
135
+ url = f"{cc_base_url}/callbacks/organization/{org_id}/scheduled-callback/{id}"
136
+ try:
137
+ result = api.session.rest_get(url)
138
+ except WebexError as e:
139
+ handle_rest_error(e)
140
+ if output == "json":
141
+ print_json(result)
142
+ else:
143
+ if isinstance(result, dict):
144
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
145
+ elif isinstance(result, list):
146
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
147
+ else:
148
+ print_json(result)
149
+
150
+
151
+
152
+ @app.command("update")
153
+ def update(
154
+ id: str = typer.Argument(help="id"),
155
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
156
+ debug: bool = typer.Option(False, "--debug"),
157
+ ):
158
+ """Update scheduled callback by Id."""
159
+ api = get_api(debug=debug)
160
+ cc_base_url = get_cc_base_url()
161
+ org_id = get_cc_org_id(api.session)
162
+ url = f"{cc_base_url}/callbacks/organization/{org_id}/scheduled-callback/{id}"
163
+ if json_body:
164
+ body = json.loads(json_body)
165
+ else:
166
+ body = {}
167
+ try:
168
+ result = api.session.rest_put(url, json=body)
169
+ except WebexError as e:
170
+ handle_rest_error(e)
171
+ typer.echo(f"Updated.")
172
+
173
+
174
+
175
+ @app.command("delete")
176
+ def delete(
177
+ id: str = typer.Argument(help="id"),
178
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
179
+ debug: bool = typer.Option(False, "--debug"),
180
+ ):
181
+ """Delete scheduled callback by Id."""
182
+ if not force:
183
+ typer.confirm(f"Delete {id}?", abort=True)
184
+ api = get_api(debug=debug)
185
+ cc_base_url = get_cc_base_url()
186
+ org_id = get_cc_org_id(api.session)
187
+ url = f"{cc_base_url}/callbacks/organization/{org_id}/scheduled-callback/{id}"
188
+ try:
189
+ api.session.rest_delete(url)
190
+ except WebexError as e:
191
+ handle_rest_error(e)
192
+ typer.echo(f"Deleted: {id}")
193
+
194
+
@@ -0,0 +1,212 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-campaign.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ id_param: str = typer.Option(None, "--id", help="(required) The id represents the unique id with which the Campaign Requ"),
15
+ vendor_version: str = typer.Option(None, "--vendor-version", help="(required) Vendor specific information, maximum length 32 characters."),
16
+ campaign_type: str = typer.Option(None, "--campaign-type", help="(required) Type of campaign and campaignType should be one of \"progress"),
17
+ campaign_name: str = typer.Option(None, "--campaign-name", help="(Optional) Used if different than id, maximum length 64 char"),
18
+ auth_token: str = typer.Option(None, "--auth-token", help="(Not in use) The token needed by the dialer for querying rec"),
19
+ dialing_rate: str = typer.Option(None, "--dialing-rate", help="(required) Number of contacts to be dialed out per available Agent. For"),
20
+ entry_point_id: str = typer.Option(None, "--entry-point-id", help="(required) Webex Contact Center outdial entry point, maximum length 36"),
21
+ dialing_list_fetch_url: str = typer.Option(None, "--dialing-list-fetch-url", help="(required) URL the dialer will use to fetch the list of contacts to dia"),
22
+ outdial_ani: str = typer.Option(None, "--outdial-ani", help="(required) The ANI (E164) that will be presented to the customer. Thes"),
23
+ record_count: str = typer.Option(None, "--record-count", help="(required) Value to indicate the recordCount the Campaign Manager expec"),
24
+ no_answer_ring_limit: str = typer.Option(None, "--no-answer-ring-limit", help="(Optional) Number of seconds before a dialed call from the d"),
25
+ max_dialing_rate: str = typer.Option(None, "--max-dialing-rate", help="Caps the maximum dialing rate per agent at this value. The r"),
26
+ abandon_rate_percentage: str = typer.Option(None, "--abandon-rate-percentage", help="The percentage of calls that are allowed to be abandoned. Th"),
27
+ predictive_correction_pace: str = typer.Option(None, "--predictive-correction-pace", help="A count of the number of live voice connections that must oc"),
28
+ predictive_gain: str = typer.Option(None, "--predictive-gain", help="The size of the adjustment to lines per agent each time an a"),
29
+ reservation_percentage: str = typer.Option(None, "--reservation-percentage", help="(Not in use) The percentage of agents to reserve within the"),
30
+ ivr_ports: str = typer.Option(None, "--ivr-ports", help="The number of IVR ports to use for this campaign. IVR ports"),
31
+ preview_offer_timeout: str = typer.Option(None, "--preview-offer-timeout", help="(Required if previewOfferTimeoutAutoAction is provided, opti"),
32
+ preview_offer_timeout_auto_action: str = typer.Option(None, "--preview-offer-timeout-auto-action", help="(Required if previewOfferTimeout is provided, optional other"),
33
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
34
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
35
+ debug: bool = typer.Option(False, "--debug"),
36
+ ):
37
+ """Start Campaign Request\n\nExample --json-body:\n '{"id":"...","vendorVersion":"...","campaignType":"...","dialingRate":0,"entryPointId":"...","dialingListFetchURL":"...","outdialANI":"...","recordCount":0}'."""
38
+ api = get_api(debug=debug)
39
+ cc_base_url = get_cc_base_url()
40
+ url = f"{cc_base_url}/dialer/campaign"
41
+ if json_body:
42
+ body = json.loads(json_body)
43
+ else:
44
+ body = {}
45
+ if id_param is not None:
46
+ body["id"] = id_param
47
+ if vendor_version is not None:
48
+ body["vendorVersion"] = vendor_version
49
+ if campaign_type is not None:
50
+ body["campaignType"] = campaign_type
51
+ if campaign_name is not None:
52
+ body["campaignName"] = campaign_name
53
+ if auth_token is not None:
54
+ body["authToken"] = auth_token
55
+ if dialing_rate is not None:
56
+ body["dialingRate"] = dialing_rate
57
+ if entry_point_id is not None:
58
+ body["entryPointId"] = entry_point_id
59
+ if dialing_list_fetch_url is not None:
60
+ body["dialingListFetchURL"] = dialing_list_fetch_url
61
+ if outdial_ani is not None:
62
+ body["outdialANI"] = outdial_ani
63
+ if record_count is not None:
64
+ body["recordCount"] = record_count
65
+ if no_answer_ring_limit is not None:
66
+ body["noAnswerRingLimit"] = no_answer_ring_limit
67
+ if max_dialing_rate is not None:
68
+ body["maxDialingRate"] = max_dialing_rate
69
+ if abandon_rate_percentage is not None:
70
+ body["abandonRatePercentage"] = abandon_rate_percentage
71
+ if predictive_correction_pace is not None:
72
+ body["predictiveCorrectionPace"] = predictive_correction_pace
73
+ if predictive_gain is not None:
74
+ body["predictiveGain"] = predictive_gain
75
+ if reservation_percentage is not None:
76
+ body["reservationPercentage"] = reservation_percentage
77
+ if ivr_ports is not None:
78
+ body["ivrPorts"] = ivr_ports
79
+ if preview_offer_timeout is not None:
80
+ body["previewOfferTimeout"] = preview_offer_timeout
81
+ if preview_offer_timeout_auto_action is not None:
82
+ body["previewOfferTimeoutAutoAction"] = preview_offer_timeout_auto_action
83
+ _missing = [f for f in ['id', 'vendorVersion', 'campaignType', 'dialingRate', 'entryPointId', 'dialingListFetchURL', 'outdialANI', 'recordCount'] if f not in body or body[f] is None]
84
+ if _missing:
85
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
86
+ raise typer.Exit(1)
87
+ try:
88
+ result = api.session.rest_post(url, json=body)
89
+ except WebexError as e:
90
+ handle_rest_error(e)
91
+ if output == "json":
92
+ print_json(result)
93
+ elif isinstance(result, dict) and "id" in result:
94
+ typer.echo(f"Created: {result['id']}")
95
+ elif not result or result == {}:
96
+ typer.echo("Created.")
97
+ else:
98
+ print_json(result)
99
+
100
+
101
+
102
+ @app.command("list")
103
+ def cmd_list(
104
+ campaign_id: str = typer.Option(..., "--campaign-id", help="The campaign ID for which valid campaign times are being req"),
105
+ agent_id: str = typer.Option(..., "--agent-id", help="The agent ID for whom valid campaign times are being request"),
106
+ tracking_id: str = typer.Option(None, "--tracking-id", help="Optional tracking identifier for request tracing."),
107
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
108
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
109
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
110
+ debug: bool = typer.Option(False, "--debug"),
111
+ ):
112
+ """Get Valid Campaign Times."""
113
+ api = get_api(debug=debug)
114
+ cc_base_url = get_cc_base_url()
115
+ org_id = get_cc_org_id(api.session)
116
+ url = f"{cc_base_url}/organization/{org_id}/getValidCampaignTimes"
117
+ params = {}
118
+ if campaign_id is not None:
119
+ params["campaignId"] = campaign_id
120
+ if agent_id is not None:
121
+ params["agentId"] = agent_id
122
+ if tracking_id is not None:
123
+ params["trackingId"] = tracking_id
124
+ if limit > 0:
125
+ params["max"] = limit
126
+ if offset > 0:
127
+ params["start"] = offset
128
+ result = None
129
+ try:
130
+ result = api.session.rest_get(url, params=params)
131
+ except WebexError as e:
132
+ handle_rest_error(e)
133
+ result = result or []
134
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
135
+ if output == "json":
136
+ print_json(items)
137
+ else:
138
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
139
+
140
+
141
+
142
+ @app.command("update")
143
+ def update(
144
+ campaign_id: str = typer.Argument(help="campaignId"),
145
+ dialing_rate: str = typer.Option(None, "--dialing-rate", help="Number of contacts to be dialed out per available Agent. For"),
146
+ campaign_name: str = typer.Option(None, "--campaign-name", help="(Optional) Used if different than id, maximum length 64 char"),
147
+ auth_token: str = typer.Option(None, "--auth-token", help="(Not in use) The token needed by the dialer for querying rec"),
148
+ dialing_list_fetch_url: str = typer.Option(None, "--dialing-list-fetch-url", help="URL the dialer will use to fetch the list of contacts to dia"),
149
+ outdial_ani: str = typer.Option(None, "--outdial-ani", help="The ANI (E164) that will be presented to the customer. Thes"),
150
+ no_answer_ring_limit: str = typer.Option(None, "--no-answer-ring-limit", help="(Optional) Number of seconds before a dialed call from the d"),
151
+ max_dialing_rate: str = typer.Option(None, "--max-dialing-rate", help="Caps the maximum dialing rate per agent at this value. The r"),
152
+ reservation_percentage: str = typer.Option(None, "--reservation-percentage", help="(Not in use) The percentage of agents to reserve within the"),
153
+ preview_offer_timeout: str = typer.Option(None, "--preview-offer-timeout", help="(Required only if previewOfferTimeoutAutoAction is provided)"),
154
+ preview_offer_timeout_auto_action: str = typer.Option(None, "--preview-offer-timeout-auto-action", help="(Required only if previewOfferTimeout is provided) The autom"),
155
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
156
+ debug: bool = typer.Option(False, "--debug"),
157
+ ):
158
+ """Update Campaign Request\n\nExample --json-body:\n '{"dialingRate":0,"dialingListFetchURL":"...","outdialANI":"...","campaignName":"...","authToken":"...","noAnswerRingLimit":0,"maxDialingRate":0,"reservationPercentage":0}'."""
159
+ api = get_api(debug=debug)
160
+ cc_base_url = get_cc_base_url()
161
+ url = f"{cc_base_url}/dialer/campaign/{campaign_id}"
162
+ if json_body:
163
+ body = json.loads(json_body)
164
+ else:
165
+ body = {}
166
+ if dialing_rate is not None:
167
+ body["dialingRate"] = dialing_rate
168
+ if campaign_name is not None:
169
+ body["campaignName"] = campaign_name
170
+ if auth_token is not None:
171
+ body["authToken"] = auth_token
172
+ if dialing_list_fetch_url is not None:
173
+ body["dialingListFetchURL"] = dialing_list_fetch_url
174
+ if outdial_ani is not None:
175
+ body["outdialANI"] = outdial_ani
176
+ if no_answer_ring_limit is not None:
177
+ body["noAnswerRingLimit"] = no_answer_ring_limit
178
+ if max_dialing_rate is not None:
179
+ body["maxDialingRate"] = max_dialing_rate
180
+ if reservation_percentage is not None:
181
+ body["reservationPercentage"] = reservation_percentage
182
+ if preview_offer_timeout is not None:
183
+ body["previewOfferTimeout"] = preview_offer_timeout
184
+ if preview_offer_timeout_auto_action is not None:
185
+ body["previewOfferTimeoutAutoAction"] = preview_offer_timeout_auto_action
186
+ try:
187
+ result = api.session.rest_put(url, json=body)
188
+ except WebexError as e:
189
+ handle_rest_error(e)
190
+ typer.echo(f"Updated.")
191
+
192
+
193
+
194
+ @app.command("delete")
195
+ def delete(
196
+ campaign_id: str = typer.Argument(help="campaignId"),
197
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
198
+ debug: bool = typer.Option(False, "--debug"),
199
+ ):
200
+ """Stop Campaign Request."""
201
+ if not force:
202
+ typer.confirm(f"Delete {campaign_id}?", abort=True)
203
+ api = get_api(debug=debug)
204
+ cc_base_url = get_cc_base_url()
205
+ url = f"{cc_base_url}/dialer/campaign/{campaign_id}"
206
+ try:
207
+ api.session.rest_delete(url)
208
+ except WebexError as e:
209
+ handle_rest_error(e)
210
+ typer.echo(f"Deleted: {campaign_id}")
211
+
212
+
@@ -0,0 +1,39 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import get_cc_base_url
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-captures.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
15
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
16
+ debug: bool = typer.Option(False, "--debug"),
17
+ ):
18
+ """List Captures\n\nExample --json-body:\n '{"query":{"taskIds":["..."],"orgId":"...","urlExpiration":0,"includeSegments":true,"includeVARecordings":true,"includeScreenRecordings":true}}'."""
19
+ api = get_api(debug=debug)
20
+ cc_base_url = get_cc_base_url()
21
+ url = f"{cc_base_url}/captures/query"
22
+ if json_body:
23
+ body = json.loads(json_body)
24
+ else:
25
+ body = {}
26
+ try:
27
+ result = api.session.rest_post(url, json=body)
28
+ except WebexError as e:
29
+ handle_rest_error(e)
30
+ if output == "json":
31
+ print_json(result)
32
+ elif isinstance(result, dict) and "id" in result:
33
+ typer.echo(f"Created: {result['id']}")
34
+ elif not result or result == {}:
35
+ typer.echo("Created.")
36
+ else:
37
+ print_json(result)
38
+
39
+
@@ -0,0 +1,169 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import get_cc_base_url
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-contact-list.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ campaign_id: str = typer.Argument(help="campaignId"),
15
+ activation_time_lag_minutes: str = typer.Option(None, "--activation-time-lag-minutes", help="Contact list activation time lag in minutes (0 = immediate a"),
16
+ activation_date_time: str = typer.Option(None, "--activation-date-time", help="Contact list activation DateTimeStamp (format: YYYY-MM-DDTHH"),
17
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
18
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
19
+ debug: bool = typer.Option(False, "--debug"),
20
+ ):
21
+ """Create contact list\n\nExample --json-body:\n '{"supportedChannels":["Voice"],"activationTimeLagMinutes":0,"activationDateTime":"..."}'."""
22
+ api = get_api(debug=debug)
23
+ cc_base_url = get_cc_base_url()
24
+ url = f"{cc_base_url}/v3/campaign-management/campaigns/{campaign_id}/contact-list"
25
+ if json_body:
26
+ body = json.loads(json_body)
27
+ else:
28
+ body = {}
29
+ if activation_time_lag_minutes is not None:
30
+ body["activationTimeLagMinutes"] = activation_time_lag_minutes
31
+ if activation_date_time is not None:
32
+ body["activationDateTime"] = activation_date_time
33
+ try:
34
+ result = api.session.rest_post(url, json=body)
35
+ except WebexError as e:
36
+ handle_rest_error(e)
37
+ if output == "json":
38
+ print_json(result)
39
+ elif isinstance(result, dict) and "contactListId" in result:
40
+ typer.echo(f"Created: {result['contactListId']}")
41
+ elif isinstance(result, dict) and "id" in result:
42
+ typer.echo(f"Created: {result['id']}")
43
+ elif not result or result == {}:
44
+ typer.echo("Created.")
45
+ else:
46
+ print_json(result)
47
+
48
+
49
+
50
+ @app.command("create-contacts")
51
+ def create_contacts(
52
+ campaign_id: str = typer.Argument(help="campaignId"),
53
+ contact_list_id: str = typer.Argument(help="contactListId"),
54
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
55
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
56
+ debug: bool = typer.Option(False, "--debug"),
57
+ ):
58
+ """Create contacts within a contact list\n\nExample --json-body:\n '{"contacts":[{"contactAttributes":"..."}]}'."""
59
+ api = get_api(debug=debug)
60
+ cc_base_url = get_cc_base_url()
61
+ url = f"{cc_base_url}/v3/campaign-management/campaigns/{campaign_id}/contact-list/{contact_list_id}/contacts"
62
+ if json_body:
63
+ body = json.loads(json_body)
64
+ else:
65
+ body = {}
66
+ try:
67
+ result = api.session.rest_post(url, json=body)
68
+ except WebexError as e:
69
+ handle_rest_error(e)
70
+ if output == "json":
71
+ print_json(result)
72
+ elif isinstance(result, dict) and "id" in result:
73
+ typer.echo(f"Created: {result['id']}")
74
+ elif not result or result == {}:
75
+ typer.echo("Created.")
76
+ else:
77
+ print_json(result)
78
+
79
+
80
+
81
+ @app.command("update")
82
+ def update(
83
+ campaign_id: str = typer.Argument(help="campaignId"),
84
+ contact_list_id: str = typer.Argument(help="contactListId"),
85
+ contact_id: str = typer.Argument(help="contactId"),
86
+ contact_status: str = typer.Option(None, "--contact-status", help="Choices: CLOSED"),
87
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
88
+ debug: bool = typer.Option(False, "--debug"),
89
+ ):
90
+ """Update a contact's status within a contact list."""
91
+ api = get_api(debug=debug)
92
+ cc_base_url = get_cc_base_url()
93
+ url = f"{cc_base_url}/v3/campaign-management/campaigns/{campaign_id}/contact-list/{contact_list_id}/contacts/{contact_id}"
94
+ if json_body:
95
+ body = json.loads(json_body)
96
+ else:
97
+ body = {}
98
+ if contact_status is not None:
99
+ body["contactStatus"] = contact_status
100
+ try:
101
+ result = api.session.rest_patch(url, json=body)
102
+ except WebexError as e:
103
+ handle_rest_error(e)
104
+ typer.echo(f"Updated.")
105
+
106
+
107
+
108
+ @app.command("update-status")
109
+ def update_status(
110
+ campaign_id: str = typer.Argument(help="campaignId"),
111
+ contact_list_id: str = typer.Argument(help="contactListId"),
112
+ contact_list_status: str = typer.Option(None, "--contact-list-status", help="Contact List Status (e.g., EXPIRED). Note: This value is not"),
113
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
114
+ debug: bool = typer.Option(False, "--debug"),
115
+ ):
116
+ """Update contact list status."""
117
+ api = get_api(debug=debug)
118
+ cc_base_url = get_cc_base_url()
119
+ url = f"{cc_base_url}/v3/campaign-management/campaigns/{campaign_id}/contact-list/{contact_list_id}/status"
120
+ if json_body:
121
+ body = json.loads(json_body)
122
+ else:
123
+ body = {}
124
+ if contact_list_status is not None:
125
+ body["contactListStatus"] = contact_list_status
126
+ try:
127
+ result = api.session.rest_patch(url, json=body)
128
+ except WebexError as e:
129
+ handle_rest_error(e)
130
+ typer.echo(f"Updated.")
131
+
132
+
133
+
134
+ @app.command("list")
135
+ def cmd_list(
136
+ campaign_id: str = typer.Argument(help="campaignId"),
137
+ status: str = typer.Option(None, "--status", help="Choices: Active, Expired, UploadFailed"),
138
+ source: str = typer.Option(None, "--source", help="Choices: API, SFTP, ManualFile, GlobalUpload, GlobalSFTP"),
139
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
140
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
141
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
142
+ debug: bool = typer.Option(False, "--debug"),
143
+ ):
144
+ """Get Contact Lists within a Campaign."""
145
+ api = get_api(debug=debug)
146
+ cc_base_url = get_cc_base_url()
147
+ url = f"{cc_base_url}/v3/campaign-management/campaigns/{campaign_id}/contact-lists"
148
+ params = {}
149
+ if status is not None:
150
+ params["status"] = status
151
+ if source is not None:
152
+ params["source"] = source
153
+ if limit > 0:
154
+ params["max"] = limit
155
+ if offset > 0:
156
+ params["start"] = offset
157
+ result = None
158
+ try:
159
+ result = api.session.rest_get(url, params=params)
160
+ except WebexError as e:
161
+ handle_rest_error(e)
162
+ result = result or []
163
+ items = result.get("contactLists", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
164
+ if output == "json":
165
+ print_json(items)
166
+ else:
167
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
168
+
169
+