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,216 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Calling partner-tags.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ type_param: str = typer.Option(..., "--type", help="List tags associated with an organization."),
15
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
16
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
17
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
18
+ debug: bool = typer.Option(False, "--debug"),
19
+ ):
20
+ """Retrieve all customer tags."""
21
+ api = get_api(debug=debug)
22
+ url = f"https://webexapis.com/v1/partner/tags"
23
+ params = {}
24
+ if type_param is not None:
25
+ params["type"] = type_param
26
+ if limit > 0:
27
+ params["max"] = limit
28
+ if offset > 0:
29
+ params["start"] = offset
30
+ result = None
31
+ try:
32
+ result = api.session.rest_get(url, params=params)
33
+ except WebexError as e:
34
+ handle_rest_error(e)
35
+ result = result or []
36
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
37
+ if output == "json":
38
+ print_json(items)
39
+ else:
40
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
41
+
42
+
43
+
44
+ @app.command("create")
45
+ def create(
46
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
47
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
48
+ debug: bool = typer.Option(False, "--debug"),
49
+ ):
50
+ """Create or Replace existing customer tags with the provided ones\n\nExample --json-body:\n '{"tags":[{"name":"...","description":"..."}]}'."""
51
+ api = get_api(debug=debug)
52
+ org_id = resolve_org_id(api.session)
53
+ url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}/assignTags"
54
+ if json_body:
55
+ body = json.loads(json_body)
56
+ else:
57
+ body = {}
58
+ try:
59
+ result = api.session.rest_post(url, json=body)
60
+ except WebexError as e:
61
+ handle_rest_error(e)
62
+ if output == "json":
63
+ print_json(result)
64
+ elif isinstance(result, dict) and "id" in result:
65
+ typer.echo(f"Created: {result['id']}")
66
+ elif not result or result == {}:
67
+ typer.echo("Created.")
68
+ else:
69
+ print_json(result)
70
+
71
+
72
+
73
+ @app.command("show")
74
+ def show(
75
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
76
+ debug: bool = typer.Option(False, "--debug"),
77
+ ):
78
+ """Get customer organization's tags."""
79
+ api = get_api(debug=debug)
80
+ org_id = resolve_org_id(api.session)
81
+ url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}"
82
+ try:
83
+ result = api.session.rest_get(url)
84
+ except WebexError as e:
85
+ handle_rest_error(e)
86
+ if output == "json":
87
+ print_json(result)
88
+ else:
89
+ if isinstance(result, dict):
90
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
91
+ elif isinstance(result, list):
92
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
93
+ else:
94
+ print_json(result)
95
+
96
+
97
+
98
+ @app.command("list-organizations")
99
+ def list_organizations(
100
+ tags: str = typer.Option(..., "--tags", help="A comma separated list of tags to filter by."),
101
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
102
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
103
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
104
+ debug: bool = typer.Option(False, "--debug"),
105
+ ):
106
+ """Fetch all customers for a given set of tags."""
107
+ api = get_api(debug=debug)
108
+ url = f"https://webexapis.com/v1/partner/tags/organizations"
109
+ params = {}
110
+ if tags is not None:
111
+ params["tags"] = tags
112
+ if limit > 0:
113
+ params["max"] = limit
114
+ if offset > 0:
115
+ params["start"] = offset
116
+ result = None
117
+ try:
118
+ result = api.session.rest_get(url, params=params)
119
+ except WebexError as e:
120
+ handle_rest_error(e)
121
+ result = result or []
122
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
123
+ if output == "json":
124
+ print_json(items)
125
+ else:
126
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
127
+
128
+
129
+
130
+ @app.command("create-assign-tags")
131
+ def create_assign_tags(
132
+ subscription_id: str = typer.Argument(help="subscriptionId"),
133
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
134
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
135
+ debug: bool = typer.Option(False, "--debug"),
136
+ ):
137
+ """Create or Replace existing subscription tags with the provided ones\n\nExample --json-body:\n '{"tags":[{"name":"...","description":"..."}]}'."""
138
+ api = get_api(debug=debug)
139
+ org_id = resolve_org_id(api.session)
140
+ url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}/subscriptions/{subscription_id}/assignTags"
141
+ if json_body:
142
+ body = json.loads(json_body)
143
+ else:
144
+ body = {}
145
+ try:
146
+ result = api.session.rest_post(url, json=body)
147
+ except WebexError as e:
148
+ handle_rest_error(e)
149
+ if output == "json":
150
+ print_json(result)
151
+ elif isinstance(result, dict) and "id" in result:
152
+ typer.echo(f"Created: {result['id']}")
153
+ elif not result or result == {}:
154
+ typer.echo("Created.")
155
+ else:
156
+ print_json(result)
157
+
158
+
159
+
160
+ @app.command("list-subscriptions")
161
+ def list_subscriptions(
162
+ tags: str = typer.Option(..., "--tags", help="A comma separated list of tags to filter by."),
163
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
164
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
165
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
166
+ debug: bool = typer.Option(False, "--debug"),
167
+ ):
168
+ """Subscription List on a given tag name or a set of tags."""
169
+ api = get_api(debug=debug)
170
+ url = f"https://webexapis.com/v1/partner/tags/subscriptions"
171
+ params = {}
172
+ if tags is not None:
173
+ params["tags"] = tags
174
+ if limit > 0:
175
+ params["max"] = limit
176
+ if offset > 0:
177
+ params["start"] = offset
178
+ result = None
179
+ try:
180
+ result = api.session.rest_get(url, params=params)
181
+ except WebexError as e:
182
+ handle_rest_error(e)
183
+ result = result or []
184
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
185
+ if output == "json":
186
+ print_json(items)
187
+ else:
188
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
189
+
190
+
191
+
192
+ @app.command("show-subscriptions")
193
+ def show_subscriptions(
194
+ subscription_id: str = typer.Argument(help="subscriptionId"),
195
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
196
+ debug: bool = typer.Option(False, "--debug"),
197
+ ):
198
+ """Fetch a Subscription."""
199
+ api = get_api(debug=debug)
200
+ org_id = resolve_org_id(api.session)
201
+ url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}/subscriptions/{subscription_id}"
202
+ try:
203
+ result = api.session.rest_get(url)
204
+ except WebexError as e:
205
+ handle_rest_error(e)
206
+ if output == "json":
207
+ print_json(result)
208
+ else:
209
+ if isinstance(result, dict):
210
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
211
+ elif isinstance(result, list):
212
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
213
+ else:
214
+ print_json(result)
215
+
216
+
@@ -0,0 +1,279 @@
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 people.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ email: str = typer.Option(None, "--email", help="List people with this email address. For non-admin requests,"),
15
+ display_name: str = typer.Option(None, "--display-name", help="List people whose name starts with this string. For non-admi"),
16
+ id_param: str = typer.Option(None, "--id", help="List people by ID. Accepts up to 85 person IDs separated by"),
17
+ roles: str = typer.Option(None, "--roles", help="List of roleIds separated by commas."),
18
+ calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
19
+ location_id: str = typer.Option(None, "--location-id", help="List people present in this location."),
20
+ exclude_status: str = typer.Option(None, "--exclude-status", help="Omit people status/availability to enhance query performance"),
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
+ """List People."""
27
+ api = get_api(debug=debug)
28
+ url = f"https://webexapis.com/v1/people"
29
+ params = {}
30
+ if email is not None:
31
+ params["email"] = email
32
+ if display_name is not None:
33
+ params["displayName"] = display_name
34
+ if id_param is not None:
35
+ params["id"] = id_param
36
+ if roles is not None:
37
+ params["roles"] = roles
38
+ if calling_data is not None:
39
+ params["callingData"] = calling_data
40
+ if location_id is not None:
41
+ params["locationId"] = location_id
42
+ if exclude_status is not None:
43
+ params["excludeStatus"] = exclude_status
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
+ try:
52
+ if limit > 0:
53
+ result = api.session.rest_get(url, params=params)
54
+ result = result or {}
55
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
56
+ else:
57
+ items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
58
+ except WebexError as e:
59
+ handle_rest_error(e)
60
+ if output == "json":
61
+ print_json(items)
62
+ else:
63
+ print_table(items, columns=[('ID', 'id'), ('Display Name', 'displayName'), ('Email', 'emails[0]')], limit=limit)
64
+
65
+
66
+
67
+ @app.command("create")
68
+ def create(
69
+ calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
70
+ min_response: str = typer.Option(None, "--min-response", help="Set to `true` to improve performance by omitting person deta"),
71
+ extension: str = typer.Option(None, "--extension", help="Webex Calling extension of the person. This is only settable"),
72
+ location_id: str = typer.Option(None, "--location-id", help="The ID of the location for this person."),
73
+ display_name: str = typer.Option(None, "--display-name", help="The full name of the person."),
74
+ first_name: str = typer.Option(None, "--first-name", help="The first name of the person."),
75
+ last_name: str = typer.Option(None, "--last-name", help="The last name of the person."),
76
+ avatar: str = typer.Option(None, "--avatar", help="The URL to the person's avatar in PNG format."),
77
+ org_id: str = typer.Option(None, "--org-id", help="The ID of the organization to which this person belongs."),
78
+ department: str = typer.Option(None, "--department", help="The business department the user belongs to."),
79
+ manager: str = typer.Option(None, "--manager", help="A manager identifier."),
80
+ manager_id: str = typer.Option(None, "--manager-id", help="Person ID of the manager."),
81
+ title: str = typer.Option(None, "--title", help="The person's title."),
82
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
83
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
84
+ debug: bool = typer.Option(False, "--debug"),
85
+ ):
86
+ """Create a Person\n\nExample --json-body:\n '{"emails":["..."],"phoneNumbers":[{"type":"...","value":"..."}],"extension":"...","locationId":"...","displayName":"...","firstName":"...","lastName":"...","avatar":"..."}'."""
87
+ api = get_api(debug=debug)
88
+ url = f"https://webexapis.com/v1/people"
89
+ params = {}
90
+ if calling_data is not None:
91
+ params["callingData"] = calling_data
92
+ if min_response is not None:
93
+ params["minResponse"] = min_response
94
+ if json_body:
95
+ body = json.loads(json_body)
96
+ else:
97
+ body = {}
98
+ if extension is not None:
99
+ body["extension"] = extension
100
+ if location_id is not None:
101
+ body["locationId"] = location_id
102
+ if display_name is not None:
103
+ body["displayName"] = display_name
104
+ if first_name is not None:
105
+ body["firstName"] = first_name
106
+ if last_name is not None:
107
+ body["lastName"] = last_name
108
+ if avatar is not None:
109
+ body["avatar"] = avatar
110
+ if org_id is not None:
111
+ body["orgId"] = org_id
112
+ if department is not None:
113
+ body["department"] = department
114
+ if manager is not None:
115
+ body["manager"] = manager
116
+ if manager_id is not None:
117
+ body["managerId"] = manager_id
118
+ if title is not None:
119
+ body["title"] = title
120
+ try:
121
+ result = api.session.rest_post(url, json=body, params=params)
122
+ except WebexError as e:
123
+ handle_rest_error(e)
124
+ if output == "json":
125
+ print_json(result)
126
+ elif isinstance(result, dict) and "id" in result:
127
+ typer.echo(f"Created: {result['id']}")
128
+ elif not result or result == {}:
129
+ typer.echo("Created.")
130
+ else:
131
+ print_json(result)
132
+
133
+
134
+
135
+ @app.command("show")
136
+ def show(
137
+ person_id: str = typer.Argument(help="personId"),
138
+ calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
139
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
140
+ debug: bool = typer.Option(False, "--debug"),
141
+ ):
142
+ """Get Person Details."""
143
+ api = get_api(debug=debug)
144
+ url = f"https://webexapis.com/v1/people/{person_id}"
145
+ params = {}
146
+ if calling_data is not None:
147
+ params["callingData"] = calling_data
148
+ try:
149
+ result = api.session.rest_get(url, params=params)
150
+ except WebexError as e:
151
+ handle_rest_error(e)
152
+ if output == "json":
153
+ print_json(result)
154
+ else:
155
+ if isinstance(result, dict):
156
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
157
+ elif isinstance(result, list):
158
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
159
+ else:
160
+ print_json(result)
161
+
162
+
163
+
164
+ @app.command("update")
165
+ def update(
166
+ person_id: str = typer.Argument(help="personId"),
167
+ calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
168
+ show_all_types: str = typer.Option(None, "--show-all-types", help="Include additional user data like `#attendee` role."),
169
+ min_response: str = typer.Option(None, "--min-response", help="Set to `true` to improve performance by omitting person deta"),
170
+ extension: str = typer.Option(None, "--extension", help="Webex Calling extension of the person. This is only settable"),
171
+ location_id: str = typer.Option(None, "--location-id", help="The ID of the location for this person."),
172
+ display_name: str = typer.Option(None, "--display-name", help="The full name of the person."),
173
+ first_name: str = typer.Option(None, "--first-name", help="The first name of the person."),
174
+ last_name: str = typer.Option(None, "--last-name", help="The last name of the person."),
175
+ nick_name: str = typer.Option(None, "--nick-name", help="The nickname of the person if configured. This cannot be ove"),
176
+ avatar: str = typer.Option(None, "--avatar", help="The URL to the person's avatar in PNG format."),
177
+ org_id: str = typer.Option(None, "--org-id", help="The ID of the organization to which this person belongs."),
178
+ department: str = typer.Option(None, "--department", help="The business department the user belongs to."),
179
+ manager: str = typer.Option(None, "--manager", help="A manager identifier."),
180
+ manager_id: str = typer.Option(None, "--manager-id", help="Person ID of the manager."),
181
+ title: str = typer.Option(None, "--title", help="The person's title."),
182
+ login_enabled: bool = typer.Option(None, "--login-enabled/--no-login-enabled", help="Whether or not the user is allowed to use Webex. This proper"),
183
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
184
+ debug: bool = typer.Option(False, "--debug"),
185
+ ):
186
+ """Update a Person\n\nExample --json-body:\n '{"displayName":"...","emails":["..."],"phoneNumbers":[{"type":"...","value":"..."}],"extension":"...","locationId":"...","firstName":"...","lastName":"...","nickName":"..."}'."""
187
+ api = get_api(debug=debug)
188
+ url = f"https://webexapis.com/v1/people/{person_id}"
189
+ params = {}
190
+ if calling_data is not None:
191
+ params["callingData"] = calling_data
192
+ if show_all_types is not None:
193
+ params["showAllTypes"] = show_all_types
194
+ if min_response is not None:
195
+ params["minResponse"] = min_response
196
+ if json_body:
197
+ body = json.loads(json_body)
198
+ else:
199
+ body = {}
200
+ if extension is not None:
201
+ body["extension"] = extension
202
+ if location_id is not None:
203
+ body["locationId"] = location_id
204
+ if display_name is not None:
205
+ body["displayName"] = display_name
206
+ if first_name is not None:
207
+ body["firstName"] = first_name
208
+ if last_name is not None:
209
+ body["lastName"] = last_name
210
+ if nick_name is not None:
211
+ body["nickName"] = nick_name
212
+ if avatar is not None:
213
+ body["avatar"] = avatar
214
+ if org_id is not None:
215
+ body["orgId"] = org_id
216
+ if department is not None:
217
+ body["department"] = department
218
+ if manager is not None:
219
+ body["manager"] = manager
220
+ if manager_id is not None:
221
+ body["managerId"] = manager_id
222
+ if title is not None:
223
+ body["title"] = title
224
+ if login_enabled is not None:
225
+ body["loginEnabled"] = login_enabled
226
+ try:
227
+ result = api.session.rest_put(url, json=body, params=params)
228
+ except WebexError as e:
229
+ handle_rest_error(e)
230
+ typer.echo(f"Updated.")
231
+
232
+
233
+
234
+ @app.command("delete")
235
+ def delete(
236
+ person_id: str = typer.Argument(help="personId"),
237
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
238
+ debug: bool = typer.Option(False, "--debug"),
239
+ ):
240
+ """Delete a Person."""
241
+ if not force:
242
+ typer.confirm(f"Delete {person_id}?", abort=True)
243
+ api = get_api(debug=debug)
244
+ url = f"https://webexapis.com/v1/people/{person_id}"
245
+ try:
246
+ api.session.rest_delete(url)
247
+ except WebexError as e:
248
+ handle_rest_error(e)
249
+ typer.echo(f"Deleted: {person_id}")
250
+
251
+
252
+
253
+ @app.command("show-me")
254
+ def show_me(
255
+ calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
256
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
257
+ debug: bool = typer.Option(False, "--debug"),
258
+ ):
259
+ """Get My Own Details."""
260
+ api = get_api(debug=debug)
261
+ url = f"https://webexapis.com/v1/people/me"
262
+ params = {}
263
+ if calling_data is not None:
264
+ params["callingData"] = calling_data
265
+ try:
266
+ result = api.session.rest_get(url, params=params)
267
+ except WebexError as e:
268
+ handle_rest_error(e)
269
+ if output == "json":
270
+ print_json(result)
271
+ else:
272
+ if isinstance(result, dict):
273
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
274
+ elif isinstance(result, list):
275
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
276
+ else:
277
+ print_json(result)
278
+
279
+
@@ -0,0 +1,71 @@
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 person-call-settings.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ person_id: str = typer.Argument(help="personId"),
15
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
16
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
17
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
18
+ debug: bool = typer.Option(False, "--debug"),
19
+ ):
20
+ """Retrieve a Person's Monitoring Settings."""
21
+ api = get_api(debug=debug)
22
+ url = f"https://webexapis.com/v1/people/{person_id}/features/monitoring"
23
+ params = {}
24
+ if limit > 0:
25
+ params["max"] = limit
26
+ if offset > 0:
27
+ params["start"] = offset
28
+ org_id = get_org_id()
29
+ if org_id is not None:
30
+ params["orgId"] = org_id
31
+ result = None
32
+ try:
33
+ result = api.session.rest_get(url, params=params)
34
+ except WebexError as e:
35
+ handle_rest_error(e)
36
+ result = result or []
37
+ items = result.get("monitoredElements", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
38
+ if output == "json":
39
+ print_json(items)
40
+ else:
41
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
42
+
43
+
44
+
45
+ @app.command("update")
46
+ def update(
47
+ person_id: str = typer.Argument(help="personId"),
48
+ enable_call_park_notification: bool = typer.Option(None, "--enable-call-park-notification/--no-enable-call-park-notification", help="Call park notification is enabled or disabled."),
49
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
50
+ debug: bool = typer.Option(False, "--debug"),
51
+ ):
52
+ """Modify Monitoring Settings for a Person\n\nExample --json-body:\n '{"enableCallParkNotification":true,"monitoredElements":["..."]}'."""
53
+ api = get_api(debug=debug)
54
+ url = f"https://webexapis.com/v1/people/{person_id}/features/monitoring"
55
+ params = {}
56
+ org_id = get_org_id()
57
+ if org_id is not None:
58
+ params["orgId"] = org_id
59
+ if json_body:
60
+ body = json.loads(json_body)
61
+ else:
62
+ body = {}
63
+ if enable_call_park_notification is not None:
64
+ body["enableCallParkNotification"] = enable_call_park_notification
65
+ try:
66
+ result = api.session.rest_put(url, json=body, params=params)
67
+ except WebexError as e:
68
+ handle_rest_error(e)
69
+ typer.echo(f"Updated.")
70
+
71
+