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,707 @@
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 call-recording.")
10
+
11
+
12
+ @app.command("show")
13
+ def show(
14
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
15
+ debug: bool = typer.Option(False, "--debug"),
16
+ ):
17
+ """Get Call Recording Settings."""
18
+ api = get_api(debug=debug)
19
+ url = f"https://webexapis.com/v1/telephony/config/callRecording"
20
+ params = {}
21
+ org_id = get_org_id()
22
+ if org_id is not None:
23
+ params["orgId"] = org_id
24
+ try:
25
+ result = api.session.rest_get(url, params=params)
26
+ except WebexError as e:
27
+ handle_rest_error(e)
28
+ if output == "json":
29
+ print_json(result)
30
+ else:
31
+ if isinstance(result, dict):
32
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
33
+ elif isinstance(result, list):
34
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
35
+ else:
36
+ print_json(result)
37
+
38
+
39
+
40
+ @app.command("update")
41
+ def update(
42
+ enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Whether or not the call recording is enabled."),
43
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
44
+ debug: bool = typer.Option(False, "--debug"),
45
+ ):
46
+ """Update Call Recording Settings."""
47
+ api = get_api(debug=debug)
48
+ url = f"https://webexapis.com/v1/telephony/config/callRecording"
49
+ params = {}
50
+ org_id = get_org_id()
51
+ if org_id is not None:
52
+ params["orgId"] = org_id
53
+ if json_body:
54
+ body = json.loads(json_body)
55
+ else:
56
+ body = {}
57
+ if enabled is not None:
58
+ body["enabled"] = enabled
59
+ try:
60
+ result = api.session.rest_put(url, json=body, params=params)
61
+ except WebexError as e:
62
+ handle_rest_error(e)
63
+ typer.echo(f"Updated.")
64
+
65
+
66
+
67
+ @app.command("show-terms-of-service")
68
+ def show_terms_of_service(
69
+ vendor_id: str = typer.Argument(help="vendorId"),
70
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
71
+ debug: bool = typer.Option(False, "--debug"),
72
+ ):
73
+ """Get Call Recording Terms Of Service Settings."""
74
+ api = get_api(debug=debug)
75
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/vendors/{vendor_id}/termsOfService"
76
+ params = {}
77
+ org_id = get_org_id()
78
+ if org_id is not None:
79
+ params["orgId"] = org_id
80
+ try:
81
+ result = api.session.rest_get(url, params=params)
82
+ except WebexError as e:
83
+ handle_rest_error(e)
84
+ if output == "json":
85
+ print_json(result)
86
+ else:
87
+ if isinstance(result, dict):
88
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
89
+ elif isinstance(result, list):
90
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
91
+ else:
92
+ print_json(result)
93
+
94
+
95
+
96
+ @app.command("update-terms-of-service")
97
+ def update_terms_of_service(
98
+ vendor_id: str = typer.Argument(help="vendorId"),
99
+ terms_of_service_enabled: bool = typer.Option(None, "--terms-of-service-enabled/--no-terms-of-service-enabled", help="Whether or not the call recording terms of service are enabl"),
100
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
101
+ debug: bool = typer.Option(False, "--debug"),
102
+ ):
103
+ """Update Call Recording Terms Of Service Settings."""
104
+ api = get_api(debug=debug)
105
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/vendors/{vendor_id}/termsOfService"
106
+ params = {}
107
+ org_id = get_org_id()
108
+ if org_id is not None:
109
+ params["orgId"] = org_id
110
+ if json_body:
111
+ body = json.loads(json_body)
112
+ else:
113
+ body = {}
114
+ if terms_of_service_enabled is not None:
115
+ body["termsOfServiceEnabled"] = terms_of_service_enabled
116
+ try:
117
+ result = api.session.rest_put(url, json=body, params=params)
118
+ except WebexError as e:
119
+ handle_rest_error(e)
120
+ typer.echo(f"Updated.")
121
+
122
+
123
+
124
+ @app.command("show-compliance-announcement-call-recording")
125
+ def show_compliance_announcement_call_recording(
126
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
127
+ debug: bool = typer.Option(False, "--debug"),
128
+ ):
129
+ """Get details for the organization Compliance Announcement Setting."""
130
+ api = get_api(debug=debug)
131
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/complianceAnnouncement"
132
+ params = {}
133
+ org_id = get_org_id()
134
+ if org_id is not None:
135
+ params["orgId"] = org_id
136
+ try:
137
+ result = api.session.rest_get(url, params=params)
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-compliance-announcement-call-recording")
153
+ def update_compliance_announcement_call_recording(
154
+ inbound_pstn_calls_enabled: bool = typer.Option(None, "--inbound-pstn-calls-enabled/--no-inbound-pstn-calls-enabled", help="Flag to indicate whether the call recording START/STOP annou"),
155
+ outbound_pstn_calls_enabled: bool = typer.Option(None, "--outbound-pstn-calls-enabled/--no-outbound-pstn-calls-enabled", help="Flag to indicate whether the call recording START/STOP annou"),
156
+ outbound_pstn_calls_delay_enabled: bool = typer.Option(None, "--outbound-pstn-calls-delay-enabled/--no-outbound-pstn-calls-delay-enabled", help="Flag to indicate whether compliance announcement is played a"),
157
+ delay_in_seconds: str = typer.Option(None, "--delay-in-seconds", help="Number of seconds to wait before playing the compliance anno"),
158
+ use_custom_announcement_enabled: bool = typer.Option(None, "--use-custom-announcement-enabled/--no-use-custom-announcement-enabled", help="Flag to indicate whether to use the custom compliance announ"),
159
+ audio_announcement_file_id: str = typer.Option(None, "--audio-announcement-file-id", help="Unique identifier for the custom audio announcement file."),
160
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
161
+ debug: bool = typer.Option(False, "--debug"),
162
+ ):
163
+ """Update the organization Compliance Announcement."""
164
+ api = get_api(debug=debug)
165
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/complianceAnnouncement"
166
+ params = {}
167
+ org_id = get_org_id()
168
+ if org_id is not None:
169
+ params["orgId"] = org_id
170
+ if json_body:
171
+ body = json.loads(json_body)
172
+ else:
173
+ body = {}
174
+ if inbound_pstn_calls_enabled is not None:
175
+ body["inboundPSTNCallsEnabled"] = inbound_pstn_calls_enabled
176
+ if outbound_pstn_calls_enabled is not None:
177
+ body["outboundPSTNCallsEnabled"] = outbound_pstn_calls_enabled
178
+ if outbound_pstn_calls_delay_enabled is not None:
179
+ body["outboundPSTNCallsDelayEnabled"] = outbound_pstn_calls_delay_enabled
180
+ if delay_in_seconds is not None:
181
+ body["delayInSeconds"] = delay_in_seconds
182
+ if use_custom_announcement_enabled is not None:
183
+ body["useCustomAnnouncementEnabled"] = use_custom_announcement_enabled
184
+ if audio_announcement_file_id is not None:
185
+ body["audioAnnouncementFileId"] = audio_announcement_file_id
186
+ try:
187
+ result = api.session.rest_put(url, json=body, params=params)
188
+ except WebexError as e:
189
+ handle_rest_error(e)
190
+ typer.echo(f"Updated.")
191
+
192
+
193
+
194
+ @app.command("show-compliance-announcement-call-recording-1")
195
+ def show_compliance_announcement_call_recording_1(
196
+ location_id: str = typer.Argument(help="locationId"),
197
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
198
+ debug: bool = typer.Option(False, "--debug"),
199
+ ):
200
+ """Get details for the Location Compliance Announcement Setting."""
201
+ api = get_api(debug=debug)
202
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/complianceAnnouncement"
203
+ params = {}
204
+ org_id = get_org_id()
205
+ if org_id is not None:
206
+ params["orgId"] = org_id
207
+ try:
208
+ result = api.session.rest_get(url, params=params)
209
+ except WebexError as e:
210
+ handle_rest_error(e)
211
+ if output == "json":
212
+ print_json(result)
213
+ else:
214
+ if isinstance(result, dict):
215
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
216
+ elif isinstance(result, list):
217
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
218
+ else:
219
+ print_json(result)
220
+
221
+
222
+
223
+ @app.command("update-compliance-announcement-call-recording-1")
224
+ def update_compliance_announcement_call_recording_1(
225
+ location_id: str = typer.Argument(help="locationId"),
226
+ inbound_pstn_calls_enabled: bool = typer.Option(None, "--inbound-pstn-calls-enabled/--no-inbound-pstn-calls-enabled", help="Flag to indicate whether the Call Recording START/STOP annou"),
227
+ use_org_settings_enabled: bool = typer.Option(None, "--use-org-settings-enabled/--no-use-org-settings-enabled", help="Flag to indicate whether to use the customer level complianc"),
228
+ outbound_pstn_calls_enabled: bool = typer.Option(None, "--outbound-pstn-calls-enabled/--no-outbound-pstn-calls-enabled", help="Flag to indicate whether the Call Recording START/STOP annou"),
229
+ outbound_pstn_calls_delay_enabled: bool = typer.Option(None, "--outbound-pstn-calls-delay-enabled/--no-outbound-pstn-calls-delay-enabled", help="Flag to indicate whether compliance announcement is played a"),
230
+ delay_in_seconds: str = typer.Option(None, "--delay-in-seconds", help="Number of seconds to wait before playing the compliance anno"),
231
+ use_org_level_announcement_enabled: bool = typer.Option(None, "--use-org-level-announcement-enabled/--no-use-org-level-announcement-enabled", help="Flag to indicate whether to use the organization level custo"),
232
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
233
+ debug: bool = typer.Option(False, "--debug"),
234
+ ):
235
+ """Update the Location Compliance Announcement\n\nExample --json-body:\n '{"inboundPSTNCallsEnabled":true,"useOrgSettingsEnabled":true,"outboundPSTNCallsEnabled":true,"outboundPSTNCallsDelayEnabled":true,"delayInSeconds":0,"useOrgLevelAnnouncementEnabled":true,"customComplianceAnnouncement":{"type":"CUSTOM","audioAnnouncementFileId":"..."}}'."""
236
+ api = get_api(debug=debug)
237
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/complianceAnnouncement"
238
+ params = {}
239
+ org_id = get_org_id()
240
+ if org_id is not None:
241
+ params["orgId"] = org_id
242
+ if json_body:
243
+ body = json.loads(json_body)
244
+ else:
245
+ body = {}
246
+ if inbound_pstn_calls_enabled is not None:
247
+ body["inboundPSTNCallsEnabled"] = inbound_pstn_calls_enabled
248
+ if use_org_settings_enabled is not None:
249
+ body["useOrgSettingsEnabled"] = use_org_settings_enabled
250
+ if outbound_pstn_calls_enabled is not None:
251
+ body["outboundPSTNCallsEnabled"] = outbound_pstn_calls_enabled
252
+ if outbound_pstn_calls_delay_enabled is not None:
253
+ body["outboundPSTNCallsDelayEnabled"] = outbound_pstn_calls_delay_enabled
254
+ if delay_in_seconds is not None:
255
+ body["delayInSeconds"] = delay_in_seconds
256
+ if use_org_level_announcement_enabled is not None:
257
+ body["useOrgLevelAnnouncementEnabled"] = use_org_level_announcement_enabled
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("list")
267
+ def cmd_list(
268
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
269
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
270
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
271
+ debug: bool = typer.Option(False, "--debug"),
272
+ ):
273
+ """Get Call Recording Regions."""
274
+ api = get_api(debug=debug)
275
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/regions"
276
+ params = {}
277
+ if limit > 0:
278
+ params["max"] = limit
279
+ if offset > 0:
280
+ params["start"] = offset
281
+ org_id = get_org_id()
282
+ if org_id is not None:
283
+ params["orgId"] = org_id
284
+ result = None
285
+ try:
286
+ result = api.session.rest_get(url, params=params)
287
+ except WebexError as e:
288
+ handle_rest_error(e)
289
+ result = result or []
290
+ items = result.get("regions", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
291
+ if output == "json":
292
+ print_json(items)
293
+ else:
294
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
295
+
296
+
297
+
298
+ @app.command("list-vendor-users-call-recording")
299
+ def list_vendor_users_call_recording(
300
+ standard_user_only: str = typer.Option(None, "--standard-user-only", help="If true, results only include Webex Calling standard users."),
301
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
302
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
303
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
304
+ debug: bool = typer.Option(False, "--debug"),
305
+ ):
306
+ """Get Call Recording Vendor Users."""
307
+ api = get_api(debug=debug)
308
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/vendorUsers"
309
+ params = {}
310
+ if standard_user_only is not None:
311
+ params["standardUserOnly"] = standard_user_only
312
+ if limit > 0:
313
+ params["max"] = limit
314
+ if offset > 0:
315
+ params["start"] = offset
316
+ org_id = get_org_id()
317
+ if org_id is not None:
318
+ params["orgId"] = org_id
319
+ result = None
320
+ try:
321
+ result = api.session.rest_get(url, params=params)
322
+ except WebexError as e:
323
+ handle_rest_error(e)
324
+ result = result or []
325
+ items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
326
+ if output == "json":
327
+ print_json(items)
328
+ else:
329
+ print_table(items, columns=[('ID', 'id'), ('First Name', 'firstName'), ('Last Name', 'lastName')], limit=limit)
330
+
331
+
332
+
333
+ @app.command("update-vendor-call-recording")
334
+ def update_vendor_call_recording(
335
+ location_id: str = typer.Argument(help="locationId"),
336
+ id_param: str = typer.Option(None, "--id", help="Unique identifier of the call recording vendor."),
337
+ org_default_enabled: bool = typer.Option(None, "--org-default-enabled/--no-org-default-enabled", help="Vendor is enabled by default."),
338
+ storage_region: str = typer.Option(None, "--storage-region", help="Regions where call recordings are stored."),
339
+ org_storage_region_enabled: bool = typer.Option(None, "--org-storage-region-enabled/--no-org-storage-region-enabled", help="Region-based call recording storage is enabled."),
340
+ failure_behavior: str = typer.Option(None, "--failure-behavior", help="Type of failure behavior."),
341
+ org_failure_behavior_enabled: bool = typer.Option(None, "--org-failure-behavior-enabled/--no-org-failure-behavior-enabled", help="Failure behavior is enabled."),
342
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
343
+ debug: bool = typer.Option(False, "--debug"),
344
+ ):
345
+ """Set Call Recording Vendor for a Location."""
346
+ api = get_api(debug=debug)
347
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/vendor"
348
+ params = {}
349
+ org_id = get_org_id()
350
+ if org_id is not None:
351
+ params["orgId"] = org_id
352
+ if json_body:
353
+ body = json.loads(json_body)
354
+ else:
355
+ body = {}
356
+ if id_param is not None:
357
+ body["id"] = id_param
358
+ if org_default_enabled is not None:
359
+ body["orgDefaultEnabled"] = org_default_enabled
360
+ if storage_region is not None:
361
+ body["storageRegion"] = storage_region
362
+ if org_storage_region_enabled is not None:
363
+ body["orgStorageRegionEnabled"] = org_storage_region_enabled
364
+ if failure_behavior is not None:
365
+ body["failureBehavior"] = failure_behavior
366
+ if org_failure_behavior_enabled is not None:
367
+ body["orgFailureBehaviorEnabled"] = org_failure_behavior_enabled
368
+ try:
369
+ result = api.session.rest_put(url, json=body, params=params)
370
+ except WebexError as e:
371
+ handle_rest_error(e)
372
+ typer.echo(f"Updated.")
373
+
374
+
375
+
376
+ @app.command("list-vendors")
377
+ def list_vendors(
378
+ location_id: str = typer.Argument(help="locationId"),
379
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
380
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
381
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
382
+ debug: bool = typer.Option(False, "--debug"),
383
+ ):
384
+ """Get Location Call Recording Vendors."""
385
+ api = get_api(debug=debug)
386
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/vendors"
387
+ params = {}
388
+ if limit > 0:
389
+ params["max"] = limit
390
+ if offset > 0:
391
+ params["start"] = offset
392
+ org_id = get_org_id()
393
+ if org_id is not None:
394
+ params["orgId"] = org_id
395
+ result = None
396
+ try:
397
+ result = api.session.rest_get(url, params=params)
398
+ except WebexError as e:
399
+ handle_rest_error(e)
400
+ result = result or []
401
+ items = result.get("vendors", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
402
+ if output == "json":
403
+ print_json(items)
404
+ else:
405
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
406
+
407
+
408
+
409
+ @app.command("list-vendor-users-call-recording-1")
410
+ def list_vendor_users_call_recording_1(
411
+ location_id: str = typer.Argument(help="locationId"),
412
+ standard_user_only: str = typer.Option(None, "--standard-user-only", help="If true, results only include Webex Calling standard users."),
413
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
414
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
415
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
416
+ debug: bool = typer.Option(False, "--debug"),
417
+ ):
418
+ """Get Call Recording Vendor Users for a Location."""
419
+ api = get_api(debug=debug)
420
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/vendorUsers"
421
+ params = {}
422
+ if standard_user_only is not None:
423
+ params["standardUserOnly"] = standard_user_only
424
+ if limit > 0:
425
+ params["max"] = limit
426
+ if offset > 0:
427
+ params["start"] = offset
428
+ org_id = get_org_id()
429
+ if org_id is not None:
430
+ params["orgId"] = org_id
431
+ result = None
432
+ try:
433
+ result = api.session.rest_get(url, params=params)
434
+ except WebexError as e:
435
+ handle_rest_error(e)
436
+ result = result or []
437
+ items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
438
+ if output == "json":
439
+ print_json(items)
440
+ else:
441
+ print_table(items, columns=[('ID', 'id'), ('First Name', 'firstName'), ('Last Name', 'lastName')], limit=limit)
442
+
443
+
444
+
445
+ @app.command("list-call-recording")
446
+ def list_call_recording(
447
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
448
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
449
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
450
+ debug: bool = typer.Option(False, "--debug"),
451
+ ):
452
+ """List Call Recording Jobs."""
453
+ api = get_api(debug=debug)
454
+ url = f"https://webexapis.com/v1/telephony/config/jobs/callRecording"
455
+ params = {}
456
+ if limit > 0:
457
+ params["max"] = limit
458
+ if offset > 0:
459
+ params["start"] = offset
460
+ org_id = get_org_id()
461
+ if org_id is not None:
462
+ params["orgId"] = org_id
463
+ result = None
464
+ try:
465
+ result = api.session.rest_get(url, params=params)
466
+ except WebexError as e:
467
+ handle_rest_error(e)
468
+ result = result or []
469
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
470
+ if output == "json":
471
+ print_json(items)
472
+ else:
473
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
474
+
475
+
476
+
477
+ @app.command("show-call-recording")
478
+ def show_call_recording(
479
+ job_id: str = typer.Argument(help="jobId"),
480
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
481
+ debug: bool = typer.Option(False, "--debug"),
482
+ ):
483
+ """Get the Job Status of a Call Recording Job."""
484
+ api = get_api(debug=debug)
485
+ url = f"https://webexapis.com/v1/telephony/config/jobs/callRecording/{job_id}"
486
+ params = {}
487
+ org_id = get_org_id()
488
+ if org_id is not None:
489
+ params["orgId"] = org_id
490
+ try:
491
+ result = api.session.rest_get(url, params=params)
492
+ except WebexError as e:
493
+ handle_rest_error(e)
494
+ if output == "json":
495
+ print_json(result)
496
+ else:
497
+ if isinstance(result, dict):
498
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
499
+ elif isinstance(result, list):
500
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
501
+ else:
502
+ print_json(result)
503
+
504
+
505
+
506
+ @app.command("list-errors")
507
+ def list_errors(
508
+ job_id: str = typer.Argument(help="jobId"),
509
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
510
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
511
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
512
+ debug: bool = typer.Option(False, "--debug"),
513
+ ):
514
+ """Get Job Errors for a Call Recording Job."""
515
+ api = get_api(debug=debug)
516
+ url = f"https://webexapis.com/v1/telephony/config/jobs/callRecording/{job_id}/errors"
517
+ params = {}
518
+ if limit > 0:
519
+ params["max"] = limit
520
+ if offset > 0:
521
+ params["start"] = offset
522
+ org_id = get_org_id()
523
+ if org_id is not None:
524
+ params["orgId"] = org_id
525
+ result = None
526
+ try:
527
+ result = api.session.rest_get(url, params=params)
528
+ except WebexError as e:
529
+ handle_rest_error(e)
530
+ result = result or []
531
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
532
+ if output == "json":
533
+ print_json(items)
534
+ else:
535
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
536
+
537
+
538
+
539
+ @app.command("show-vendors")
540
+ def show_vendors(
541
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
542
+ debug: bool = typer.Option(False, "--debug"),
543
+ ):
544
+ """Get Organization Call Recording Vendors."""
545
+ api = get_api(debug=debug)
546
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/vendors"
547
+ params = {}
548
+ org_id = get_org_id()
549
+ if org_id is not None:
550
+ params["orgId"] = org_id
551
+ try:
552
+ result = api.session.rest_get(url, params=params)
553
+ except WebexError as e:
554
+ handle_rest_error(e)
555
+ if output == "json":
556
+ print_json(result)
557
+ else:
558
+ if isinstance(result, dict):
559
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
560
+ elif isinstance(result, list):
561
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
562
+ else:
563
+ print_json(result)
564
+
565
+
566
+
567
+ @app.command("update-vendor-call-recording-1")
568
+ def update_vendor_call_recording_1(
569
+ vendor_id: str = typer.Option(None, "--vendor-id", help="Unique identifier of the vendor."),
570
+ storage_region: str = typer.Option(None, "--storage-region", help="Call recording storage region. Only applicable for Webex as"),
571
+ failure_behavior: str = typer.Option(None, "--failure-behavior", help="Call recording failure behavior."),
572
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
573
+ debug: bool = typer.Option(False, "--debug"),
574
+ ):
575
+ """Set Organization Call Recording Vendor."""
576
+ api = get_api(debug=debug)
577
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/vendor"
578
+ params = {}
579
+ org_id = get_org_id()
580
+ if org_id is not None:
581
+ params["orgId"] = org_id
582
+ if json_body:
583
+ body = json.loads(json_body)
584
+ else:
585
+ body = {}
586
+ if vendor_id is not None:
587
+ body["vendorId"] = vendor_id
588
+ if storage_region is not None:
589
+ body["storageRegion"] = storage_region
590
+ if failure_behavior is not None:
591
+ body["failureBehavior"] = failure_behavior
592
+ try:
593
+ result = api.session.rest_put(url, json=body, params=params)
594
+ except WebexError as e:
595
+ handle_rest_error(e)
596
+ typer.echo(f"Updated.")
597
+
598
+
599
+
600
+ @app.command("show-announcements-call-recording")
601
+ def show_announcements_call_recording(
602
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
603
+ debug: bool = typer.Option(False, "--debug"),
604
+ ):
605
+ """Get Organization Call Recording Announcement Settings."""
606
+ api = get_api(debug=debug)
607
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/announcements"
608
+ params = {}
609
+ org_id = get_org_id()
610
+ if org_id is not None:
611
+ params["orgId"] = org_id
612
+ try:
613
+ result = api.session.rest_get(url, params=params)
614
+ except WebexError as e:
615
+ handle_rest_error(e)
616
+ if output == "json":
617
+ print_json(result)
618
+ else:
619
+ if isinstance(result, dict):
620
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
621
+ elif isinstance(result, list):
622
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
623
+ else:
624
+ print_json(result)
625
+
626
+
627
+
628
+ @app.command("update-announcements-call-recording")
629
+ def update_announcements_call_recording(
630
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
631
+ debug: bool = typer.Option(False, "--debug"),
632
+ ):
633
+ """Update Organization Call Recording Announcement Settings\n\nExample --json-body:\n '{"start":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"stop":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"pause":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"resume":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"failureEndWithCall":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"failureProceedWithCall":{"type":"CUSTOM","audioAnnouncementFileId":"..."}}'."""
634
+ api = get_api(debug=debug)
635
+ url = f"https://webexapis.com/v1/telephony/config/callRecording/announcements"
636
+ params = {}
637
+ org_id = get_org_id()
638
+ if org_id is not None:
639
+ params["orgId"] = org_id
640
+ if json_body:
641
+ body = json.loads(json_body)
642
+ else:
643
+ body = {}
644
+ try:
645
+ result = api.session.rest_put(url, json=body, params=params)
646
+ except WebexError as e:
647
+ handle_rest_error(e)
648
+ typer.echo(f"Updated.")
649
+
650
+
651
+
652
+ @app.command("show-announcements-call-recording-1")
653
+ def show_announcements_call_recording_1(
654
+ location_id: str = typer.Argument(help="locationId"),
655
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
656
+ debug: bool = typer.Option(False, "--debug"),
657
+ ):
658
+ """Get Location Call Recording Announcement Settings."""
659
+ api = get_api(debug=debug)
660
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/announcements"
661
+ params = {}
662
+ org_id = get_org_id()
663
+ if org_id is not None:
664
+ params["orgId"] = org_id
665
+ try:
666
+ result = api.session.rest_get(url, params=params)
667
+ except WebexError as e:
668
+ handle_rest_error(e)
669
+ if output == "json":
670
+ print_json(result)
671
+ else:
672
+ if isinstance(result, dict):
673
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
674
+ elif isinstance(result, list):
675
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
676
+ else:
677
+ print_json(result)
678
+
679
+
680
+
681
+ @app.command("update-announcements-call-recording-1")
682
+ def update_announcements_call_recording_1(
683
+ location_id: str = typer.Argument(help="locationId"),
684
+ use_org_level_announcement_enabled: bool = typer.Option(None, "--use-org-level-announcement-enabled/--no-use-org-level-announcement-enabled", help="Flag to indicate whether to use the organization level call"),
685
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
686
+ debug: bool = typer.Option(False, "--debug"),
687
+ ):
688
+ """Update Location Call Recording Announcement Settings\n\nExample --json-body:\n '{"useOrgLevelAnnouncementEnabled":true,"start":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"stop":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"pause":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"resume":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"failureEndWithCall":{"type":"CUSTOM","audioAnnouncementFileId":"..."},"failureProceedWithCall":{"type":"CUSTOM","audioAnnouncementFileId":"..."}}'."""
689
+ api = get_api(debug=debug)
690
+ url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRecording/announcements"
691
+ params = {}
692
+ org_id = get_org_id()
693
+ if org_id is not None:
694
+ params["orgId"] = org_id
695
+ if json_body:
696
+ body = json.loads(json_body)
697
+ else:
698
+ body = {}
699
+ if use_org_level_announcement_enabled is not None:
700
+ body["useOrgLevelAnnouncementEnabled"] = use_org_level_announcement_enabled
701
+ try:
702
+ result = api.session.rest_put(url, json=body, params=params)
703
+ except WebexError as e:
704
+ handle_rest_error(e)
705
+ typer.echo(f"Updated.")
706
+
707
+