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,1083 @@
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-queue.")
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
+ channel_types: str = typer.Option(None, "--channel-types", help="[DEPRECATED] Channel type(s) allowed by the system.Separate"),
16
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
17
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
18
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
19
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specify whether to include array fields in the response. Thi"),
20
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
21
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
22
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
23
+ debug: bool = typer.Option(False, "--debug"),
24
+ ):
25
+ """List Contact Service Queues."""
26
+ api = get_api(debug=debug)
27
+ cc_base_url = get_cc_base_url()
28
+ orgid = get_cc_org_id(api.session)
29
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue"
30
+ params = {}
31
+ if filter_param is not None:
32
+ params["filter"] = filter_param
33
+ if channel_types is not None:
34
+ params["channelTypes"] = channel_types
35
+ if attributes is not None:
36
+ params["attributes"] = attributes
37
+ if page is not None:
38
+ params["page"] = page
39
+ if page_size is not None:
40
+ params["pageSize"] = page_size
41
+ if single_object_response is not None:
42
+ params["singleObjectResponse"] = single_object_response
43
+ if limit > 0:
44
+ params["max"] = limit
45
+ if offset > 0:
46
+ params["start"] = offset
47
+ result = None
48
+ try:
49
+ result = api.session.rest_get(url, params=params)
50
+ except WebexError as e:
51
+ handle_rest_error(e)
52
+ result = result or []
53
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
54
+ if output == "json":
55
+ print_json(items)
56
+ else:
57
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
58
+
59
+
60
+
61
+ @app.command("create")
62
+ def create(
63
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
64
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
65
+ debug: bool = typer.Option(False, "--debug"),
66
+ ):
67
+ """Bulk save Contact Service Queues\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
68
+ api = get_api(debug=debug)
69
+ cc_base_url = get_cc_base_url()
70
+ orgid = get_cc_org_id(api.session)
71
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/bulk"
72
+ if json_body:
73
+ body = json.loads(json_body)
74
+ else:
75
+ body = {}
76
+ try:
77
+ result = api.session.rest_post(url, json=body)
78
+ except WebexError as e:
79
+ handle_rest_error(e)
80
+ if output == "json":
81
+ print_json(result)
82
+ elif isinstance(result, dict) and "id" in result:
83
+ typer.echo(f"Created: {result['id']}")
84
+ elif not result or result == {}:
85
+ typer.echo("Created.")
86
+ else:
87
+ print_json(result)
88
+
89
+
90
+
91
+ @app.command("update")
92
+ def update(
93
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
94
+ debug: bool = typer.Option(False, "--debug"),
95
+ ):
96
+ """Bulk partial update Contact Service Queues\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
97
+ api = get_api(debug=debug)
98
+ cc_base_url = get_cc_base_url()
99
+ orgid = get_cc_org_id(api.session)
100
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/bulk"
101
+ if json_body:
102
+ body = json.loads(json_body)
103
+ else:
104
+ body = {}
105
+ try:
106
+ result = api.session.rest_patch(url, json=body)
107
+ except WebexError as e:
108
+ handle_rest_error(e)
109
+ typer.echo(f"Updated.")
110
+
111
+
112
+
113
+ @app.command("show")
114
+ def show(
115
+ id: str = typer.Argument(help="id"),
116
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
117
+ debug: bool = typer.Option(False, "--debug"),
118
+ ):
119
+ """List skill-based Contact Service Queues by skill profile ID (public)."""
120
+ api = get_api(debug=debug)
121
+ cc_base_url = get_cc_base_url()
122
+ orgid = get_cc_org_id(api.session)
123
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/by-skill-profile-id/{id}"
124
+ try:
125
+ result = api.session.rest_get(url)
126
+ except WebexError as e:
127
+ handle_rest_error(e)
128
+ if output == "json":
129
+ print_json(result)
130
+ else:
131
+ if isinstance(result, dict):
132
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
133
+ elif isinstance(result, list):
134
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
135
+ else:
136
+ print_json(result)
137
+
138
+
139
+
140
+ @app.command("create-delete-reference")
141
+ def create_delete_reference(
142
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
143
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
144
+ debug: bool = typer.Option(False, "--debug"),
145
+ ):
146
+ """Delete references from Contact Service Queues\n\nExample --json-body:\n '{"references":{}}'."""
147
+ api = get_api(debug=debug)
148
+ cc_base_url = get_cc_base_url()
149
+ orgid = get_cc_org_id(api.session)
150
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/delete-reference"
151
+ if json_body:
152
+ body = json.loads(json_body)
153
+ else:
154
+ body = {}
155
+ try:
156
+ result = api.session.rest_post(url, json=body)
157
+ except WebexError as e:
158
+ handle_rest_error(e)
159
+ if output == "json":
160
+ print_json(result)
161
+ elif isinstance(result, dict) and "id" in result:
162
+ typer.echo(f"Created: {result['id']}")
163
+ elif not result or result == {}:
164
+ typer.echo("Created.")
165
+ else:
166
+ print_json(result)
167
+
168
+
169
+
170
+ @app.command("create-fetch-by-dynamic-skills-and-skill-profile")
171
+ def create_fetch_by_dynamic_skills_and_skill_profile(
172
+ skill_profile_id: str = typer.Option(None, "--skill-profile-id", help="Unique identifier of the skill profile to look up queues for"),
173
+ user_id: str = typer.Option(None, "--user-id", help="Unique identifier of the user (agent) whose skill-based queu"),
174
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
175
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
176
+ debug: bool = typer.Option(False, "--debug"),
177
+ ):
178
+ """List skill-based Contact Service Queues by dynamic skills and skill profile\n\nExample --json-body:\n '{"skillProfileId":"...","dynamicSkills":[{"skillId":"...","textValue":"...","booleanValue":"...","proficiencyValue":"...","enumSkillValues":"..."}],"userId":"..."}'."""
179
+ api = get_api(debug=debug)
180
+ cc_base_url = get_cc_base_url()
181
+ orgid = get_cc_org_id(api.session)
182
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/fetch-by-dynamic-skills-and-skillProfile"
183
+ if json_body:
184
+ body = json.loads(json_body)
185
+ else:
186
+ body = {}
187
+ if skill_profile_id is not None:
188
+ body["skillProfileId"] = skill_profile_id
189
+ if user_id is not None:
190
+ body["userId"] = user_id
191
+ try:
192
+ result = api.session.rest_post(url, json=body)
193
+ except WebexError as e:
194
+ handle_rest_error(e)
195
+ if output == "json":
196
+ print_json(result)
197
+ elif isinstance(result, dict) and "id" in result:
198
+ typer.echo(f"Created: {result['id']}")
199
+ elif not result or result == {}:
200
+ typer.echo("Created.")
201
+ else:
202
+ print_json(result)
203
+
204
+
205
+
206
+ @app.command("create-fetch-by-user-id-skill-profile-id")
207
+ def create_fetch_by_user_id_skill_profile_id(
208
+ skill_profile_id: str = typer.Option(None, "--skill-profile-id", help="Unique identifier of the skill profile to look up queues for"),
209
+ user_id: str = typer.Option(None, "--user-id", help="Unique identifier of the user (agent) whose skill-based queu"),
210
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
211
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
212
+ debug: bool = typer.Option(False, "--debug"),
213
+ ):
214
+ """List skill-based Contact Service Queues by skill profile ID and user ID\n\nExample --json-body:\n '{"skillProfileId":"...","dynamicSkills":[{"skillId":"...","textValue":"...","booleanValue":"...","proficiencyValue":"...","enumSkillValues":"..."}],"userId":"..."}'."""
215
+ api = get_api(debug=debug)
216
+ cc_base_url = get_cc_base_url()
217
+ orgid = get_cc_org_id(api.session)
218
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/fetch-by-userId-skillProfileId"
219
+ if json_body:
220
+ body = json.loads(json_body)
221
+ else:
222
+ body = {}
223
+ if skill_profile_id is not None:
224
+ body["skillProfileId"] = skill_profile_id
225
+ if user_id is not None:
226
+ body["userId"] = user_id
227
+ try:
228
+ result = api.session.rest_post(url, json=body)
229
+ except WebexError as e:
230
+ handle_rest_error(e)
231
+ if output == "json":
232
+ print_json(result)
233
+ elif isinstance(result, dict) and "id" in result:
234
+ typer.echo(f"Created: {result['id']}")
235
+ elif not result or result == {}:
236
+ typer.echo("Created.")
237
+ else:
238
+ print_json(result)
239
+
240
+
241
+
242
+ @app.command("create-fetch-manually-assignable-queues")
243
+ def create_fetch_manually_assignable_queues(
244
+ agent_id: str = typer.Option(None, "--agent-id", help="Unique identifier of the agent (CI user ID) for whom manuall"),
245
+ team_id: str = typer.Option(None, "--team-id", help="Unique identifier of the team that the agent belongs to. Use"),
246
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
247
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
248
+ debug: bool = typer.Option(False, "--debug"),
249
+ ):
250
+ """List manually assignable Contact Service Queues."""
251
+ api = get_api(debug=debug)
252
+ cc_base_url = get_cc_base_url()
253
+ orgid = get_cc_org_id(api.session)
254
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/fetch-manually-assignable-queues"
255
+ if json_body:
256
+ body = json.loads(json_body)
257
+ else:
258
+ body = {}
259
+ if agent_id is not None:
260
+ body["agentId"] = agent_id
261
+ if team_id is not None:
262
+ body["teamId"] = team_id
263
+ try:
264
+ result = api.session.rest_post(url, json=body)
265
+ except WebexError as e:
266
+ handle_rest_error(e)
267
+ if output == "json":
268
+ print_json(result)
269
+ elif isinstance(result, dict) and "id" in result:
270
+ typer.echo(f"Created: {result['id']}")
271
+ elif not result or result == {}:
272
+ typer.echo("Created.")
273
+ else:
274
+ print_json(result)
275
+
276
+
277
+
278
+ @app.command("create-purge-inactive-entities")
279
+ def create_purge_inactive_entities(
280
+ next_start_id: str = typer.Option(None, "--next-start-id", help="This is the entity ID from which items for the next purge ba"),
281
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
282
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
283
+ debug: bool = typer.Option(False, "--debug"),
284
+ ):
285
+ """Purge inactive Contact Service Queues."""
286
+ api = get_api(debug=debug)
287
+ cc_base_url = get_cc_base_url()
288
+ orgid = get_cc_org_id(api.session)
289
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/purge-inactive-entities"
290
+ params = {}
291
+ if next_start_id is not None:
292
+ params["nextStartId"] = next_start_id
293
+ if json_body:
294
+ body = json.loads(json_body)
295
+ else:
296
+ body = {}
297
+ try:
298
+ result = api.session.rest_post(url, json=body, params=params)
299
+ except WebexError as e:
300
+ handle_rest_error(e)
301
+ if output == "json":
302
+ print_json(result)
303
+ elif isinstance(result, dict) and "id" in result:
304
+ typer.echo(f"Created: {result['id']}")
305
+ elif not result or result == {}:
306
+ typer.echo("Created.")
307
+ else:
308
+ print_json(result)
309
+
310
+
311
+
312
+ @app.command("show-contact-service-queue-organization")
313
+ def show_contact_service_queue_organization(
314
+ id: str = typer.Argument(help="id"),
315
+ agents_updated_info: str = typer.Option(None, "--agents-updated-info", help="If `true`, returns the user details who has last updated the"),
316
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
317
+ debug: bool = typer.Option(False, "--debug"),
318
+ ):
319
+ """Get specific Contact Service Queue by ID."""
320
+ api = get_api(debug=debug)
321
+ cc_base_url = get_cc_base_url()
322
+ orgid = get_cc_org_id(api.session)
323
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/{id}"
324
+ params = {}
325
+ if agents_updated_info is not None:
326
+ params["agentsUpdatedInfo"] = agents_updated_info
327
+ try:
328
+ result = api.session.rest_get(url, params=params)
329
+ except WebexError as e:
330
+ handle_rest_error(e)
331
+ if output == "json":
332
+ print_json(result)
333
+ else:
334
+ if isinstance(result, dict):
335
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
336
+ elif isinstance(result, list):
337
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
338
+ else:
339
+ print_json(result)
340
+
341
+
342
+
343
+ @app.command("delete")
344
+ def delete(
345
+ id: str = typer.Argument(help="id"),
346
+ force: bool = typer.Option(False, "--force", help="Skip confirmation"),
347
+ debug: bool = typer.Option(False, "--debug"),
348
+ ):
349
+ """Delete specific Contact Service Queue by ID."""
350
+ if not force:
351
+ typer.confirm(f"Delete {id}?", abort=True)
352
+ api = get_api(debug=debug)
353
+ cc_base_url = get_cc_base_url()
354
+ orgid = get_cc_org_id(api.session)
355
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/{id}"
356
+ try:
357
+ api.session.rest_delete(url)
358
+ except WebexError as e:
359
+ handle_rest_error(e)
360
+ typer.echo(f"Deleted: {id}")
361
+
362
+
363
+
364
+ @app.command("list-incoming-references")
365
+ def list_incoming_references(
366
+ id: str = typer.Argument(help="id"),
367
+ type_param: str = typer.Option(None, "--type", help="Entity type of the other entity that has a reference to this"),
368
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
369
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
370
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
371
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
372
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
373
+ debug: bool = typer.Option(False, "--debug"),
374
+ ):
375
+ """List references for a specific Contact Service Queue."""
376
+ api = get_api(debug=debug)
377
+ cc_base_url = get_cc_base_url()
378
+ orgid = get_cc_org_id(api.session)
379
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/{id}/incoming-references"
380
+ params = {}
381
+ if type_param is not None:
382
+ params["type"] = type_param
383
+ if page is not None:
384
+ params["page"] = page
385
+ if page_size is not None:
386
+ params["pageSize"] = page_size
387
+ if limit > 0:
388
+ params["max"] = limit
389
+ if offset > 0:
390
+ params["start"] = offset
391
+ result = None
392
+ try:
393
+ result = api.session.rest_get(url, params=params)
394
+ except WebexError as e:
395
+ handle_rest_error(e)
396
+ result = result or []
397
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
398
+ if output == "json":
399
+ print_json(items)
400
+ else:
401
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
402
+
403
+
404
+
405
+ @app.command("create-bulk")
406
+ def create_bulk(
407
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
408
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
409
+ debug: bool = typer.Option(False, "--debug"),
410
+ ):
411
+ """Bulk save Contact Service Queues\n\nExample --json-body:\n '{"items":[{"itemIdentifier":"...","item":"...","requestAction":"..."}]}'."""
412
+ api = get_api(debug=debug)
413
+ cc_base_url = get_cc_base_url()
414
+ orgid = get_cc_org_id(api.session)
415
+ url = f"{cc_base_url}/organization/{orgid}/contact-service-queue/v2/bulk"
416
+ if json_body:
417
+ body = json.loads(json_body)
418
+ else:
419
+ body = {}
420
+ try:
421
+ result = api.session.rest_post(url, json=body)
422
+ except WebexError as e:
423
+ handle_rest_error(e)
424
+ if output == "json":
425
+ print_json(result)
426
+ elif isinstance(result, dict) and "id" in result:
427
+ typer.echo(f"Created: {result['id']}")
428
+ elif not result or result == {}:
429
+ typer.echo("Created.")
430
+ else:
431
+ print_json(result)
432
+
433
+
434
+
435
+ @app.command("list-contact-service-queue-v2")
436
+ def list_contact_service_queue_v2(
437
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
438
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
439
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
440
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
441
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
442
+ desktop_profile_filter: str = typer.Option(None, "--desktop-profile-filter", help="If set to true, the API will return only the data that the u"),
443
+ provisioning_view: str = typer.Option(None, "--provisioning-view", help="If set to true, the API will only return data that the user"),
444
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specify whether to include array fields in the response. Thi"),
445
+ 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"),
446
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
447
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
448
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
449
+ debug: bool = typer.Option(False, "--debug"),
450
+ ):
451
+ """List Contact Service Queues."""
452
+ api = get_api(debug=debug)
453
+ cc_base_url = get_cc_base_url()
454
+ orgid = get_cc_org_id(api.session)
455
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue"
456
+ params = {}
457
+ if filter_param is not None:
458
+ params["filter"] = filter_param
459
+ if attributes is not None:
460
+ params["attributes"] = attributes
461
+ if search is not None:
462
+ params["search"] = search
463
+ if page is not None:
464
+ params["page"] = page
465
+ if page_size is not None:
466
+ params["pageSize"] = page_size
467
+ if desktop_profile_filter is not None:
468
+ params["desktopProfileFilter"] = desktop_profile_filter
469
+ if provisioning_view is not None:
470
+ params["provisioningView"] = provisioning_view
471
+ if single_object_response is not None:
472
+ params["singleObjectResponse"] = single_object_response
473
+ if include_ai_mapping_count is not None:
474
+ params["includeAIMappingCount"] = include_ai_mapping_count
475
+ if limit > 0:
476
+ params["max"] = limit
477
+ if offset > 0:
478
+ params["start"] = offset
479
+ result = None
480
+ try:
481
+ result = api.session.rest_get(url, params=params)
482
+ except WebexError as e:
483
+ handle_rest_error(e)
484
+ result = result or []
485
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
486
+ if output == "json":
487
+ print_json(items)
488
+ else:
489
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
490
+
491
+
492
+
493
+ @app.command("create-contact-service-queue")
494
+ def create_contact_service_queue(
495
+ organization_id: str = typer.Option(None, "--organization-id", help="ID of the contact center organization. This field is require"),
496
+ id_param: str = typer.Option(None, "--id", help="ID of this contact center resource. It should not be specifi"),
497
+ version: str = typer.Option(None, "--version", help="The version of this resource. For a newly created resource,"),
498
+ name: str = typer.Option(None, "--name", help="(required) Name of the Contact Service Queue"),
499
+ description: str = typer.Option(None, "--description", help="(Optional) A short description of the queue."),
500
+ queue_type: str = typer.Option(None, "--queue-type", help="(required) Choices: INBOUND, OUTBOUND"),
501
+ check_agent_availability: bool = typer.Option(None, "--check-agent-availability/--no-check-agent-availability", help="(required) This setting specifies whether the system can exclude teams"),
502
+ channel_type: str = typer.Option(None, "--channel-type", help="(required) Choices: TELEPHONY, EMAIL, FAX, CHAT, VIDEO, OTHERS, SOCIAL_CHANNEL, WORK_ITEM, CUSTOM_MESSAGING"),
503
+ social_channel_type: str = typer.Option(None, "--social-channel-type", help="Choices: MESSAGEBIRD, MESSENGER, WHATSAPP, APPLE_BUSINESS_CHAT, GOOGLE_BUSINESS_MESSAGES"),
504
+ service_level_threshold: str = typer.Option(None, "--service-level-threshold", help="(required) The time in seconds that a customer request can be in a queu"),
505
+ max_active_contacts: str = typer.Option(None, "--max-active-contacts", help="(required) The maximum number of simultaneous contacts allowed for this"),
506
+ max_time_in_queue: str = typer.Option(None, "--max-time-in-queue", help="(required) The time in seconds after which the system distributes the q"),
507
+ default_music_in_queue_media_file_id: str = typer.Option(None, "--default-music-in-queue-media-file-id", help="Identifies the default audio file which will be played for c"),
508
+ timezone: str = typer.Option(None, "--timezone", help="(Optional) Any routing strategy for this queue uses the time"),
509
+ active: bool = typer.Option(None, "--active/--no-active", help="(required) Specify whether the queue is active or not active"),
510
+ outdial_campaign_enabled: bool = typer.Option(None, "--outdial-campaign-enabled/--no-outdial-campaign-enabled", help="Should be specified only for outdial queues; if enabled, the"),
511
+ monitoring_permitted: bool = typer.Option(None, "--monitoring-permitted/--no-monitoring-permitted", help="Indicates whether or not monitoring is permitted. This sett"),
512
+ parking_permitted: bool = typer.Option(None, "--parking-permitted/--no-parking-permitted", help="Indicates whether or not parking is permitted. This setting"),
513
+ recording_permitted: bool = typer.Option(None, "--recording-permitted/--no-recording-permitted", help="Indicates whether or not recording is permitted. This setti"),
514
+ recording_all_calls_permitted: bool = typer.Option(None, "--recording-all-calls-permitted/--no-recording-all-calls-permitted", help="Indicates whether or not recording all calls is permitted."),
515
+ pause_recording_permitted: bool = typer.Option(None, "--pause-recording-permitted/--no-pause-recording-permitted", help="Indicates whether or not pausing the recording is permitted."),
516
+ recording_pause_duration: str = typer.Option(None, "--recording-pause-duration", help="The duration in seconds of pause in recording. This setting"),
517
+ control_flow_script_url: str = typer.Option(None, "--control-flow-script-url", help="The URL for the queue or the default control script of the q"),
518
+ ivr_requeue_url: str = typer.Option(None, "--ivr-requeue-url", help="This setting is available only for the Telephony channel typ"),
519
+ overflow_number: str = typer.Option(None, "--overflow-number", help="The destination phone number to which the system distributes"),
520
+ vendor_id: str = typer.Option(None, "--vendor-id", help="The unique alphanumeric string that maps this queue to the v"),
521
+ routing_type: str = typer.Option(None, "--routing-type", help="(required) Choices: LONGEST_AVAILABLE_AGENT, SKILLS_BASED, CIRCULAR, LINEAR"),
522
+ skill_based_routing_type: str = typer.Option(None, "--skill-based-routing-type", help="Choices: LONGEST_AVAILABLE_AGENT, BEST_AVAILABLE_AGENT"),
523
+ queue_routing_type: str = typer.Option(None, "--queue-routing-type", help="(required) Choices: TEAM_BASED, SKILL_BASED, AGENT_BASED"),
524
+ xsp_version: str = typer.Option(None, "--xsp-version", help="(Optional) Used to subscribe for recording events."),
525
+ subscription_id: str = typer.Option(None, "--subscription-id", help="(Optional) Used to subscribe for recording events."),
526
+ system_default: bool = typer.Option(None, "--system-default/--no-system-default", help="Indicates whether the created resource is system created or"),
527
+ manually_assignable: bool = typer.Option(None, "--manually-assignable/--no-manually-assignable", help="If `true`, the queue can be manually assigned."),
528
+ agents_last_updated_by_user_name: str = typer.Option(None, "--agents-last-updated-by-user-name", help="The name of the user who last modified the agents list."),
529
+ agents_last_updated_by_user_email_prefix: str = typer.Option(None, "--agents-last-updated-by-user-email-prefix", help="The email of the user who last modified the agents list."),
530
+ agents_last_updated_time: str = typer.Option(None, "--agents-last-updated-time", help="The date when the agents list was last modified (epoch times"),
531
+ queue_level_summaries_inclusion: str = typer.Option(None, "--queue-level-summaries-inclusion", help="Queue level summaries inclusion type. Used only when Queue i"),
532
+ queue_level_sentiment_analysis_inclusion: str = typer.Option(None, "--queue-level-sentiment-analysis-inclusion", help="Queue level sentiment analysis inclusion type. Used only whe"),
533
+ queue_level_predicted_wait_time_inclusion: str = typer.Option(None, "--queue-level-predicted-wait-time-inclusion", help="Queue level predicted wait time inclusion type. Used only wh"),
534
+ queue_level_auto_csat_inclusion: str = typer.Option(None, "--queue-level-auto-csat-inclusion", help="Queue level auto CSAT inclusion type. Used only when Queue i"),
535
+ queue_level_real_time_transcriptions_inclusion: str = typer.Option(None, "--queue-level-real-time-transcriptions-inclusion", help="Queue level real time transcriptions inclusion type. Used on"),
536
+ created_time: str = typer.Option(None, "--created-time", help="This is the created time of the entity."),
537
+ last_updated_time: str = typer.Option(None, "--last-updated-time", help="This is the updated time of the entity."),
538
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
539
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
540
+ debug: bool = typer.Option(False, "--debug"),
541
+ ):
542
+ """Create a new Contact Service Queue\n\nExample --json-body:\n '{"name":"...","queueType":"INBOUND","checkAgentAvailability":true,"channelType":"TELEPHONY","serviceLevelThreshold":0,"maxActiveContacts":0,"maxTimeInQueue":0,"active":true}'."""
543
+ api = get_api(debug=debug)
544
+ cc_base_url = get_cc_base_url()
545
+ orgid = get_cc_org_id(api.session)
546
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue"
547
+ if json_body:
548
+ body = json.loads(json_body)
549
+ else:
550
+ body = {}
551
+ if organization_id is not None:
552
+ body["organizationId"] = organization_id
553
+ if id_param is not None:
554
+ body["id"] = id_param
555
+ if version is not None:
556
+ body["version"] = version
557
+ if name is not None:
558
+ body["name"] = name
559
+ if description is not None:
560
+ body["description"] = description
561
+ if queue_type is not None:
562
+ body["queueType"] = queue_type
563
+ if check_agent_availability is not None:
564
+ body["checkAgentAvailability"] = check_agent_availability
565
+ if channel_type is not None:
566
+ body["channelType"] = channel_type
567
+ if social_channel_type is not None:
568
+ body["socialChannelType"] = social_channel_type
569
+ if service_level_threshold is not None:
570
+ body["serviceLevelThreshold"] = service_level_threshold
571
+ if max_active_contacts is not None:
572
+ body["maxActiveContacts"] = max_active_contacts
573
+ if max_time_in_queue is not None:
574
+ body["maxTimeInQueue"] = max_time_in_queue
575
+ if default_music_in_queue_media_file_id is not None:
576
+ body["defaultMusicInQueueMediaFileId"] = default_music_in_queue_media_file_id
577
+ if timezone is not None:
578
+ body["timezone"] = timezone
579
+ if active is not None:
580
+ body["active"] = active
581
+ if outdial_campaign_enabled is not None:
582
+ body["outdialCampaignEnabled"] = outdial_campaign_enabled
583
+ if monitoring_permitted is not None:
584
+ body["monitoringPermitted"] = monitoring_permitted
585
+ if parking_permitted is not None:
586
+ body["parkingPermitted"] = parking_permitted
587
+ if recording_permitted is not None:
588
+ body["recordingPermitted"] = recording_permitted
589
+ if recording_all_calls_permitted is not None:
590
+ body["recordingAllCallsPermitted"] = recording_all_calls_permitted
591
+ if pause_recording_permitted is not None:
592
+ body["pauseRecordingPermitted"] = pause_recording_permitted
593
+ if recording_pause_duration is not None:
594
+ body["recordingPauseDuration"] = recording_pause_duration
595
+ if control_flow_script_url is not None:
596
+ body["controlFlowScriptUrl"] = control_flow_script_url
597
+ if ivr_requeue_url is not None:
598
+ body["ivrRequeueUrl"] = ivr_requeue_url
599
+ if overflow_number is not None:
600
+ body["overflowNumber"] = overflow_number
601
+ if vendor_id is not None:
602
+ body["vendorId"] = vendor_id
603
+ if routing_type is not None:
604
+ body["routingType"] = routing_type
605
+ if skill_based_routing_type is not None:
606
+ body["skillBasedRoutingType"] = skill_based_routing_type
607
+ if queue_routing_type is not None:
608
+ body["queueRoutingType"] = queue_routing_type
609
+ if xsp_version is not None:
610
+ body["xspVersion"] = xsp_version
611
+ if subscription_id is not None:
612
+ body["subscriptionId"] = subscription_id
613
+ if system_default is not None:
614
+ body["systemDefault"] = system_default
615
+ if manually_assignable is not None:
616
+ body["manuallyAssignable"] = manually_assignable
617
+ if agents_last_updated_by_user_name is not None:
618
+ body["agentsLastUpdatedByUserName"] = agents_last_updated_by_user_name
619
+ if agents_last_updated_by_user_email_prefix is not None:
620
+ body["agentsLastUpdatedByUserEmailPrefix"] = agents_last_updated_by_user_email_prefix
621
+ if agents_last_updated_time is not None:
622
+ body["agentsLastUpdatedTime"] = agents_last_updated_time
623
+ if queue_level_summaries_inclusion is not None:
624
+ body["queueLevelSummariesInclusion"] = queue_level_summaries_inclusion
625
+ if queue_level_sentiment_analysis_inclusion is not None:
626
+ body["queueLevelSentimentAnalysisInclusion"] = queue_level_sentiment_analysis_inclusion
627
+ if queue_level_predicted_wait_time_inclusion is not None:
628
+ body["queueLevelPredictedWaitTimeInclusion"] = queue_level_predicted_wait_time_inclusion
629
+ if queue_level_auto_csat_inclusion is not None:
630
+ body["queueLevelAutoCsatInclusion"] = queue_level_auto_csat_inclusion
631
+ if queue_level_real_time_transcriptions_inclusion is not None:
632
+ body["queueLevelRealTimeTranscriptionsInclusion"] = queue_level_real_time_transcriptions_inclusion
633
+ if created_time is not None:
634
+ body["createdTime"] = created_time
635
+ if last_updated_time is not None:
636
+ body["lastUpdatedTime"] = last_updated_time
637
+ _missing = [f for f in ['name', 'queueType', 'checkAgentAvailability', 'channelType', 'serviceLevelThreshold', 'maxActiveContacts', 'maxTimeInQueue', 'active', 'routingType', 'queueRoutingType'] if f not in body or body[f] is None]
638
+ if _missing:
639
+ typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
640
+ raise typer.Exit(1)
641
+ try:
642
+ result = api.session.rest_post(url, json=body)
643
+ except WebexError as e:
644
+ handle_rest_error(e)
645
+ if output == "json":
646
+ print_json(result)
647
+ elif isinstance(result, dict) and "id" in result:
648
+ typer.echo(f"Created: {result['id']}")
649
+ elif not result or result == {}:
650
+ typer.echo("Created.")
651
+ else:
652
+ print_json(result)
653
+
654
+
655
+
656
+ @app.command("list-agent-based-queues")
657
+ def list_agent_based_queues(
658
+ userid: str = typer.Argument(help="userid"),
659
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
660
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
661
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
662
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
663
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
664
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
665
+ debug: bool = typer.Option(False, "--debug"),
666
+ ):
667
+ """List agent-based Contact Service Queues by user ID."""
668
+ api = get_api(debug=debug)
669
+ cc_base_url = get_cc_base_url()
670
+ orgid = get_cc_org_id(api.session)
671
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/by-user-id/{userid}/agent-based-queues"
672
+ params = {}
673
+ if search is not None:
674
+ params["search"] = search
675
+ if page is not None:
676
+ params["page"] = page
677
+ if page_size is not None:
678
+ params["pageSize"] = page_size
679
+ if limit > 0:
680
+ params["max"] = limit
681
+ if offset > 0:
682
+ params["start"] = offset
683
+ result = None
684
+ try:
685
+ result = api.session.rest_get(url, params=params)
686
+ except WebexError as e:
687
+ handle_rest_error(e)
688
+ result = result or []
689
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
690
+ if output == "json":
691
+ print_json(items)
692
+ else:
693
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
694
+
695
+
696
+
697
+ @app.command("list-skill-based-queues")
698
+ def list_skill_based_queues(
699
+ userid: str = typer.Argument(help="userid"),
700
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
701
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
702
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
703
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
704
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
705
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
706
+ debug: bool = typer.Option(False, "--debug"),
707
+ ):
708
+ """List skill-based Contact Service Queues by user ID."""
709
+ api = get_api(debug=debug)
710
+ cc_base_url = get_cc_base_url()
711
+ orgid = get_cc_org_id(api.session)
712
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/by-user-id/{userid}/skill-based-queues"
713
+ params = {}
714
+ if search is not None:
715
+ params["search"] = search
716
+ if page is not None:
717
+ params["page"] = page
718
+ if page_size is not None:
719
+ params["pageSize"] = page_size
720
+ if limit > 0:
721
+ params["max"] = limit
722
+ if offset > 0:
723
+ params["start"] = offset
724
+ result = None
725
+ try:
726
+ result = api.session.rest_get(url, params=params)
727
+ except WebexError as e:
728
+ handle_rest_error(e)
729
+ result = result or []
730
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
731
+ if output == "json":
732
+ print_json(items)
733
+ else:
734
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
735
+
736
+
737
+
738
+ @app.command("list-team-based-queues")
739
+ def list_team_based_queues(
740
+ userid: str = typer.Argument(help="userid"),
741
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
742
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
743
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
744
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
745
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
746
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
747
+ debug: bool = typer.Option(False, "--debug"),
748
+ ):
749
+ """List team-based Contact Service Queues by user ID."""
750
+ api = get_api(debug=debug)
751
+ cc_base_url = get_cc_base_url()
752
+ orgid = get_cc_org_id(api.session)
753
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/by-user-id/{userid}/team-based-queues"
754
+ params = {}
755
+ if search is not None:
756
+ params["search"] = search
757
+ if page is not None:
758
+ params["page"] = page
759
+ if page_size is not None:
760
+ params["pageSize"] = page_size
761
+ if limit > 0:
762
+ params["max"] = limit
763
+ if offset > 0:
764
+ params["start"] = offset
765
+ result = None
766
+ try:
767
+ result = api.session.rest_get(url, params=params)
768
+ except WebexError as e:
769
+ handle_rest_error(e)
770
+ result = result or []
771
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
772
+ if output == "json":
773
+ print_json(items)
774
+ else:
775
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
776
+
777
+
778
+
779
+ @app.command("create-fetch-by-grouped-assistant-skill")
780
+ def create_fetch_by_grouped_assistant_skill(
781
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
782
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
783
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
784
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
785
+ debug: bool = typer.Option(False, "--debug"),
786
+ ):
787
+ """List queue mapping summary grouped by Assistant Skill\n\nExample --json-body:\n '{"assistantSkillIds":["..."]}'."""
788
+ api = get_api(debug=debug)
789
+ cc_base_url = get_cc_base_url()
790
+ orgid = get_cc_org_id(api.session)
791
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/fetch-by-grouped-assistant-skill"
792
+ params = {}
793
+ if page is not None:
794
+ params["page"] = page
795
+ if page_size is not None:
796
+ params["pageSize"] = page_size
797
+ if json_body:
798
+ body = json.loads(json_body)
799
+ else:
800
+ body = {}
801
+ try:
802
+ result = api.session.rest_post(url, json=body, params=params)
803
+ except WebexError as e:
804
+ handle_rest_error(e)
805
+ if output == "json":
806
+ print_json(result)
807
+ elif isinstance(result, dict) and "id" in result:
808
+ typer.echo(f"Created: {result['id']}")
809
+ elif not result or result == {}:
810
+ typer.echo("Created.")
811
+ else:
812
+ print_json(result)
813
+
814
+
815
+
816
+ @app.command("show-contact-service-queue-v2")
817
+ def show_contact_service_queue_v2(
818
+ id: str = typer.Argument(help="id"),
819
+ agents_updated_info: str = typer.Option(None, "--agents-updated-info", help="If `true`, returns the user details who has last updated the"),
820
+ output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
821
+ debug: bool = typer.Option(False, "--debug"),
822
+ ):
823
+ """Get specific Contact Service Queue by ID."""
824
+ api = get_api(debug=debug)
825
+ cc_base_url = get_cc_base_url()
826
+ orgid = get_cc_org_id(api.session)
827
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/{id}"
828
+ params = {}
829
+ if agents_updated_info is not None:
830
+ params["agentsUpdatedInfo"] = agents_updated_info
831
+ try:
832
+ result = api.session.rest_get(url, params=params)
833
+ except WebexError as e:
834
+ handle_rest_error(e)
835
+ if output == "json":
836
+ print_json(result)
837
+ else:
838
+ if isinstance(result, dict):
839
+ print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
840
+ elif isinstance(result, list):
841
+ print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
842
+ else:
843
+ print_json(result)
844
+
845
+
846
+
847
+ @app.command("update-contact-service-queue")
848
+ def update_contact_service_queue(
849
+ id: str = typer.Argument(help="id"),
850
+ organization_id: str = typer.Option(None, "--organization-id", help="ID of the contact center organization. This field is require"),
851
+ id_param: str = typer.Option(None, "--id", help="ID of this contact center resource. It should not be specifi"),
852
+ version: str = typer.Option(None, "--version", help="The version of this resource. For a newly created resource,"),
853
+ name: str = typer.Option(None, "--name", help="Name of the Contact Service Queue"),
854
+ description: str = typer.Option(None, "--description", help="(Optional) A short description of the queue."),
855
+ queue_type: str = typer.Option(None, "--queue-type", help="Choices: INBOUND, OUTBOUND"),
856
+ check_agent_availability: bool = typer.Option(None, "--check-agent-availability/--no-check-agent-availability", help="This setting specifies whether the system can exclude teams"),
857
+ channel_type: str = typer.Option(None, "--channel-type", help="Choices: TELEPHONY, EMAIL, FAX, CHAT, VIDEO, OTHERS, SOCIAL_CHANNEL, WORK_ITEM, CUSTOM_MESSAGING"),
858
+ social_channel_type: str = typer.Option(None, "--social-channel-type", help="Choices: MESSAGEBIRD, MESSENGER, WHATSAPP, APPLE_BUSINESS_CHAT, GOOGLE_BUSINESS_MESSAGES"),
859
+ service_level_threshold: str = typer.Option(None, "--service-level-threshold", help="The time in seconds that a customer request can be in a queu"),
860
+ max_active_contacts: str = typer.Option(None, "--max-active-contacts", help="The maximum number of simultaneous contacts allowed for this"),
861
+ max_time_in_queue: str = typer.Option(None, "--max-time-in-queue", help="The time in seconds after which the system distributes the q"),
862
+ default_music_in_queue_media_file_id: str = typer.Option(None, "--default-music-in-queue-media-file-id", help="Identifies the default audio file which will be played for c"),
863
+ timezone: str = typer.Option(None, "--timezone", help="(Optional) Any routing strategy for this queue uses the time"),
864
+ active: bool = typer.Option(None, "--active/--no-active", help="Specify whether the queue is active or not active"),
865
+ outdial_campaign_enabled: bool = typer.Option(None, "--outdial-campaign-enabled/--no-outdial-campaign-enabled", help="Should be specified only for outdial queues; if enabled, the"),
866
+ monitoring_permitted: bool = typer.Option(None, "--monitoring-permitted/--no-monitoring-permitted", help="Indicates whether or not monitoring is permitted. This sett"),
867
+ parking_permitted: bool = typer.Option(None, "--parking-permitted/--no-parking-permitted", help="Indicates whether or not parking is permitted. This setting"),
868
+ recording_permitted: bool = typer.Option(None, "--recording-permitted/--no-recording-permitted", help="Indicates whether or not recording is permitted. This setti"),
869
+ recording_all_calls_permitted: bool = typer.Option(None, "--recording-all-calls-permitted/--no-recording-all-calls-permitted", help="Indicates whether or not recording all calls is permitted."),
870
+ pause_recording_permitted: bool = typer.Option(None, "--pause-recording-permitted/--no-pause-recording-permitted", help="Indicates whether or not pausing the recording is permitted."),
871
+ recording_pause_duration: str = typer.Option(None, "--recording-pause-duration", help="The duration in seconds of pause in recording. This setting"),
872
+ control_flow_script_url: str = typer.Option(None, "--control-flow-script-url", help="The URL for the queue or the default control script of the q"),
873
+ ivr_requeue_url: str = typer.Option(None, "--ivr-requeue-url", help="This setting is available only for the Telephony channel typ"),
874
+ overflow_number: str = typer.Option(None, "--overflow-number", help="The destination phone number to which the system distributes"),
875
+ vendor_id: str = typer.Option(None, "--vendor-id", help="The unique alphanumeric string that maps this queue to the v"),
876
+ routing_type: str = typer.Option(None, "--routing-type", help="Choices: LONGEST_AVAILABLE_AGENT, SKILLS_BASED, CIRCULAR, LINEAR"),
877
+ skill_based_routing_type: str = typer.Option(None, "--skill-based-routing-type", help="Choices: LONGEST_AVAILABLE_AGENT, BEST_AVAILABLE_AGENT"),
878
+ queue_routing_type: str = typer.Option(None, "--queue-routing-type", help="Choices: TEAM_BASED, SKILL_BASED, AGENT_BASED"),
879
+ xsp_version: str = typer.Option(None, "--xsp-version", help="(Optional) Used to subscribe for recording events."),
880
+ subscription_id: str = typer.Option(None, "--subscription-id", help="(Optional) Used to subscribe for recording events."),
881
+ system_default: bool = typer.Option(None, "--system-default/--no-system-default", help="Indicates whether the created resource is system created or"),
882
+ manually_assignable: bool = typer.Option(None, "--manually-assignable/--no-manually-assignable", help="If `true`, the queue can be manually assigned."),
883
+ agents_last_updated_by_user_name: str = typer.Option(None, "--agents-last-updated-by-user-name", help="The name of the user who last modified the agents list."),
884
+ agents_last_updated_by_user_email_prefix: str = typer.Option(None, "--agents-last-updated-by-user-email-prefix", help="The email of the user who last modified the agents list."),
885
+ agents_last_updated_time: str = typer.Option(None, "--agents-last-updated-time", help="The date when the agents list was last modified (epoch times"),
886
+ queue_level_summaries_inclusion: str = typer.Option(None, "--queue-level-summaries-inclusion", help="Queue level summaries inclusion type. Used only when Queue i"),
887
+ queue_level_sentiment_analysis_inclusion: str = typer.Option(None, "--queue-level-sentiment-analysis-inclusion", help="Queue level sentiment analysis inclusion type. Used only whe"),
888
+ queue_level_predicted_wait_time_inclusion: str = typer.Option(None, "--queue-level-predicted-wait-time-inclusion", help="Queue level predicted wait time inclusion type. Used only wh"),
889
+ queue_level_auto_csat_inclusion: str = typer.Option(None, "--queue-level-auto-csat-inclusion", help="Queue level auto CSAT inclusion type. Used only when Queue i"),
890
+ queue_level_real_time_transcriptions_inclusion: str = typer.Option(None, "--queue-level-real-time-transcriptions-inclusion", help="Queue level real time transcriptions inclusion type. Used on"),
891
+ created_time: str = typer.Option(None, "--created-time", help="This is the created time of the entity."),
892
+ last_updated_time: str = typer.Option(None, "--last-updated-time", help="This is the updated time of the entity."),
893
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
894
+ debug: bool = typer.Option(False, "--debug"),
895
+ ):
896
+ """Update specific Contact Service Queue by ID\n\nExample --json-body:\n '{"name":"...","queueType":"INBOUND","checkAgentAvailability":true,"channelType":"TELEPHONY","serviceLevelThreshold":0,"maxActiveContacts":0,"maxTimeInQueue":0,"active":true}'."""
897
+ api = get_api(debug=debug)
898
+ cc_base_url = get_cc_base_url()
899
+ orgid = get_cc_org_id(api.session)
900
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/{id}"
901
+ if json_body:
902
+ body = json.loads(json_body)
903
+ else:
904
+ body = {}
905
+ if organization_id is not None:
906
+ body["organizationId"] = organization_id
907
+ if id_param is not None:
908
+ body["id"] = id_param
909
+ if version is not None:
910
+ body["version"] = version
911
+ if name is not None:
912
+ body["name"] = name
913
+ if description is not None:
914
+ body["description"] = description
915
+ if queue_type is not None:
916
+ body["queueType"] = queue_type
917
+ if check_agent_availability is not None:
918
+ body["checkAgentAvailability"] = check_agent_availability
919
+ if channel_type is not None:
920
+ body["channelType"] = channel_type
921
+ if social_channel_type is not None:
922
+ body["socialChannelType"] = social_channel_type
923
+ if service_level_threshold is not None:
924
+ body["serviceLevelThreshold"] = service_level_threshold
925
+ if max_active_contacts is not None:
926
+ body["maxActiveContacts"] = max_active_contacts
927
+ if max_time_in_queue is not None:
928
+ body["maxTimeInQueue"] = max_time_in_queue
929
+ if default_music_in_queue_media_file_id is not None:
930
+ body["defaultMusicInQueueMediaFileId"] = default_music_in_queue_media_file_id
931
+ if timezone is not None:
932
+ body["timezone"] = timezone
933
+ if active is not None:
934
+ body["active"] = active
935
+ if outdial_campaign_enabled is not None:
936
+ body["outdialCampaignEnabled"] = outdial_campaign_enabled
937
+ if monitoring_permitted is not None:
938
+ body["monitoringPermitted"] = monitoring_permitted
939
+ if parking_permitted is not None:
940
+ body["parkingPermitted"] = parking_permitted
941
+ if recording_permitted is not None:
942
+ body["recordingPermitted"] = recording_permitted
943
+ if recording_all_calls_permitted is not None:
944
+ body["recordingAllCallsPermitted"] = recording_all_calls_permitted
945
+ if pause_recording_permitted is not None:
946
+ body["pauseRecordingPermitted"] = pause_recording_permitted
947
+ if recording_pause_duration is not None:
948
+ body["recordingPauseDuration"] = recording_pause_duration
949
+ if control_flow_script_url is not None:
950
+ body["controlFlowScriptUrl"] = control_flow_script_url
951
+ if ivr_requeue_url is not None:
952
+ body["ivrRequeueUrl"] = ivr_requeue_url
953
+ if overflow_number is not None:
954
+ body["overflowNumber"] = overflow_number
955
+ if vendor_id is not None:
956
+ body["vendorId"] = vendor_id
957
+ if routing_type is not None:
958
+ body["routingType"] = routing_type
959
+ if skill_based_routing_type is not None:
960
+ body["skillBasedRoutingType"] = skill_based_routing_type
961
+ if queue_routing_type is not None:
962
+ body["queueRoutingType"] = queue_routing_type
963
+ if xsp_version is not None:
964
+ body["xspVersion"] = xsp_version
965
+ if subscription_id is not None:
966
+ body["subscriptionId"] = subscription_id
967
+ if system_default is not None:
968
+ body["systemDefault"] = system_default
969
+ if manually_assignable is not None:
970
+ body["manuallyAssignable"] = manually_assignable
971
+ if agents_last_updated_by_user_name is not None:
972
+ body["agentsLastUpdatedByUserName"] = agents_last_updated_by_user_name
973
+ if agents_last_updated_by_user_email_prefix is not None:
974
+ body["agentsLastUpdatedByUserEmailPrefix"] = agents_last_updated_by_user_email_prefix
975
+ if agents_last_updated_time is not None:
976
+ body["agentsLastUpdatedTime"] = agents_last_updated_time
977
+ if queue_level_summaries_inclusion is not None:
978
+ body["queueLevelSummariesInclusion"] = queue_level_summaries_inclusion
979
+ if queue_level_sentiment_analysis_inclusion is not None:
980
+ body["queueLevelSentimentAnalysisInclusion"] = queue_level_sentiment_analysis_inclusion
981
+ if queue_level_predicted_wait_time_inclusion is not None:
982
+ body["queueLevelPredictedWaitTimeInclusion"] = queue_level_predicted_wait_time_inclusion
983
+ if queue_level_auto_csat_inclusion is not None:
984
+ body["queueLevelAutoCsatInclusion"] = queue_level_auto_csat_inclusion
985
+ if queue_level_real_time_transcriptions_inclusion is not None:
986
+ body["queueLevelRealTimeTranscriptionsInclusion"] = queue_level_real_time_transcriptions_inclusion
987
+ if created_time is not None:
988
+ body["createdTime"] = created_time
989
+ if last_updated_time is not None:
990
+ body["lastUpdatedTime"] = last_updated_time
991
+ try:
992
+ result = api.session.rest_put(url, json=body)
993
+ except WebexError as e:
994
+ handle_rest_error(e)
995
+ typer.echo(f"Updated.")
996
+
997
+
998
+
999
+ @app.command("create-reassign-agents")
1000
+ def create_reassign_agents(
1001
+ id: str = typer.Argument(help="id"),
1002
+ json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
1003
+ output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
1004
+ debug: bool = typer.Option(False, "--debug"),
1005
+ ):
1006
+ """Add or remove agents/users to/from an agent based queue\n\nExample --json-body:\n '{"add":["..."],"remove":["..."]}'."""
1007
+ api = get_api(debug=debug)
1008
+ cc_base_url = get_cc_base_url()
1009
+ orgid = get_cc_org_id(api.session)
1010
+ url = f"{cc_base_url}/organization/{orgid}/v2/contact-service-queue/{id}/reassign-agents"
1011
+ if json_body:
1012
+ body = json.loads(json_body)
1013
+ else:
1014
+ body = {}
1015
+ try:
1016
+ result = api.session.rest_post(url, json=body)
1017
+ except WebexError as e:
1018
+ handle_rest_error(e)
1019
+ if output == "json":
1020
+ print_json(result)
1021
+ elif isinstance(result, dict) and "id" in result:
1022
+ typer.echo(f"Created: {result['id']}")
1023
+ elif not result or result == {}:
1024
+ typer.echo("Created.")
1025
+ else:
1026
+ print_json(result)
1027
+
1028
+
1029
+
1030
+ @app.command("list-contact-service-queue-v3")
1031
+ def list_contact_service_queue_v3(
1032
+ filter_param: str = typer.Option(None, "--filter", help="Specify a filter based on which the results will be fetched."),
1033
+ attributes: str = typer.Option(None, "--attributes", help="Specify the attributes to be returned. By default, all attri"),
1034
+ search: str = typer.Option(None, "--search", help="Filter data based on the search keyword.Supported search col"),
1035
+ page: str = typer.Option(None, "--page", help="Defines the number of displayed page. The page number starts"),
1036
+ page_size: str = typer.Option(None, "--page-size", help="Defines the number of items to be displayed on a page. If th"),
1037
+ desktop_profile_filter: str = typer.Option(None, "--desktop-profile-filter", help="If set to true, the API will return only the data that the u"),
1038
+ provisioning_view: str = typer.Option(None, "--provisioning-view", help="If set to true, the API will only return data that the user"),
1039
+ single_object_response: str = typer.Option(None, "--single-object-response", help="Specify whether to include array fields in the response. Thi"),
1040
+ output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
1041
+ limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
1042
+ offset: int = typer.Option(0, "--offset", help="Start offset"),
1043
+ debug: bool = typer.Option(False, "--debug"),
1044
+ ):
1045
+ """List Contact Service Queues."""
1046
+ api = get_api(debug=debug)
1047
+ cc_base_url = get_cc_base_url()
1048
+ orgid = get_cc_org_id(api.session)
1049
+ url = f"{cc_base_url}/organization/{orgid}/v3/contact-service-queue"
1050
+ params = {}
1051
+ if filter_param is not None:
1052
+ params["filter"] = filter_param
1053
+ if attributes is not None:
1054
+ params["attributes"] = attributes
1055
+ if search is not None:
1056
+ params["search"] = search
1057
+ if page is not None:
1058
+ params["page"] = page
1059
+ if page_size is not None:
1060
+ params["pageSize"] = page_size
1061
+ if desktop_profile_filter is not None:
1062
+ params["desktopProfileFilter"] = desktop_profile_filter
1063
+ if provisioning_view is not None:
1064
+ params["provisioningView"] = provisioning_view
1065
+ if single_object_response is not None:
1066
+ params["singleObjectResponse"] = single_object_response
1067
+ if limit > 0:
1068
+ params["max"] = limit
1069
+ if offset > 0:
1070
+ params["start"] = offset
1071
+ result = None
1072
+ try:
1073
+ result = api.session.rest_get(url, params=params)
1074
+ except WebexError as e:
1075
+ handle_rest_error(e)
1076
+ result = result or []
1077
+ items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
1078
+ if output == "json":
1079
+ print_json(items)
1080
+ else:
1081
+ print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
1082
+
1083
+