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,701 @@
1
+ import json
2
+ import typer
3
+ from wxcli.auth import get_api
4
+ from wxcli.errors import WebexError, handle_rest_error
5
+ from wxcli.output import print_table, print_json
6
+ from wxcli.config import resolve_org_id, get_cc_base_url, get_cc_org_id
7
+
8
+
9
+ app = typer.Typer(help="Manage Webex Contact Center cc-users.")
10
+
11
+
12
+ @app.command("list")
13
+ def cmd_list(
14
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
15
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
16
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
17
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
18
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specify whether to include array fields in the response. Thi"),
19
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
20
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
21
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
22
+ debug: bool = typer.Option(False, "--debug"),
23
+ ):
24
+ """List Users."""
25
+ api = get_api(debug=debug)
26
+ cc_base_url = get_cc_base_url()
27
+ orgid = get_cc_org_id(api.session)
28
+ url = f"{cc_base_url}/organization/{orgid}/user"
29
+ params = {}
30
+ if filter_param is not None:
31
+ params["filter"] = filter_param
32
+ if attributes is not None:
33
+ params["attributes"] = attributes
34
+ if page is not None:
35
+ params["page"] = page
36
+ if page_size is not None:
37
+ params["pageSize"] = page_size
38
+ if single_object_response is not None:
39
+ params["singleObjectResponse"] = single_object_response
40
+ if limit > 0:
41
+ params["max"] = limit
42
+ if offset > 0:
43
+ params["start"] = offset
44
+ result = None
45
+ try:
46
+ result = api.session.rest_get(url, params=params)
47
+ except WebexError as e:
48
+ handle_rest_error(e)
49
+ result = result or []
50
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
51
+ if output == "json":
52
+ print_json(items)
53
+ else:
54
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
55
+
56
+
57
+
58
+ @app.command("update")
59
+ def update(
60
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
61
+ debug: bool = typer.Option(False, "--debug"),
62
+ ):
63
+ """Bulk partial update Users\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
64
+ api = get_api(debug=debug)
65
+ cc_base_url = get_cc_base_url()
66
+ orgid = get_cc_org_id(api.session)
67
+ url = f"{cc_base_url}/organization/{orgid}/user/bulk"
68
+ if json_body:
69
+ body = json.loads(json_body)
70
+ else:
71
+ body = {}
72
+ try:
73
+ result = api.session.rest_patch(url, json=body)
74
+ except WebexError as e:
75
+ handle_rest_error(e)
76
+ typer.echo(f"Updated.")
77
+
78
+
79
+
80
+ @app.command("update-dynamic-skill")
81
+ def update_dynamic_skill(
82
+ skill_id: str = typer.Argument(help="skillId"),
83
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
84
+ debug: bool = typer.Option(False, "--debug"),
85
+ ):
86
+ """Bulk partial update Users with dynamic skills\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
87
+ api = get_api(debug=debug)
88
+ cc_base_url = get_cc_base_url()
89
+ orgid = get_cc_org_id(api.session)
90
+ url = f"{cc_base_url}/organization/{orgid}/user/bulk/update-dynamic-skill/{skill_id}"
91
+ if json_body:
92
+ body = json.loads(json_body)
93
+ else:
94
+ body = {}
95
+ try:
96
+ result = api.session.rest_patch(url, json=body)
97
+ except WebexError as e:
98
+ handle_rest_error(e)
99
+ typer.echo(f"Updated.")
100
+
101
+
102
+
103
+ @app.command("show")
104
+ def show(
105
+ id: str = typer.Argument(help="id"),
106
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
107
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
108
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
109
+ debug: bool = typer.Option(False, "--debug"),
110
+ ):
111
+ """List users by call monitoring id."""
112
+ api = get_api(debug=debug)
113
+ cc_base_url = get_cc_base_url()
114
+ orgid = get_cc_org_id(api.session)
115
+ url = f"{cc_base_url}/organization/{orgid}/user/by-call-monitoring-id/{id}"
116
+ params = {}
117
+ if page is not None:
118
+ params["page"] = page
119
+ if page_size is not None:
120
+ params["pageSize"] = page_size
121
+ try:
122
+ result = api.session.rest_get(url, params=params)
123
+ except WebexError as e:
124
+ handle_rest_error(e)
125
+ if output == "json":
126
+ print_json(result)
127
+ else:
128
+ if isinstance(result, dict):
129
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
130
+ elif isinstance(result, list):
131
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
132
+ else:
133
+ print_json(result)
134
+
135
+
136
+
137
+ @app.command("show-by-ci-user-id-organization")
138
+ def show_by_ci_user_id_organization(
139
+ id: str = typer.Argument(help="id"),
140
+ include_user_profile: str = typer.Option(None, "--include-user-profile", help="Specifiy whether to include user profile data"),
141
+ include_skill_details: str = typer.Option(None, "--include-skill-details", help="If set to true, the response includes skill information for"),
142
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
143
+ debug: bool = typer.Option(False, "--debug"),
144
+ ):
145
+ """Get specific User by CI User ID."""
146
+ api = get_api(debug=debug)
147
+ cc_base_url = get_cc_base_url()
148
+ orgid = get_cc_org_id(api.session)
149
+ url = f"{cc_base_url}/organization/{orgid}/user/by-ci-user-id/{id}"
150
+ params = {}
151
+ if include_user_profile is not None:
152
+ params["includeUserProfile"] = include_user_profile
153
+ if include_skill_details is not None:
154
+ params["includeSkillDetails"] = include_skill_details
155
+ try:
156
+ result = api.session.rest_get(url, params=params)
157
+ except WebexError as e:
158
+ handle_rest_error(e)
159
+ if output == "json":
160
+ print_json(result)
161
+ else:
162
+ if isinstance(result, dict):
163
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
164
+ elif isinstance(result, list):
165
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
166
+ else:
167
+ print_json(result)
168
+
169
+
170
+
171
+ @app.command("show-by-dynamic-skill-id")
172
+ def show_by_dynamic_skill_id(
173
+ skill_id: str = typer.Argument(help="skillId"),
174
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
175
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
176
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
177
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
178
+ debug: bool = typer.Option(False, "--debug"),
179
+ ):
180
+ """Get users by dynamic skill ID."""
181
+ api = get_api(debug=debug)
182
+ cc_base_url = get_cc_base_url()
183
+ orgid = get_cc_org_id(api.session)
184
+ url = f"{cc_base_url}/organization/{orgid}/user/by-dynamic-skill-id/{skill_id}"
185
+ params = {}
186
+ if search is not None:
187
+ params["search"] = search
188
+ if page is not None:
189
+ params["page"] = page
190
+ if page_size is not None:
191
+ params["pageSize"] = page_size
192
+ try:
193
+ result = api.session.rest_get(url, params=params)
194
+ except WebexError as e:
195
+ handle_rest_error(e)
196
+ if output == "json":
197
+ print_json(result)
198
+ else:
199
+ if isinstance(result, dict):
200
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
201
+ elif isinstance(result, list):
202
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
203
+ else:
204
+ print_json(result)
205
+
206
+
207
+
208
+ @app.command("create")
209
+ def create(
210
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
211
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
212
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
213
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
214
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
215
+ debug: bool = typer.Option(False, "--debug"),
216
+ ):
217
+ """Get the agents matching skill requirements criteria\n\nExample --json-body:\n '{"skillRequirements":[{"skillId":"...","condition":"...","skillValue":"...","organizationId":"...","id":"...","version":"...","skillName":"...","skillType":"..."}]}'."""
218
+ api = get_api(debug=debug)
219
+ cc_base_url = get_cc_base_url()
220
+ orgid = get_cc_org_id(api.session)
221
+ url = f"{cc_base_url}/organization/{orgid}/user/fetch-by-skill-requirements"
222
+ params = {}
223
+ if search is not None:
224
+ params["search"] = search
225
+ if page is not None:
226
+ params["page"] = page
227
+ if page_size is not None:
228
+ params["pageSize"] = page_size
229
+ if json_body:
230
+ body = json.loads(json_body)
231
+ else:
232
+ body = {}
233
+ try:
234
+ result = api.session.rest_post(url, json=body, params=params)
235
+ except WebexError as e:
236
+ handle_rest_error(e)
237
+ if output == "json":
238
+ print_json(result)
239
+ elif isinstance(result, dict) and "id" in result:
240
+ typer.echo(f"Created: {result['id']}")
241
+ elif not result or result == {}:
242
+ typer.echo("Created.")
243
+ else:
244
+ print_json(result)
245
+
246
+
247
+
248
+ @app.command("create-fetch-user-details-by-ids")
249
+ def create_fetch_user_details_by_ids(
250
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
251
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
252
+ search: str = typer.Option(None, "--search", help="Text used to search for users (e.g., by firstName, lastName"),
253
+ queue_id: str = typer.Option(None, "--queue-id", help="Agent Based Queue ID to filter users . Required if `search`"),
254
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
255
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
256
+ debug: bool = typer.Option(False, "--debug"),
257
+ ):
258
+ """List Users with details\n\nExample --json-body:\n '{"userIds":[{}],"search":"...","queueId":"..."}'."""
259
+ api = get_api(debug=debug)
260
+ cc_base_url = get_cc_base_url()
261
+ orgid = get_cc_org_id(api.session)
262
+ url = f"{cc_base_url}/organization/{orgid}/user/fetch-user-details-by-ids"
263
+ params = {}
264
+ if page is not None:
265
+ params["page"] = page
266
+ if page_size is not None:
267
+ params["pageSize"] = page_size
268
+ if json_body:
269
+ body = json.loads(json_body)
270
+ else:
271
+ body = {}
272
+ if search is not None:
273
+ body["search"] = search
274
+ if queue_id is not None:
275
+ body["queueId"] = queue_id
276
+ try:
277
+ result = api.session.rest_post(url, json=body, params=params)
278
+ except WebexError as e:
279
+ handle_rest_error(e)
280
+ if output == "json":
281
+ print_json(result)
282
+ elif isinstance(result, dict) and "id" in result:
283
+ typer.echo(f"Created: {result['id']}")
284
+ elif not result or result == {}:
285
+ typer.echo("Created.")
286
+ else:
287
+ print_json(result)
288
+
289
+
290
+
291
+ @app.command("list-with-user-profile")
292
+ def list_with_user_profile(
293
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
294
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
295
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
296
+ debug: bool = typer.Option(False, "--debug"),
297
+ ):
298
+ """List Users along with profile."""
299
+ api = get_api(debug=debug)
300
+ cc_base_url = get_cc_base_url()
301
+ orgid = get_cc_org_id(api.session)
302
+ url = f"{cc_base_url}/organization/{orgid}/user/with-user-profile"
303
+ params = {}
304
+ if limit > 0:
305
+ params["max"] = limit
306
+ if offset > 0:
307
+ params["start"] = offset
308
+ result = None
309
+ try:
310
+ result = api.session.rest_get(url, params=params)
311
+ except WebexError as e:
312
+ handle_rest_error(e)
313
+ result = result or []
314
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
315
+ if output == "json":
316
+ print_json(items)
317
+ else:
318
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
319
+
320
+
321
+
322
+ @app.command("show-with-user-profile")
323
+ def show_with_user_profile(
324
+ id: str = typer.Argument(help="id"),
325
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
326
+ debug: bool = typer.Option(False, "--debug"),
327
+ ):
328
+ """Get specific User along with profile by ID."""
329
+ api = get_api(debug=debug)
330
+ cc_base_url = get_cc_base_url()
331
+ orgid = get_cc_org_id(api.session)
332
+ url = f"{cc_base_url}/organization/{orgid}/user/with-user-profile/{id}"
333
+ try:
334
+ result = api.session.rest_get(url)
335
+ except WebexError as e:
336
+ handle_rest_error(e)
337
+ if output == "json":
338
+ print_json(result)
339
+ else:
340
+ if isinstance(result, dict):
341
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
342
+ elif isinstance(result, list):
343
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
344
+ else:
345
+ print_json(result)
346
+
347
+
348
+
349
+ @app.command("show-user")
350
+ def show_user(
351
+ id: str = typer.Argument(help="id"),
352
+ include_count: str = typer.Option(None, "--include-count", help="If set to true, the API response will include the count of e"),
353
+ include_user_profile_type: str = typer.Option(None, "--include-user-profile-type", help="If set to true, the API response includes the User Profile."),
354
+ include_skill_profile_audit: str = typer.Option(None, "--include-skill-profile-audit", help="If set to true gives skill profile modification info."),
355
+ include_reskill_audit_info: str = typer.Option(None, "--include-reskill-audit-info", help="If set to true gives skill profile and dynamic skill modific"),
356
+ include_skill_details: str = typer.Option(None, "--include-skill-details", help="If set to true, the response includes skill information for"),
357
+ check_if_user_has_dynamic_skill: str = typer.Option(None, "--check-if-user-has-dynamic-skill", help="If set to true, checks if user has the specified dynamic ski"),
358
+ dynamic_skill_id: str = typer.Option(None, "--dynamic-skill-id", help="Dynamic skill ID to check if user has it assigned (required"),
359
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
360
+ debug: bool = typer.Option(False, "--debug"),
361
+ ):
362
+ """Get specific User by ID."""
363
+ api = get_api(debug=debug)
364
+ cc_base_url = get_cc_base_url()
365
+ orgid = get_cc_org_id(api.session)
366
+ url = f"{cc_base_url}/organization/{orgid}/user/{id}"
367
+ params = {}
368
+ if include_count is not None:
369
+ params["includeCount"] = include_count
370
+ if include_user_profile_type is not None:
371
+ params["includeUserProfileType"] = include_user_profile_type
372
+ if include_skill_profile_audit is not None:
373
+ params["includeSkillProfileAudit"] = include_skill_profile_audit
374
+ if include_reskill_audit_info is not None:
375
+ params["includeReskillAuditInfo"] = include_reskill_audit_info
376
+ if include_skill_details is not None:
377
+ params["includeSkillDetails"] = include_skill_details
378
+ if check_if_user_has_dynamic_skill is not None:
379
+ params["checkIfUserHasDynamicSkill"] = check_if_user_has_dynamic_skill
380
+ if dynamic_skill_id is not None:
381
+ params["dynamicSkillId"] = dynamic_skill_id
382
+ try:
383
+ result = api.session.rest_get(url, params=params)
384
+ except WebexError as e:
385
+ handle_rest_error(e)
386
+ if output == "json":
387
+ print_json(result)
388
+ else:
389
+ if isinstance(result, dict):
390
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
391
+ elif isinstance(result, list):
392
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
393
+ else:
394
+ print_json(result)
395
+
396
+
397
+
398
+ @app.command("update-user")
399
+ def update_user(
400
+ id: str = typer.Argument(help="id"),
401
+ organization_id: str = typer.Option(None, "--organization-id", help="ID of the contact center organization. This field is require"),
402
+ id_param: str = typer.Option(None, "--id", help="ID of this contact center resource. It should not be specifi"),
403
+ version: str = typer.Option(None, "--version", help="The version of this resource. For a newly created resource,"),
404
+ first_name: str = typer.Option(None, "--first-name", help="The first name of the user. Can be changed using Users Manag"),
405
+ last_name: str = typer.Option(None, "--last-name", help="The last name of the user. Can be changed using Users Manage"),
406
+ email: str = typer.Option(None, "--email", help="The email address of the user. Can be changed using Users Ma"),
407
+ work_phone: str = typer.Option(None, "--work-phone", help="The work phone number of the user."),
408
+ mobile: str = typer.Option(None, "--mobile", help="The mobile phone number of the user."),
409
+ ci_user_id: str = typer.Option(None, "--ci-user-id", help="Cisco Common Identity user Id. Existence of a CI user is a p"),
410
+ broad_cloud_user_id: str = typer.Option(None, "--broad-cloud-user-id", help="Broadcloud user Id. This field cannot be modified."),
411
+ user_profile_id: str = typer.Option(None, "--user-profile-id", help="Identifier for an user profile which a Contact Center admini"),
412
+ contact_center_enabled: bool = typer.Option(None, "--contact-center-enabled/--no-contact-center-enabled", help="The setting is for accessing the Agent Desktop to handle cus"),
413
+ timezone: str = typer.Option(None, "--timezone", help="(Optional) The time zone that you provision for your enterpr"),
414
+ xsp_version: str = typer.Option(None, "--xsp-version", help="(Optional) Used to subscribe for recording events. This fiel"),
415
+ subscription_id: str = typer.Option(None, "--subscription-id", help="(Optional) Used to subscribe for recording events. This fiel"),
416
+ site_id: str = typer.Option(None, "--site-id", help="(Optional) Identifier for a site which is a physical contact"),
417
+ skill_profile_id: str = typer.Option(None, "--skill-profile-id", help="(Optional) If your enterprise uses the optional Skills-Based"),
418
+ agent_profile_id: str = typer.Option(None, "--agent-profile-id", help="Identifier for a Desktop Profile which is a group of permiss"),
419
+ multimedia_profile_id: str = typer.Option(None, "--multimedia-profile-id", help="(Optional) If your organization administrator enables Multim"),
420
+ deafult_dialled_number: str = typer.Option(None, "--deafult-dialled-number", help="(Optional) The dial number of the agent. This field is appli"),
421
+ external_identifier: str = typer.Option(None, "--external-identifier", help="(Optional) Agent identification details, such as the employe"),
422
+ active: bool = typer.Option(None, "--active/--no-active", help="Indicates whether the user is active or not active. Can be c"),
423
+ imi_user_created: bool = typer.Option(None, "--imi-user-created/--no-imi-user-created", help="(Optional) Indicates whether this user has a corresponding u"),
424
+ preferred_supervisor_team_id: str = typer.Option(None, "--preferred-supervisor-team-id", help="(Optional) Indicates the id of a preferred supervisor."),
425
+ user_level_burnout_inclusion: str = typer.Option(None, "--user-level-burnout-inclusion", help="Choices: INCLUDED, EXCLUDED"),
426
+ user_level_auto_csat_inclusion: str = typer.Option(None, "--user-level-auto-csat-inclusion", help="Choices: INCLUDED, EXCLUDED"),
427
+ user_level_wellness_break_reminders: str = typer.Option(None, "--user-level-wellness-break-reminders", help="Choices: DISABLED, ENABLED"),
428
+ user_level_summaries_inclusion: str = typer.Option(None, "--user-level-summaries-inclusion", help="Choices: INCLUDED, EXCLUDED"),
429
+ supervisor_capabilities_enabled: bool = typer.Option(None, "--supervisor-capabilities-enabled/--no-supervisor-capabilities-enabled", help="Indicates whether supervisor capabilities are enabled for th"),
430
+ agent_capabilities_enabled: bool = typer.Option(None, "--agent-capabilities-enabled/--no-agent-capabilities-enabled", help="Indicates whether agent capabilities are enabled for the use"),
431
+ created_time: str = typer.Option(None, "--created-time", help="This is the created time of the entity."),
432
+ last_updated_time: str = typer.Option(None, "--last-updated-time", help="This is the updated time of the entity."),
433
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
434
+ debug: bool = typer.Option(False, "--debug"),
435
+ ):
436
+ """Update specific User by ID\n\nExample --json-body:\n '{"firstName":"...","lastName":"...","email":"...","ciUserId":"...","userProfileId":"...","contactCenterEnabled":true,"active":true,"organizationId":"..."}'."""
437
+ api = get_api(debug=debug)
438
+ cc_base_url = get_cc_base_url()
439
+ orgid = get_cc_org_id(api.session)
440
+ url = f"{cc_base_url}/organization/{orgid}/user/{id}"
441
+ if json_body:
442
+ body = json.loads(json_body)
443
+ else:
444
+ body = {}
445
+ if organization_id is not None:
446
+ body["organizationId"] = organization_id
447
+ if id_param is not None:
448
+ body["id"] = id_param
449
+ if version is not None:
450
+ body["version"] = version
451
+ if first_name is not None:
452
+ body["firstName"] = first_name
453
+ if last_name is not None:
454
+ body["lastName"] = last_name
455
+ if email is not None:
456
+ body["email"] = email
457
+ if work_phone is not None:
458
+ body["workPhone"] = work_phone
459
+ if mobile is not None:
460
+ body["mobile"] = mobile
461
+ if ci_user_id is not None:
462
+ body["ciUserId"] = ci_user_id
463
+ if broad_cloud_user_id is not None:
464
+ body["broadCloudUserId"] = broad_cloud_user_id
465
+ if user_profile_id is not None:
466
+ body["userProfileId"] = user_profile_id
467
+ if contact_center_enabled is not None:
468
+ body["contactCenterEnabled"] = contact_center_enabled
469
+ if timezone is not None:
470
+ body["timezone"] = timezone
471
+ if xsp_version is not None:
472
+ body["xspVersion"] = xsp_version
473
+ if subscription_id is not None:
474
+ body["subscriptionId"] = subscription_id
475
+ if site_id is not None:
476
+ body["siteId"] = site_id
477
+ if skill_profile_id is not None:
478
+ body["skillProfileId"] = skill_profile_id
479
+ if agent_profile_id is not None:
480
+ body["agentProfileId"] = agent_profile_id
481
+ if multimedia_profile_id is not None:
482
+ body["multimediaProfileId"] = multimedia_profile_id
483
+ if deafult_dialled_number is not None:
484
+ body["deafultDialledNumber"] = deafult_dialled_number
485
+ if external_identifier is not None:
486
+ body["externalIdentifier"] = external_identifier
487
+ if active is not None:
488
+ body["active"] = active
489
+ if imi_user_created is not None:
490
+ body["imiUserCreated"] = imi_user_created
491
+ if preferred_supervisor_team_id is not None:
492
+ body["preferredSupervisorTeamId"] = preferred_supervisor_team_id
493
+ if user_level_burnout_inclusion is not None:
494
+ body["userLevelBurnoutInclusion"] = user_level_burnout_inclusion
495
+ if user_level_auto_csat_inclusion is not None:
496
+ body["userLevelAutoCSATInclusion"] = user_level_auto_csat_inclusion
497
+ if user_level_wellness_break_reminders is not None:
498
+ body["userLevelWellnessBreakReminders"] = user_level_wellness_break_reminders
499
+ if user_level_summaries_inclusion is not None:
500
+ body["userLevelSummariesInclusion"] = user_level_summaries_inclusion
501
+ if supervisor_capabilities_enabled is not None:
502
+ body["supervisorCapabilitiesEnabled"] = supervisor_capabilities_enabled
503
+ if agent_capabilities_enabled is not None:
504
+ body["agentCapabilitiesEnabled"] = agent_capabilities_enabled
505
+ if created_time is not None:
506
+ body["createdTime"] = created_time
507
+ if last_updated_time is not None:
508
+ body["lastUpdatedTime"] = last_updated_time
509
+ try:
510
+ result = api.session.rest_put(url, json=body)
511
+ except WebexError as e:
512
+ handle_rest_error(e)
513
+ typer.echo(f"Updated.")
514
+
515
+
516
+
517
+ @app.command("list-incoming-references")
518
+ def list_incoming_references(
519
+ id: str = typer.Argument(help="id"),
520
+ type_param: str = typer.Option(None, "--type", help="Entity type of the other entity that has a reference to this"),
521
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
522
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
523
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
524
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
525
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
526
+ debug: bool = typer.Option(False, "--debug"),
527
+ ):
528
+ """List references for a specific User."""
529
+ api = get_api(debug=debug)
530
+ cc_base_url = get_cc_base_url()
531
+ orgid = get_cc_org_id(api.session)
532
+ url = f"{cc_base_url}/organization/{orgid}/user/{id}/incoming-references"
533
+ params = {}
534
+ if type_param is not None:
535
+ params["type"] = type_param
536
+ if page is not None:
537
+ params["page"] = page
538
+ if page_size is not None:
539
+ params["pageSize"] = page_size
540
+ if limit > 0:
541
+ params["max"] = limit
542
+ if offset > 0:
543
+ params["start"] = offset
544
+ result = None
545
+ try:
546
+ result = api.session.rest_get(url, params=params)
547
+ except WebexError as e:
548
+ handle_rest_error(e)
549
+ result = result or []
550
+ items = result.get("data", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
551
+ if output == "json":
552
+ print_json(items)
553
+ else:
554
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
555
+
556
+
557
+
558
+ @app.command("update-reskill")
559
+ def update_reskill(
560
+ id: str = typer.Argument(help="id"),
561
+ organization_id: str = typer.Option(None, "--organization-id", help="ID of the contact center organization. This field is require"),
562
+ id_param: str = typer.Option(None, "--id", help="ID of this contact center resource. It should not be specifi"),
563
+ version: str = typer.Option(None, "--version", help="The version of this resource. For a newly created resource,"),
564
+ skill_profile_id: str = typer.Option(None, "--skill-profile-id", help="The unique identifier of the skill profile to assign to the"),
565
+ created_time: str = typer.Option(None, "--created-time", help="This is the created time of the entity."),
566
+ last_updated_time: str = typer.Option(None, "--last-updated-time", help="This is the updated time of the entity."),
567
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
568
+ debug: bool = typer.Option(False, "--debug"),
569
+ ):
570
+ """Reskill Agents\n\nExample --json-body:\n '{"organizationId":"...","id":"...","version":0,"skillProfileId":"...","dynamicSkills":{"add":["..."],"remove":["..."]},"createdTime":0,"lastUpdatedTime":0}'."""
571
+ api = get_api(debug=debug)
572
+ cc_base_url = get_cc_base_url()
573
+ orgid = get_cc_org_id(api.session)
574
+ url = f"{cc_base_url}/organization/{orgid}/user/{id}/reskill"
575
+ if json_body:
576
+ body = json.loads(json_body)
577
+ else:
578
+ body = {}
579
+ if organization_id is not None:
580
+ body["organizationId"] = organization_id
581
+ if id_param is not None:
582
+ body["id"] = id_param
583
+ if version is not None:
584
+ body["version"] = version
585
+ if skill_profile_id is not None:
586
+ body["skillProfileId"] = skill_profile_id
587
+ if created_time is not None:
588
+ body["createdTime"] = created_time
589
+ if last_updated_time is not None:
590
+ body["lastUpdatedTime"] = last_updated_time
591
+ try:
592
+ result = api.session.rest_patch(url, json=body)
593
+ except WebexError as e:
594
+ handle_rest_error(e)
595
+ typer.echo(f"Updated.")
596
+
597
+
598
+
599
+ @app.command("list-user")
600
+ def list_user(
601
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
602
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
603
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
604
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
605
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
606
+ supervisor_managed_agents_only: str = typer.Option(None, "--supervisor-managed-agents-only", help="If set to true, the API will return contact center enabled u"),
607
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specify whether to include array fields in the response. Thi"),
608
+ buddy_team_agents_only: str = typer.Option(None, "--buddy-team-agents-only", help="If set to true, returns only users who are part of buddy tea"),
609
+ user_in_queue: str = typer.Option(None, "--user-in-queue", help="Can be either assigned or unassigned. If passed, returns the"),
610
+ queue_id: str = typer.Option(None, "--queue-id", help="Contact Service Queue ID for which the list of assigned or u"),
611
+ include_ai_mapping_count: str = typer.Option(None, "--include-ai-mapping-count", help="If set to true, the API response will include the count of e"),
612
+ include_dynamic_skills_limit_reached: str = typer.Option(None, "--include-dynamic-skills-limit-reached", help="If true, includes whether each user has reached the dynamic"),
613
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
614
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
615
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
616
+ debug: bool = typer.Option(False, "--debug"),
617
+ ):
618
+ """List Users."""
619
+ api = get_api(debug=debug)
620
+ cc_base_url = get_cc_base_url()
621
+ orgid = get_cc_org_id(api.session)
622
+ url = f"{cc_base_url}/organization/{orgid}/v2/user"
623
+ params = {}
624
+ if filter_param is not None:
625
+ params["filter"] = filter_param
626
+ if attributes is not None:
627
+ params["attributes"] = attributes
628
+ if search is not None:
629
+ params["search"] = search
630
+ if page is not None:
631
+ params["page"] = page
632
+ if page_size is not None:
633
+ params["pageSize"] = page_size
634
+ if supervisor_managed_agents_only is not None:
635
+ params["supervisorManagedAgentsOnly"] = supervisor_managed_agents_only
636
+ if single_object_response is not None:
637
+ params["singleObjectResponse"] = single_object_response
638
+ if buddy_team_agents_only is not None:
639
+ params["buddyTeamAgentsOnly"] = buddy_team_agents_only
640
+ if user_in_queue is not None:
641
+ params["userInQueue"] = user_in_queue
642
+ if queue_id is not None:
643
+ params["queueId"] = queue_id
644
+ if include_ai_mapping_count is not None:
645
+ params["includeAIMappingCount"] = include_ai_mapping_count
646
+ if include_dynamic_skills_limit_reached is not None:
647
+ params["includeDynamicSkillsLimitReached"] = include_dynamic_skills_limit_reached
648
+ if limit > 0:
649
+ params["max"] = limit
650
+ if offset > 0:
651
+ params["start"] = offset
652
+ result = None
653
+ try:
654
+ result = api.session.rest_get(url, params=params)
655
+ except WebexError as e:
656
+ handle_rest_error(e)
657
+ result = result or []
658
+ items = result.get("data", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
659
+ if output == "json":
660
+ print_json(items)
661
+ else:
662
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
663
+
664
+
665
+
666
+ @app.command("show-by-ci-user-id-v2")
667
+ def show_by_ci_user_id_v2(
668
+ id: str = typer.Argument(help="id"),
669
+ include_user_profile: str = typer.Option(None, "--include-user-profile", help="Specifiy whether to include user profile data"),
670
+ include_names: str = typer.Option(None, "--include-names", help="Specifiy whether to include resource collection names"),
671
+ include_skill_details: str = typer.Option(None, "--include-skill-details", help="If set to true, the response includes skill information for"),
672
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
673
+ debug: bool = typer.Option(False, "--debug"),
674
+ ):
675
+ """Get specific User by CI User ID."""
676
+ api = get_api(debug=debug)
677
+ cc_base_url = get_cc_base_url()
678
+ orgid = get_cc_org_id(api.session)
679
+ url = f"{cc_base_url}/organization/{orgid}/v2/user/by-ci-user-id/{id}"
680
+ params = {}
681
+ if include_user_profile is not None:
682
+ params["includeUserProfile"] = include_user_profile
683
+ if include_names is not None:
684
+ params["includeNames"] = include_names
685
+ if include_skill_details is not None:
686
+ params["includeSkillDetails"] = include_skill_details
687
+ try:
688
+ result = api.session.rest_get(url, params=params)
689
+ except WebexError as e:
690
+ handle_rest_error(e)
691
+ if output == "json":
692
+ print_json(result)
693
+ else:
694
+ if isinstance(result, dict):
695
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
696
+ elif isinstance(result, list):
697
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
698
+ else:
699
+ print_json(result)
700
+
701
+