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,55 @@
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_org_id, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-queue-stats.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ from_param: str = typer.Option(..., "--from", help="Start time for the query (in epoch milliseconds). Any epoch"),
15
+ to: str = typer.Option(..., "--to", help="End time for the query (in epoch milliseconds). Any epoch ti"),
16
+ interval: str = typer.Option(None, "--interval", help="Time interval (in minutes) to chunk statistics by i.e. break"),
17
+ queue_ids: str = typer.Option(None, "--queue-ids", help="Comma-separated list of queue IDs. A maximum of 100 values i"),
18
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
19
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
20
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
21
+ debug: bool = typer.Option(False, "--debug"),
22
+ ):
23
+ """Get Queue Statistics."""
24
+ api = get_api(debug=debug)
25
+ cc_base_url = get_cc_base_url()
26
+ url = f"{cc_base_url}/queues/statistics"
27
+ params = {}
28
+ if from_param is not None:
29
+ params["from"] = from_param
30
+ if to is not None:
31
+ params["to"] = to
32
+ if interval is not None:
33
+ params["interval"] = interval
34
+ if queue_ids is not None:
35
+ params["queueIds"] = queue_ids
36
+ if limit > 0:
37
+ params["max"] = limit
38
+ if offset > 0:
39
+ params["start"] = offset
40
+ org_id = get_org_id()
41
+ if org_id is not None:
42
+ params["orgId"] = org_id
43
+ result = None
44
+ try:
45
+ result = api.session.rest_get(url, params=params)
46
+ except WebexError as e:
47
+ handle_rest_error(e)
48
+ result = result or []
49
+ items = result.get("data", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
50
+ if output == "json":
51
+ print_json(items)
52
+ else:
53
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
54
+
55
+
@@ -0,0 +1,51 @@
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-realtime.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ is_keep_alive_enabled: bool = typer.Option(None, "--is-keep-alive-enabled/--no-is-keep-alive-enabled", help="This represents that a json message {\\\"keepalive\\\":\\\"true\\\"}"),
15
+ client_type: str = typer.Option(None, "--client-type", help="ClientType is used to identify a web application differently"),
16
+ allow_multi_login: bool = typer.Option(None, "--allow-multi-login/--no-allow-multi-login", help="This cannot be used without providing \\\"clientType\\\". When s"),
17
+ force: bool = typer.Option(None, "--force/--no-force", help="When true, will drop a random connection and then subscribes"),
18
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
19
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
20
+ debug: bool = typer.Option(False, "--debug"),
21
+ ):
22
+ """Subscribe Realtime Notification."""
23
+ api = get_api(debug=debug)
24
+ cc_base_url = get_cc_base_url()
25
+ url = f"{cc_base_url}/realtime/subscribe"
26
+ if json_body:
27
+ body = json.loads(json_body)
28
+ else:
29
+ body = {}
30
+ if is_keep_alive_enabled is not None:
31
+ body["isKeepAliveEnabled"] = is_keep_alive_enabled
32
+ if client_type is not None:
33
+ body["clientType"] = client_type
34
+ if allow_multi_login is not None:
35
+ body["allowMultiLogin"] = allow_multi_login
36
+ if force is not None:
37
+ body["force"] = force
38
+ try:
39
+ result = api.session.rest_post(url, json=body)
40
+ except WebexError as e:
41
+ handle_rest_error(e)
42
+ if output == "json":
43
+ print_json(result)
44
+ elif isinstance(result, dict) and "id" in result:
45
+ typer.echo(f"Created: {result['id']}")
46
+ elif not result or result == {}:
47
+ typer.echo("Created.")
48
+ else:
49
+ print_json(result)
50
+
51
+
@@ -0,0 +1,312 @@
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-resource-collection.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ organization_id: str = typer.Option(None, "--organization-id", help="ID of the contact center organization. This field is require"),
15
+ id_param: str = typer.Option(None, "--id", help="ID of this contact center resource. It should not be specifi"),
16
+ version: str = typer.Option(None, "--version", help="The version of this resource. For a newly created resource,"),
17
+ name: str = typer.Option(None, "--name", help="(required) The name of the resource collection."),
18
+ description: str = typer.Option(None, "--description", help="An optional description of the resource collection."),
19
+ resource_count: str = typer.Option(None, "--resource-count", help="The total count of resources in this collection"),
20
+ created_time: str = typer.Option(None, "--created-time", help="This is the created time of the entity."),
21
+ last_updated_time: str = typer.Option(None, "--last-updated-time", help="This is the updated time of the entity."),
22
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
23
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
24
+ debug: bool = typer.Option(False, "--debug"),
25
+ ):
26
+ """Create a new Resource Collection\n\nExample --json-body:\n '{"name":"...","organizationId":"...","id":"...","version":0,"description":"...","resources":[{"name":"...","accessLevel":"...","ids":"..."}],"resourceCount":0,"createdTime":0}'."""
27
+ api = get_api(debug=debug)
28
+ cc_base_url = get_cc_base_url()
29
+ orgid = get_cc_org_id(api.session)
30
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection"
31
+ if json_body:
32
+ body = json.loads(json_body)
33
+ else:
34
+ body = {}
35
+ if organization_id is not None:
36
+ body["organizationId"] = organization_id
37
+ if id_param is not None:
38
+ body["id"] = id_param
39
+ if version is not None:
40
+ body["version"] = version
41
+ if name is not None:
42
+ body["name"] = name
43
+ if description is not None:
44
+ body["description"] = description
45
+ if resource_count is not None:
46
+ body["resourceCount"] = resource_count
47
+ if created_time is not None:
48
+ body["createdTime"] = created_time
49
+ if last_updated_time is not None:
50
+ body["lastUpdatedTime"] = last_updated_time
51
+ _missing = [f for f in ['name'] if f not in body or body[f] is None]
52
+ if _missing:
53
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
54
+ raise typer.Exit(1)
55
+ try:
56
+ result = api.session.rest_post(url, json=body)
57
+ except WebexError as e:
58
+ handle_rest_error(e)
59
+ if output == "json":
60
+ print_json(result)
61
+ elif isinstance(result, dict) and "id" in result:
62
+ typer.echo(f"Created: {result['id']}")
63
+ elif not result or result == {}:
64
+ typer.echo("Created.")
65
+ else:
66
+ print_json(result)
67
+
68
+
69
+
70
+ @app.command("update")
71
+ def update(
72
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
73
+ debug: bool = typer.Option(False, "--debug"),
74
+ ):
75
+ """Bulk partial update Resource Collections\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
76
+ api = get_api(debug=debug)
77
+ cc_base_url = get_cc_base_url()
78
+ orgid = get_cc_org_id(api.session)
79
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection/bulk"
80
+ if json_body:
81
+ body = json.loads(json_body)
82
+ else:
83
+ body = {}
84
+ try:
85
+ result = api.session.rest_patch(url, json=body)
86
+ except WebexError as e:
87
+ handle_rest_error(e)
88
+ typer.echo(f"Updated.")
89
+
90
+
91
+
92
+ @app.command("create-update-resource")
93
+ def create_update_resource(
94
+ resource_type: str = typer.Option(None, "--resource-type", help="(required) Resource type."),
95
+ resource_id: str = typer.Option(None, "--resource-id", help="(required) Resource Id."),
96
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
97
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
98
+ debug: bool = typer.Option(False, "--debug"),
99
+ ):
100
+ """Update resource with default resource collection\n\nExample --json-body:\n '{"resourceType":"...","resourceId":"...","resourceCollections":[{"id":"..."}]}'."""
101
+ api = get_api(debug=debug)
102
+ cc_base_url = get_cc_base_url()
103
+ orgid = get_cc_org_id(api.session)
104
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection/update-resource"
105
+ if json_body:
106
+ body = json.loads(json_body)
107
+ else:
108
+ body = {}
109
+ if resource_type is not None:
110
+ body["resourceType"] = resource_type
111
+ if resource_id is not None:
112
+ body["resourceId"] = resource_id
113
+ _missing = [f for f in ['resourceType', 'resourceId'] if f not in body or body[f] is None]
114
+ if _missing:
115
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
116
+ raise typer.Exit(1)
117
+ try:
118
+ result = api.session.rest_post(url, json=body)
119
+ except WebexError as e:
120
+ handle_rest_error(e)
121
+ if output == "json":
122
+ print_json(result)
123
+ elif isinstance(result, dict) and "id" in result:
124
+ typer.echo(f"Created: {result['id']}")
125
+ elif not result or result == {}:
126
+ typer.echo("Created.")
127
+ else:
128
+ print_json(result)
129
+
130
+
131
+
132
+ @app.command("show")
133
+ def show(
134
+ id: str = typer.Argument(help="id"),
135
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
136
+ debug: bool = typer.Option(False, "--debug"),
137
+ ):
138
+ """Get specific Resource Collection by ID."""
139
+ api = get_api(debug=debug)
140
+ cc_base_url = get_cc_base_url()
141
+ orgid = get_cc_org_id(api.session)
142
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection/{id}"
143
+ try:
144
+ result = api.session.rest_get(url)
145
+ except WebexError as e:
146
+ handle_rest_error(e)
147
+ if output == "json":
148
+ print_json(result)
149
+ else:
150
+ if isinstance(result, dict):
151
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
152
+ elif isinstance(result, list):
153
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
154
+ else:
155
+ print_json(result)
156
+
157
+
158
+
159
+ @app.command("update-resource-collection")
160
+ def update_resource_collection(
161
+ id: str = typer.Argument(help="id"),
162
+ organization_id: str = typer.Option(None, "--organization-id", help="ID of the contact center organization. This field is require"),
163
+ id_param: str = typer.Option(None, "--id", help="ID of this contact center resource. It should not be specifi"),
164
+ version: str = typer.Option(None, "--version", help="The version of this resource. For a newly created resource,"),
165
+ name: str = typer.Option(None, "--name", help="The name of the resource collection."),
166
+ description: str = typer.Option(None, "--description", help="An optional description of the resource collection."),
167
+ resource_count: str = typer.Option(None, "--resource-count", help="The total count of resources in this collection"),
168
+ created_time: str = typer.Option(None, "--created-time", help="This is the created time of the entity."),
169
+ last_updated_time: str = typer.Option(None, "--last-updated-time", help="This is the updated time of the entity."),
170
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
171
+ debug: bool = typer.Option(False, "--debug"),
172
+ ):
173
+ """Update specific Resource Collection by ID\n\nExample --json-body:\n '{"name":"...","organizationId":"...","id":"...","version":0,"description":"...","resources":[{"name":"...","accessLevel":"...","ids":"..."}],"resourceCount":0,"createdTime":0}'."""
174
+ api = get_api(debug=debug)
175
+ cc_base_url = get_cc_base_url()
176
+ orgid = get_cc_org_id(api.session)
177
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection/{id}"
178
+ if json_body:
179
+ body = json.loads(json_body)
180
+ else:
181
+ body = {}
182
+ if organization_id is not None:
183
+ body["organizationId"] = organization_id
184
+ if id_param is not None:
185
+ body["id"] = id_param
186
+ if version is not None:
187
+ body["version"] = version
188
+ if name is not None:
189
+ body["name"] = name
190
+ if description is not None:
191
+ body["description"] = description
192
+ if resource_count is not None:
193
+ body["resourceCount"] = resource_count
194
+ if created_time is not None:
195
+ body["createdTime"] = created_time
196
+ if last_updated_time is not None:
197
+ body["lastUpdatedTime"] = last_updated_time
198
+ try:
199
+ result = api.session.rest_put(url, json=body)
200
+ except WebexError as e:
201
+ handle_rest_error(e)
202
+ typer.echo(f"Updated.")
203
+
204
+
205
+
206
+ @app.command("delete")
207
+ def delete(
208
+ id: str = typer.Argument(help="id"),
209
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
210
+ debug: bool = typer.Option(False, "--debug"),
211
+ ):
212
+ """Delete specific Resource Collection by ID."""
213
+ if not force:
214
+ typer.confirm(f"Delete {id}?", abort=True)
215
+ api = get_api(debug=debug)
216
+ cc_base_url = get_cc_base_url()
217
+ orgid = get_cc_org_id(api.session)
218
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection/{id}"
219
+ try:
220
+ api.session.rest_delete(url)
221
+ except WebexError as e:
222
+ handle_rest_error(e)
223
+ typer.echo(f"Deleted: {id}")
224
+
225
+
226
+
227
+ @app.command("list")
228
+ def cmd_list(
229
+ id: str = typer.Argument(help="id"),
230
+ type_param: str = typer.Option(None, "--type", help="Entity type of the other entity that has a reference to this"),
231
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
232
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
233
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
234
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
235
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
236
+ debug: bool = typer.Option(False, "--debug"),
237
+ ):
238
+ """List references for a specific Resource Collection."""
239
+ api = get_api(debug=debug)
240
+ cc_base_url = get_cc_base_url()
241
+ orgid = get_cc_org_id(api.session)
242
+ url = f"{cc_base_url}/organization/{orgid}/resource-collection/{id}/incoming-references"
243
+ params = {}
244
+ if type_param is not None:
245
+ params["type"] = type_param
246
+ if page is not None:
247
+ params["page"] = page
248
+ if page_size is not None:
249
+ params["pageSize"] = page_size
250
+ if limit > 0:
251
+ params["max"] = limit
252
+ if offset > 0:
253
+ params["start"] = offset
254
+ result = None
255
+ try:
256
+ result = api.session.rest_get(url, params=params)
257
+ except WebexError as e:
258
+ handle_rest_error(e)
259
+ result = result or []
260
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
261
+ if output == "json":
262
+ print_json(items)
263
+ else:
264
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
265
+
266
+
267
+
268
+ @app.command("list-resource-collection")
269
+ def list_resource_collection(
270
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
271
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
272
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
273
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
274
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
275
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
276
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
277
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
278
+ debug: bool = typer.Option(False, "--debug"),
279
+ ):
280
+ """List Resource Collections."""
281
+ api = get_api(debug=debug)
282
+ cc_base_url = get_cc_base_url()
283
+ orgid = get_cc_org_id(api.session)
284
+ url = f"{cc_base_url}/organization/{orgid}/v2/resource-collection"
285
+ params = {}
286
+ if filter_param is not None:
287
+ params["filter"] = filter_param
288
+ if attributes is not None:
289
+ params["attributes"] = attributes
290
+ if search is not None:
291
+ params["search"] = search
292
+ if page is not None:
293
+ params["page"] = page
294
+ if page_size is not None:
295
+ params["pageSize"] = page_size
296
+ if limit > 0:
297
+ params["max"] = limit
298
+ if offset > 0:
299
+ params["start"] = offset
300
+ result = None
301
+ try:
302
+ result = api.session.rest_get(url, params=params)
303
+ except WebexError as e:
304
+ handle_rest_error(e)
305
+ result = result or []
306
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
307
+ if output == "json":
308
+ print_json(items)
309
+ else:
310
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
311
+
312
+
@@ -0,0 +1,46 @@
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_org_id, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-search.")
10
+
11
+
12
+ @app.command("create")
13
+ def create(
14
+ query: str = typer.Option(None, "--query", help="A graphQL query specifying the task attributes needed in the"),
15
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
16
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
17
+ debug: bool = typer.Option(False, "--debug"),
18
+ ):
19
+ """Search tasks\n\nExample --json-body:\n '{"variables":{},"query":"..."}'."""
20
+ api = get_api(debug=debug)
21
+ cc_base_url = get_cc_base_url()
22
+ url = f"{cc_base_url}/search"
23
+ params = {}
24
+ org_id = get_org_id()
25
+ if org_id is not None:
26
+ params["orgId"] = org_id
27
+ if json_body:
28
+ body = json.loads(json_body)
29
+ else:
30
+ body = {}
31
+ if query is not None:
32
+ body["query"] = query
33
+ try:
34
+ result = api.session.rest_post(url, json=body, params=params)
35
+ except WebexError as e:
36
+ handle_rest_error(e)
37
+ if output == "json":
38
+ print_json(result)
39
+ elif isinstance(result, dict) and "id" in result:
40
+ typer.echo(f"Created: {result['id']}")
41
+ elif not result or result == {}:
42
+ typer.echo("Created.")
43
+ else:
44
+ print_json(result)
45
+
46
+