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,502 @@
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
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Calling virtual-extensions.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ order: str = typer.Option(None, "--order", help="Order the list of virtual extensions in ascending or descend"),
15
+ extension: str = typer.Option(None, "--extension", help="Filter the list of virtual extensions by extension number."),
16
+ phone_number: str = typer.Option(None, "--phone-number", help="Filter the list of virtual extensions by phone number."),
17
+ name: str = typer.Option(None, "--name", help="Filter the list of virtual extensions by name. This can be e"),
18
+ location_name: str = typer.Option(None, "--location-name", help="Filter the list of virtual extensions by location name.(Only"),
19
+ location_id: str = typer.Option(None, "--location-id", help="Filter the list of virtual extensions by location ID."),
20
+ org_level_only: str = typer.Option(None, "--org-level-only", help="Filter the list of virtual extensions by organization level."),
21
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
22
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
23
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
24
+ debug: bool = typer.Option(False, "--debug"),
25
+ ):
26
+ """Read the List of Virtual Extensions."""
27
+ api = get_api(debug=debug)
28
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions"
29
+ params = {}
30
+ if order is not None:
31
+ params["order"] = order
32
+ if extension is not None:
33
+ params["extension"] = extension
34
+ if phone_number is not None:
35
+ params["phoneNumber"] = phone_number
36
+ if name is not None:
37
+ params["name"] = name
38
+ if location_name is not None:
39
+ params["locationName"] = location_name
40
+ if location_id is not None:
41
+ params["locationId"] = location_id
42
+ if org_level_only is not None:
43
+ params["orgLevelOnly"] = org_level_only
44
+ if limit > 0:
45
+ params["max"] = limit
46
+ if offset > 0:
47
+ params["start"] = offset
48
+ org_id = get_org_id()
49
+ if org_id is not None:
50
+ params["orgId"] = org_id
51
+ result = None
52
+ try:
53
+ result = api.session.rest_get(url, params=params)
54
+ except WebexError as e:
55
+ handle_rest_error(e)
56
+ result = result or []
57
+ items = result.get("virtualExtensions", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
58
+ if output == "json":
59
+ print_json(items)
60
+ else:
61
+ print_table(items, columns=[('ID', 'id'), ('Name', 'displayName'), ('Extension', 'extension'), ('Phone Number', 'phoneNumber')], limit=limit)
62
+
63
+
64
+
65
+ @app.command("create")
66
+ def create(
67
+ first_name: str = typer.Option(None, "--first-name", help="First name of the person at the virtual extension."),
68
+ last_name: str = typer.Option(None, "--last-name", help="Last name of the person at the virtual extension."),
69
+ display_name: str = typer.Option(None, "--display-name", help="(required) Display name of the person at the virtual extension."),
70
+ phone_number: str = typer.Option(None, "--phone-number", help="(required) Directory number of the virtual extension."),
71
+ extension: str = typer.Option(None, "--extension", help="(required) Extension of the virtual extension."),
72
+ location_id: str = typer.Option(None, "--location-id", help="ID of the location to which the virtual extension is assigne"),
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
+ """Create a Virtual Extension."""
78
+ api = get_api(debug=debug)
79
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions"
80
+ params = {}
81
+ org_id = get_org_id()
82
+ if org_id is not None:
83
+ params["orgId"] = org_id
84
+ if json_body:
85
+ body = json.loads(json_body)
86
+ else:
87
+ body = {}
88
+ if first_name is not None:
89
+ body["firstName"] = first_name
90
+ if last_name is not None:
91
+ body["lastName"] = last_name
92
+ if display_name is not None:
93
+ body["displayName"] = display_name
94
+ if phone_number is not None:
95
+ body["phoneNumber"] = phone_number
96
+ if extension is not None:
97
+ body["extension"] = extension
98
+ if location_id is not None:
99
+ body["locationId"] = location_id
100
+ _missing = [f for f in ['displayName', 'phoneNumber', 'extension'] if f not in body or body[f] is None]
101
+ if _missing:
102
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
103
+ raise typer.Exit(1)
104
+ try:
105
+ result = api.session.rest_post(url, json=body, params=params)
106
+ except WebexError as e:
107
+ handle_rest_error(e)
108
+ if output == "json":
109
+ print_json(result)
110
+ elif isinstance(result, dict) and "id" in result:
111
+ typer.echo(f"Created: {result['id']}")
112
+ elif not result or result == {}:
113
+ typer.echo("Created.")
114
+ else:
115
+ print_json(result)
116
+
117
+
118
+
119
+ @app.command("show")
120
+ def show(
121
+ extension_id: str = typer.Argument(help="extensionId"),
122
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
123
+ debug: bool = typer.Option(False, "--debug"),
124
+ ):
125
+ """Get a Virtual Extension."""
126
+ api = get_api(debug=debug)
127
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions/{extension_id}"
128
+ params = {}
129
+ org_id = get_org_id()
130
+ if org_id is not None:
131
+ params["orgId"] = org_id
132
+ try:
133
+ result = api.session.rest_get(url, params=params)
134
+ except WebexError as e:
135
+ handle_rest_error(e)
136
+ if output == "json":
137
+ print_json(result)
138
+ else:
139
+ if isinstance(result, dict):
140
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
141
+ elif isinstance(result, list):
142
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
143
+ else:
144
+ print_json(result)
145
+
146
+
147
+
148
+ @app.command("update")
149
+ def update(
150
+ extension_id: str = typer.Argument(help="extensionId"),
151
+ first_name: str = typer.Option(None, "--first-name", help="First name of the person at the virtual extension."),
152
+ last_name: str = typer.Option(None, "--last-name", help="Last name of the person at the virtual extension."),
153
+ display_name: str = typer.Option(None, "--display-name", help="Display name of the person at the virtual extension."),
154
+ phone_number: str = typer.Option(None, "--phone-number", help="Directory number of the virtual extension."),
155
+ extension: str = typer.Option(None, "--extension", help="Extension of the virtual extension."),
156
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
157
+ debug: bool = typer.Option(False, "--debug"),
158
+ ):
159
+ """Update a Virtual Extension."""
160
+ api = get_api(debug=debug)
161
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions/{extension_id}"
162
+ params = {}
163
+ org_id = get_org_id()
164
+ if org_id is not None:
165
+ params["orgId"] = org_id
166
+ if json_body:
167
+ body = json.loads(json_body)
168
+ else:
169
+ body = {}
170
+ if first_name is not None:
171
+ body["firstName"] = first_name
172
+ if last_name is not None:
173
+ body["lastName"] = last_name
174
+ if display_name is not None:
175
+ body["displayName"] = display_name
176
+ if phone_number is not None:
177
+ body["phoneNumber"] = phone_number
178
+ if extension is not None:
179
+ body["extension"] = extension
180
+ try:
181
+ result = api.session.rest_put(url, json=body, params=params)
182
+ except WebexError as e:
183
+ handle_rest_error(e)
184
+ typer.echo(f"Updated.")
185
+
186
+
187
+
188
+ @app.command("delete")
189
+ def delete(
190
+ extension_id: str = typer.Argument(help="extensionId"),
191
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
192
+ debug: bool = typer.Option(False, "--debug"),
193
+ ):
194
+ """Delete a Virtual Extension."""
195
+ if not force:
196
+ typer.confirm(f"Delete {extension_id}?", abort=True)
197
+ api = get_api(debug=debug)
198
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions/{extension_id}"
199
+ params = {}
200
+ org_id = get_org_id()
201
+ if org_id is not None:
202
+ params["orgId"] = org_id
203
+ try:
204
+ api.session.rest_delete(url, params=params)
205
+ except WebexError as e:
206
+ handle_rest_error(e)
207
+ typer.echo(f"Deleted: {extension_id}")
208
+
209
+
210
+
211
+ @app.command("show-settings")
212
+ def show_settings(
213
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
214
+ debug: bool = typer.Option(False, "--debug"),
215
+ ):
216
+ """Get Virtual extension settings."""
217
+ api = get_api(debug=debug)
218
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions/settings"
219
+ params = {}
220
+ org_id = get_org_id()
221
+ if org_id is not None:
222
+ params["orgId"] = org_id
223
+ try:
224
+ result = api.session.rest_get(url, params=params)
225
+ except WebexError as e:
226
+ handle_rest_error(e)
227
+ if output == "json":
228
+ print_json(result)
229
+ else:
230
+ if isinstance(result, dict):
231
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
232
+ elif isinstance(result, list):
233
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
234
+ else:
235
+ print_json(result)
236
+
237
+
238
+
239
+ @app.command("update-settings")
240
+ def update_settings(
241
+ mode: str = typer.Option(None, "--mode", help="Choices: STANDARD"),
242
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
243
+ debug: bool = typer.Option(False, "--debug"),
244
+ ):
245
+ """Modify Virtual Extension Settings."""
246
+ api = get_api(debug=debug)
247
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions/settings"
248
+ params = {}
249
+ org_id = get_org_id()
250
+ if org_id is not None:
251
+ params["orgId"] = org_id
252
+ if json_body:
253
+ body = json.loads(json_body)
254
+ else:
255
+ body = {}
256
+ if mode is not None:
257
+ body["mode"] = mode
258
+ try:
259
+ result = api.session.rest_put(url, json=body, params=params)
260
+ except WebexError as e:
261
+ handle_rest_error(e)
262
+ typer.echo(f"Updated.")
263
+
264
+
265
+
266
+ @app.command("validate-an-external")
267
+ def validate_an_external(
268
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
269
+ debug: bool = typer.Option(False, "--debug"),
270
+ ):
271
+ """Validate an external phone number\n\nExample --json-body:\n '{"phoneNumbers":["..."]}'."""
272
+ api = get_api(debug=debug)
273
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensions/actions/validateNumbers/invoke"
274
+ params = {}
275
+ org_id = get_org_id()
276
+ if org_id is not None:
277
+ params["orgId"] = org_id
278
+ if json_body:
279
+ body = json.loads(json_body)
280
+ else:
281
+ body = {}
282
+ try:
283
+ result = api.session.rest_post(url, json=body, params=params)
284
+ except WebexError as e:
285
+ handle_rest_error(e)
286
+ print_json(result)
287
+
288
+
289
+
290
+ @app.command("list-virtual-extension-ranges")
291
+ def list_virtual_extension_ranges(
292
+ order: str = typer.Option(None, "--order", help="Sort the list of virtual extension ranges by name or prefix,"),
293
+ name: str = typer.Option(None, "--name", help="Filter the list of virtual extension ranges by name."),
294
+ prefix: str = typer.Option(None, "--prefix", help="Filter the list of virtual extension ranges by prefix."),
295
+ location_id: str = typer.Option(None, "--location-id", help="Filter the list of virtual extension ranges by location ID."),
296
+ org_level_only: str = typer.Option(None, "--org-level-only", help="Filter the list of virtual extension ranges by organization"),
297
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
298
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
299
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
300
+ debug: bool = typer.Option(False, "--debug"),
301
+ ):
302
+ """Get a list of a Virtual Extension Range."""
303
+ api = get_api(debug=debug)
304
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensionRanges"
305
+ params = {}
306
+ if order is not None:
307
+ params["order"] = order
308
+ if name is not None:
309
+ params["name"] = name
310
+ if prefix is not None:
311
+ params["prefix"] = prefix
312
+ if location_id is not None:
313
+ params["locationId"] = location_id
314
+ if org_level_only is not None:
315
+ params["orgLevelOnly"] = org_level_only
316
+ if limit > 0:
317
+ params["max"] = limit
318
+ if offset > 0:
319
+ params["start"] = offset
320
+ org_id = get_org_id()
321
+ if org_id is not None:
322
+ params["orgId"] = org_id
323
+ result = None
324
+ try:
325
+ result = api.session.rest_get(url, params=params)
326
+ except WebexError as e:
327
+ handle_rest_error(e)
328
+ result = result or []
329
+ items = result.get("virtualExtensionRanges", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
330
+ if output == "json":
331
+ print_json(items)
332
+ else:
333
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
334
+
335
+
336
+
337
+ @app.command("create-virtual-extension-ranges")
338
+ def create_virtual_extension_ranges(
339
+ name: str = typer.Option(None, "--name", help="(required) Name of the virtual extension range. This is a unique name f"),
340
+ prefix: str = typer.Option(None, "--prefix", help="(required) Prefix used for a virtual extension range. Prefix works in S"),
341
+ location_id: str = typer.Option(None, "--location-id", help="ID of the location to which the virtual extension range is a"),
342
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
343
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
344
+ debug: bool = typer.Option(False, "--debug"),
345
+ ):
346
+ """Create a Virtual Extension Range\n\nExample --json-body:\n '{"name":"...","prefix":"...","patterns":["..."],"locationId":"..."}'."""
347
+ api = get_api(debug=debug)
348
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensionRanges"
349
+ params = {}
350
+ org_id = get_org_id()
351
+ if org_id is not None:
352
+ params["orgId"] = org_id
353
+ if json_body:
354
+ body = json.loads(json_body)
355
+ else:
356
+ body = {}
357
+ if name is not None:
358
+ body["name"] = name
359
+ if prefix is not None:
360
+ body["prefix"] = prefix
361
+ if location_id is not None:
362
+ body["locationId"] = location_id
363
+ _missing = [f for f in ['name', 'prefix'] if f not in body or body[f] is None]
364
+ if _missing:
365
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
366
+ raise typer.Exit(1)
367
+ try:
368
+ result = api.session.rest_post(url, json=body, params=params)
369
+ except WebexError as e:
370
+ handle_rest_error(e)
371
+ if output == "json":
372
+ print_json(result)
373
+ elif isinstance(result, dict) and "id" in result:
374
+ typer.echo(f"Created: {result['id']}")
375
+ elif not result or result == {}:
376
+ typer.echo("Created.")
377
+ else:
378
+ print_json(result)
379
+
380
+
381
+
382
+ @app.command("show-virtual-extension-ranges")
383
+ def show_virtual_extension_ranges(
384
+ extension_range_id: str = typer.Argument(help="extensionRangeId"),
385
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
386
+ debug: bool = typer.Option(False, "--debug"),
387
+ ):
388
+ """Get details of a Virtual Extension Range."""
389
+ api = get_api(debug=debug)
390
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensionRanges/{extension_range_id}"
391
+ params = {}
392
+ org_id = get_org_id()
393
+ if org_id is not None:
394
+ params["orgId"] = org_id
395
+ try:
396
+ result = api.session.rest_get(url, params=params)
397
+ except WebexError as e:
398
+ handle_rest_error(e)
399
+ if output == "json":
400
+ print_json(result)
401
+ else:
402
+ if isinstance(result, dict):
403
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
404
+ elif isinstance(result, list):
405
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
406
+ else:
407
+ print_json(result)
408
+
409
+
410
+
411
+ @app.command("delete-virtual-extension-ranges")
412
+ def delete_virtual_extension_ranges(
413
+ extension_range_id: str = typer.Argument(help="extensionRangeId"),
414
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
415
+ debug: bool = typer.Option(False, "--debug"),
416
+ ):
417
+ """Delete a Virtual Extension Range."""
418
+ if not force:
419
+ typer.confirm(f"Delete {extension_range_id}?", abort=True)
420
+ api = get_api(debug=debug)
421
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensionRanges/{extension_range_id}"
422
+ params = {}
423
+ org_id = get_org_id()
424
+ if org_id is not None:
425
+ params["orgId"] = org_id
426
+ try:
427
+ api.session.rest_delete(url, params=params)
428
+ except WebexError as e:
429
+ handle_rest_error(e)
430
+ typer.echo(f"Deleted: {extension_range_id}")
431
+
432
+
433
+
434
+ @app.command("update-virtual-extension-ranges")
435
+ def update_virtual_extension_ranges(
436
+ extension_range_id: str = typer.Argument(help="extensionRangeId"),
437
+ name: str = typer.Option(None, "--name", help="Name of the virtual extension range. This is a unique name f"),
438
+ prefix: str = typer.Option(None, "--prefix", help="Prefix used for a virtual extension range."),
439
+ action: str = typer.Option(None, "--action", help="Choices: ADD, REMOVE, REPLACE"),
440
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
441
+ debug: bool = typer.Option(False, "--debug"),
442
+ ):
443
+ """Modify Virtual Extension Range\n\nExample --json-body:\n '{"name":"...","prefix":"...","patterns":["..."],"action":"ADD"}'."""
444
+ api = get_api(debug=debug)
445
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensionRanges/{extension_range_id}/"
446
+ params = {}
447
+ org_id = get_org_id()
448
+ if org_id is not None:
449
+ params["orgId"] = org_id
450
+ if json_body:
451
+ body = json.loads(json_body)
452
+ else:
453
+ body = {}
454
+ if name is not None:
455
+ body["name"] = name
456
+ if prefix is not None:
457
+ body["prefix"] = prefix
458
+ if action is not None:
459
+ body["action"] = action
460
+ try:
461
+ result = api.session.rest_put(url, json=body, params=params)
462
+ except WebexError as e:
463
+ handle_rest_error(e)
464
+ typer.echo(f"Updated.")
465
+
466
+
467
+
468
+ @app.command("validate-the-prefix")
469
+ def validate_the_prefix(
470
+ location_id: str = typer.Option(None, "--location-id", help="ID of the location to which the virtual extension range is a"),
471
+ name: str = typer.Option(None, "--name", help="Name of the virtual extension range. This is a unique name f"),
472
+ prefix: str = typer.Option(None, "--prefix", help="Prefix used for a virtual extension range."),
473
+ range_id: str = typer.Option(None, "--range-id", help="ID of the virtual extension range. This is mandatory when va"),
474
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
475
+ debug: bool = typer.Option(False, "--debug"),
476
+ ):
477
+ """Validate the prefix and extension pattern for a Virtual Extension Range\n\nExample --json-body:\n '{"locationId":"...","name":"...","prefix":"...","patterns":["..."],"rangeId":"..."}'."""
478
+ api = get_api(debug=debug)
479
+ url = f"https://webexapis.com/v1/telephony/config/virtualExtensionRanges/actions/validate/invoke"
480
+ params = {}
481
+ org_id = get_org_id()
482
+ if org_id is not None:
483
+ params["orgId"] = org_id
484
+ if json_body:
485
+ body = json.loads(json_body)
486
+ else:
487
+ body = {}
488
+ if location_id is not None:
489
+ body["locationId"] = location_id
490
+ if name is not None:
491
+ body["name"] = name
492
+ if prefix is not None:
493
+ body["prefix"] = prefix
494
+ if range_id is not None:
495
+ body["rangeId"] = range_id
496
+ try:
497
+ result = api.session.rest_post(url, json=body, params=params)
498
+ except WebexError as e:
499
+ handle_rest_error(e)
500
+ print_json(result)
501
+
502
+