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.
- wxcli/__init__.py +4 -0
- wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
- wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
- wxcli/_playbook/.claude/rules/cleanup.md +29 -0
- wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
- wxcli/_playbook/.claude/rules/org-health.md +14 -0
- wxcli/_playbook/.claude/settings.json +8 -0
- wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
- wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
- wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
- wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
- wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
- wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
- wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
- wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
- wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
- wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
- wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
- wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
- wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
- wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
- wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
- wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
- wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
- wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
- wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
- wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
- wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
- wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
- wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
- wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
- wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
- wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
- wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
- wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
- wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
- wxcli/_playbook/CLAUDE.md +373 -0
- wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
- wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
- wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
- wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
- wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
- wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
- wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
- wxcli/_playbook/docs/reference/admin-partner.md +357 -0
- wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
- wxcli/_playbook/docs/reference/authentication.md +965 -0
- wxcli/_playbook/docs/reference/call-control.md +1205 -0
- wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
- wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
- wxcli/_playbook/docs/reference/call-routing.md +2304 -0
- wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
- wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
- wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
- wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
- wxcli/_playbook/docs/reference/devices-core.md +1869 -0
- wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
- wxcli/_playbook/docs/reference/devices-platform.md +467 -0
- wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
- wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
- wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
- wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
- wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
- wxcli/_playbook/docs/reference/meetings-content.md +473 -0
- wxcli/_playbook/docs/reference/meetings-core.md +903 -0
- wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
- wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
- wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
- wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
- wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
- wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
- wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
- wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
- wxcli/_playbook/docs/reference/provisioning.md +1366 -0
- wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
- wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
- wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
- wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
- wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
- wxcli/_version.py +24 -0
- wxcli/auth.py +137 -0
- wxcli/commands/__init__.py +0 -0
- wxcli/commands/_registry.py +181 -0
- wxcli/commands/activation_email.py +103 -0
- wxcli/commands/admin_recordings.py +585 -0
- wxcli/commands/analytics.py +105 -0
- wxcli/commands/announcement_playlists.py +219 -0
- wxcli/commands/announcements.py +519 -0
- wxcli/commands/archive_users.py +36 -0
- wxcli/commands/attachment_actions.py +60 -0
- wxcli/commands/audit_events.py +83 -0
- wxcli/commands/authorizations.py +113 -0
- wxcli/commands/auto_attendant.py +642 -0
- wxcli/commands/broadworks_billing_reports.py +126 -0
- wxcli/commands/broadworks_enterprises.py +160 -0
- wxcli/commands/broadworks_subscribers.py +319 -0
- wxcli/commands/broadworks_workspaces.py +108 -0
- wxcli/commands/call_controls.py +1304 -0
- wxcli/commands/call_park.py +494 -0
- wxcli/commands/call_pickup.py +229 -0
- wxcli/commands/call_queue.py +1878 -0
- wxcli/commands/call_recording.py +707 -0
- wxcli/commands/call_routing.py +1610 -0
- wxcli/commands/call_settings_for_me_phase_5.py +212 -0
- wxcli/commands/caller_reputation.py +169 -0
- wxcli/commands/calling_service.py +305 -0
- wxcli/commands/cc_address_book.py +770 -0
- wxcli/commands/cc_agent_greetings.py +242 -0
- wxcli/commands/cc_agent_summaries.py +39 -0
- wxcli/commands/cc_agent_wellbeing.py +216 -0
- wxcli/commands/cc_agents.py +425 -0
- wxcli/commands/cc_ai_assistant.py +55 -0
- wxcli/commands/cc_ai_feature.py +294 -0
- wxcli/commands/cc_audio_files.py +149 -0
- wxcli/commands/cc_auto_csat.py +311 -0
- wxcli/commands/cc_aux_code.py +458 -0
- wxcli/commands/cc_business_hour.py +353 -0
- wxcli/commands/cc_call_monitoring.py +228 -0
- wxcli/commands/cc_callbacks.py +194 -0
- wxcli/commands/cc_campaign.py +212 -0
- wxcli/commands/cc_captures.py +39 -0
- wxcli/commands/cc_contact_list.py +169 -0
- wxcli/commands/cc_contact_number.py +295 -0
- wxcli/commands/cc_data_sources.py +235 -0
- wxcli/commands/cc_desktop_layout.py +380 -0
- wxcli/commands/cc_desktop_profile.py +322 -0
- wxcli/commands/cc_dial_number.py +511 -0
- wxcli/commands/cc_dial_plan.py +347 -0
- wxcli/commands/cc_dnc.py +101 -0
- wxcli/commands/cc_entry_point.py +545 -0
- wxcli/commands/cc_ewt.py +51 -0
- wxcli/commands/cc_flow.py +477 -0
- wxcli/commands/cc_global_vars.py +430 -0
- wxcli/commands/cc_holiday_list.py +335 -0
- wxcli/commands/cc_journey.py +1261 -0
- wxcli/commands/cc_legacy_flows.py +49 -0
- wxcli/commands/cc_multimedia_profile.py +436 -0
- wxcli/commands/cc_notification.py +51 -0
- wxcli/commands/cc_outdial_ani.py +604 -0
- wxcli/commands/cc_overrides.py +341 -0
- wxcli/commands/cc_queue.py +1083 -0
- wxcli/commands/cc_queue_stats.py +55 -0
- wxcli/commands/cc_realtime.py +51 -0
- wxcli/commands/cc_resource_collection.py +312 -0
- wxcli/commands/cc_search.py +46 -0
- wxcli/commands/cc_site.py +400 -0
- wxcli/commands/cc_skill.py +350 -0
- wxcli/commands/cc_skill_profile.py +289 -0
- wxcli/commands/cc_subscriptions.py +426 -0
- wxcli/commands/cc_summaries.py +130 -0
- wxcli/commands/cc_tasks.py +844 -0
- wxcli/commands/cc_team.py +325 -0
- wxcli/commands/cc_user_profiles.py +349 -0
- wxcli/commands/cc_users.py +701 -0
- wxcli/commands/cc_work_types.py +363 -0
- wxcli/commands/cdr.py +89 -0
- wxcli/commands/classifications.py +38 -0
- wxcli/commands/cleanup.py +1427 -0
- wxcli/commands/client_settings.py +72 -0
- wxcli/commands/conference.py +328 -0
- wxcli/commands/configure.py +72 -0
- wxcli/commands/converged_recordings.py +347 -0
- wxcli/commands/converged_recordings_export.py +310 -0
- wxcli/commands/cq_playlists.py +42 -0
- wxcli/commands/cucm.py +2794 -0
- wxcli/commands/cucm_config.py +129 -0
- wxcli/commands/customer_assist.py +373 -0
- wxcli/commands/data_sources.py +227 -0
- wxcli/commands/dect_devices.py +787 -0
- wxcli/commands/device_configurations.py +77 -0
- wxcli/commands/device_dynamic_settings.py +320 -0
- wxcli/commands/device_settings.py +1489 -0
- wxcli/commands/devices.py +280 -0
- wxcli/commands/domains.py +142 -0
- wxcli/commands/ecm.py +178 -0
- wxcli/commands/emergency_services.py +827 -0
- wxcli/commands/events.py +83 -0
- wxcli/commands/external_voicemail.py +52 -0
- wxcli/commands/groups.py +206 -0
- wxcli/commands/guest_management.py +76 -0
- wxcli/commands/hds.py +340 -0
- wxcli/commands/hot_desk.py +67 -0
- wxcli/commands/hot_desking_members.py +118 -0
- wxcli/commands/hot_desking_portal.py +124 -0
- wxcli/commands/hunt_group.py +577 -0
- wxcli/commands/hybrid_clusters.py +71 -0
- wxcli/commands/hybrid_connectors.py +67 -0
- wxcli/commands/identity_org.py +159 -0
- wxcli/commands/init_playbook.py +155 -0
- wxcli/commands/licenses.py +106 -0
- wxcli/commands/live_monitoring.py +40 -0
- wxcli/commands/location_call_handling.py +577 -0
- wxcli/commands/location_schedules.py +341 -0
- wxcli/commands/location_settings.py +1297 -0
- wxcli/commands/location_voicemail.py +494 -0
- wxcli/commands/locations.py +336 -0
- wxcli/commands/meeting_captions.py +110 -0
- wxcli/commands/meeting_chats.py +63 -0
- wxcli/commands/meeting_invitees.py +234 -0
- wxcli/commands/meeting_messages.py +28 -0
- wxcli/commands/meeting_participants.py +278 -0
- wxcli/commands/meeting_polls.py +111 -0
- wxcli/commands/meeting_preferences.py +515 -0
- wxcli/commands/meeting_qa.py +78 -0
- wxcli/commands/meeting_qualities.py +43 -0
- wxcli/commands/meeting_reports.py +101 -0
- wxcli/commands/meeting_session_types.py +105 -0
- wxcli/commands/meeting_site.py +57 -0
- wxcli/commands/meeting_slido.py +44 -0
- wxcli/commands/meeting_summaries.py +92 -0
- wxcli/commands/meeting_tracking_codes.py +233 -0
- wxcli/commands/meeting_transcripts.py +230 -0
- wxcli/commands/meetings.py +1997 -0
- wxcli/commands/memberships.py +164 -0
- wxcli/commands/messages.py +213 -0
- wxcli/commands/mode_management.py +244 -0
- wxcli/commands/my_call_settings.py +3577 -0
- wxcli/commands/numbers.py +405 -0
- wxcli/commands/operating_modes.py +410 -0
- wxcli/commands/org_contacts.py +284 -0
- wxcli/commands/org_health_cli.py +55 -0
- wxcli/commands/org_settings.py +71 -0
- wxcli/commands/organizations.py +83 -0
- wxcli/commands/paging_group.py +257 -0
- wxcli/commands/partner_admins.py +141 -0
- wxcli/commands/partner_reports.py +188 -0
- wxcli/commands/partner_tags.py +216 -0
- wxcli/commands/people.py +279 -0
- wxcli/commands/person_call_settings.py +71 -0
- wxcli/commands/pstn.py +280 -0
- wxcli/commands/recording_report.py +154 -0
- wxcli/commands/report_templates.py +38 -0
- wxcli/commands/reports.py +144 -0
- wxcli/commands/resource_group_memberships.py +160 -0
- wxcli/commands/resource_groups.py +67 -0
- wxcli/commands/roles.py +63 -0
- wxcli/commands/room_tabs.py +160 -0
- wxcli/commands/rooms.py +225 -0
- wxcli/commands/scim_bulk.py +46 -0
- wxcli/commands/scim_groups.py +246 -0
- wxcli/commands/scim_schemas.py +82 -0
- wxcli/commands/scim_users.py +283 -0
- wxcli/commands/security_audit.py +54 -0
- wxcli/commands/service_apps.py +51 -0
- wxcli/commands/single_number_reach.py +209 -0
- wxcli/commands/team_memberships.py +155 -0
- wxcli/commands/teams.py +153 -0
- wxcli/commands/ucm_profile.py +42 -0
- wxcli/commands/update.py +219 -0
- wxcli/commands/user_settings.py +5116 -0
- wxcli/commands/video_mesh.py +1090 -0
- wxcli/commands/virtual_extensions.py +502 -0
- wxcli/commands/virtual_line_settings.py +2072 -0
- wxcli/commands/webhooks.py +176 -0
- wxcli/commands/wholesale_billing_reports.py +147 -0
- wxcli/commands/wholesale_provisioning.py +523 -0
- wxcli/commands/workspace_locations.py +339 -0
- wxcli/commands/workspace_metrics.py +103 -0
- wxcli/commands/workspace_personalization.py +70 -0
- wxcli/commands/workspace_settings.py +3347 -0
- wxcli/commands/workspaces.py +279 -0
- wxcli/commands/xapi.py +114 -0
- wxcli/config.py +139 -0
- wxcli/errors.py +77 -0
- wxcli/main.py +210 -0
- wxcli/migration/CLAUDE.md +106 -0
- wxcli/migration/__init__.py +1 -0
- wxcli/migration/advisory/CLAUDE.md +196 -0
- wxcli/migration/advisory/__init__.py +46 -0
- wxcli/migration/advisory/advisor.py +107 -0
- wxcli/migration/advisory/advisory_patterns.py +2552 -0
- wxcli/migration/advisory/recommendation_rules.py +835 -0
- wxcli/migration/cucm/CLAUDE.md +74 -0
- wxcli/migration/cucm/__init__.py +5 -0
- wxcli/migration/cucm/connection.py +265 -0
- wxcli/migration/cucm/discovery.py +225 -0
- wxcli/migration/cucm/extractors/__init__.py +1 -0
- wxcli/migration/cucm/extractors/announcements.py +92 -0
- wxcli/migration/cucm/extractors/base.py +90 -0
- wxcli/migration/cucm/extractors/device_profiles.py +98 -0
- wxcli/migration/cucm/extractors/devices.py +193 -0
- wxcli/migration/cucm/extractors/e911.py +103 -0
- wxcli/migration/cucm/extractors/features.py +309 -0
- wxcli/migration/cucm/extractors/helpers.py +73 -0
- wxcli/migration/cucm/extractors/informational.py +295 -0
- wxcli/migration/cucm/extractors/locations.py +221 -0
- wxcli/migration/cucm/extractors/moh.py +100 -0
- wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
- wxcli/migration/cucm/extractors/routing.py +493 -0
- wxcli/migration/cucm/extractors/shared_lines.py +146 -0
- wxcli/migration/cucm/extractors/templates.py +229 -0
- wxcli/migration/cucm/extractors/tier4.py +173 -0
- wxcli/migration/cucm/extractors/users.py +240 -0
- wxcli/migration/cucm/extractors/voicemail.py +243 -0
- wxcli/migration/cucm/extractors/workspaces.py +88 -0
- wxcli/migration/cucm/unity_connection.py +304 -0
- wxcli/migration/execute/CLAUDE.md +372 -0
- wxcli/migration/execute/__init__.py +303 -0
- wxcli/migration/execute/batch.py +277 -0
- wxcli/migration/execute/dependency.py +483 -0
- wxcli/migration/execute/engine.py +964 -0
- wxcli/migration/execute/handlers.py +2232 -0
- wxcli/migration/execute/planner.py +1939 -0
- wxcli/migration/execute/runtime.py +571 -0
- wxcli/migration/export/CLAUDE.md +49 -0
- wxcli/migration/export/__init__.py +8 -0
- wxcli/migration/export/csv_export.py +126 -0
- wxcli/migration/export/deployment_plan.py +479 -0
- wxcli/migration/export/json_export.py +60 -0
- wxcli/migration/models.py +941 -0
- wxcli/migration/phone_models.py +50 -0
- wxcli/migration/preflight/CLAUDE.md +52 -0
- wxcli/migration/preflight/__init__.py +89 -0
- wxcli/migration/preflight/checks.py +911 -0
- wxcli/migration/preflight/runner.py +293 -0
- wxcli/migration/rate_limiter.py +144 -0
- wxcli/migration/report/CLAUDE.md +245 -0
- wxcli/migration/report/__init__.py +7 -0
- wxcli/migration/report/appendix.py +2437 -0
- wxcli/migration/report/assembler.py +183 -0
- wxcli/migration/report/charts.py +263 -0
- wxcli/migration/report/executive.py +776 -0
- wxcli/migration/report/explainer.py +704 -0
- wxcli/migration/report/helpers.py +74 -0
- wxcli/migration/report/ingest.py +152 -0
- wxcli/migration/report/notice_templates.py +192 -0
- wxcli/migration/report/score.py +375 -0
- wxcli/migration/report/styles.py +1052 -0
- wxcli/migration/report/user_diff.py +1052 -0
- wxcli/migration/report/user_notice.py +425 -0
- wxcli/migration/state.py +139 -0
- wxcli/migration/store.py +860 -0
- wxcli/migration/transform/CLAUDE.md +107 -0
- wxcli/migration/transform/__init__.py +12 -0
- wxcli/migration/transform/analysis_pipeline.py +453 -0
- wxcli/migration/transform/analyzers/__init__.py +142 -0
- wxcli/migration/transform/analyzers/css_permission.py +189 -0
- wxcli/migration/transform/analyzers/css_routing.py +335 -0
- wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
- wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
- wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
- wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
- wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
- wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
- wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
- wxcli/migration/transform/analyzers/missing_data.py +300 -0
- wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
- wxcli/migration/transform/analyzers/shared_line.py +170 -0
- wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
- wxcli/migration/transform/analyzers/workspace_license.py +212 -0
- wxcli/migration/transform/cross_reference.py +1136 -0
- wxcli/migration/transform/cucm_pattern.py +246 -0
- wxcli/migration/transform/decisions.py +301 -0
- wxcli/migration/transform/e164.py +145 -0
- wxcli/migration/transform/engine.py +256 -0
- wxcli/migration/transform/mappers/CLAUDE.md +123 -0
- wxcli/migration/transform/mappers/__init__.py +76 -0
- wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
- wxcli/migration/transform/mappers/base.py +190 -0
- wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
- wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
- wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
- wxcli/migration/transform/mappers/css_mapper.py +868 -0
- wxcli/migration/transform/mappers/dect_mapper.py +367 -0
- wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
- wxcli/migration/transform/mappers/device_mapper.py +227 -0
- wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
- wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
- wxcli/migration/transform/mappers/e911_mapper.py +129 -0
- wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
- wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
- wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
- wxcli/migration/transform/mappers/line_mapper.py +310 -0
- wxcli/migration/transform/mappers/location_mapper.py +235 -0
- wxcli/migration/transform/mappers/moh_mapper.py +114 -0
- wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
- wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
- wxcli/migration/transform/mappers/routing_mapper.py +821 -0
- wxcli/migration/transform/mappers/snr_mapper.py +201 -0
- wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
- wxcli/migration/transform/mappers/user_mapper.py +264 -0
- wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
- wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
- wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
- wxcli/migration/transform/normalizers.py +2008 -0
- wxcli/migration/transform/pattern_converter.py +106 -0
- wxcli/migration/transform/pipeline.py +271 -0
- wxcli/migration/transform/rules.py +255 -0
- wxcli/org_health/CLAUDE.md +63 -0
- wxcli/org_health/__init__.py +7 -0
- wxcli/org_health/analyze.py +93 -0
- wxcli/org_health/checks.py +458 -0
- wxcli/org_health/collector.py +62 -0
- wxcli/org_health/models.py +78 -0
- wxcli/org_health/report.py +300 -0
- wxcli/output.py +101 -0
- wxcli-1.2.0.dist-info/METADATA +505 -0
- wxcli-1.2.0.dist-info/RECORD +413 -0
- wxcli-1.2.0.dist-info/WHEEL +5 -0
- wxcli-1.2.0.dist-info/entry_points.txt +2 -0
- wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
- wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
- wxcli-1.2.0.dist-info/scm_version.json +8 -0
- wxcli-1.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1878 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
from wxcli.config import get_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling call-queue.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
location_id: str = typer.Option(None, "--location-id", help="Returns the list of call queues in this location."),
|
|
15
|
+
name: str = typer.Option(None, "--name", help="Returns only the call queues matching the given name."),
|
|
16
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Returns only the call queues matching the given primary phon"),
|
|
17
|
+
department_id: str = typer.Option(None, "--department-id", help="Returns only call queues matching the given department ID."),
|
|
18
|
+
department_name: str = typer.Option(None, "--department-name", help="Returns only call queues matching the given department name."),
|
|
19
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Returns only the list of call queues with Customer Assist li"),
|
|
20
|
+
digital_inbox_enabled: str = typer.Option(None, "--digital-inbox-enabled", help="Returns only the list of call queues with digital inbox enab"),
|
|
21
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
22
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
23
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
24
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
25
|
+
):
|
|
26
|
+
"""Read the List of Call Queues with Customer Assist."""
|
|
27
|
+
api = get_api(debug=debug)
|
|
28
|
+
url = f"https://webexapis.com/v1/telephony/config/queues"
|
|
29
|
+
params = {}
|
|
30
|
+
if location_id is not None:
|
|
31
|
+
params["locationId"] = location_id
|
|
32
|
+
if name is not None:
|
|
33
|
+
params["name"] = name
|
|
34
|
+
if phone_number is not None:
|
|
35
|
+
params["phoneNumber"] = phone_number
|
|
36
|
+
if department_id is not None:
|
|
37
|
+
params["departmentId"] = department_id
|
|
38
|
+
if department_name is not None:
|
|
39
|
+
params["departmentName"] = department_name
|
|
40
|
+
if has_cx_essentials is not None:
|
|
41
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
42
|
+
if digital_inbox_enabled is not None:
|
|
43
|
+
params["digitalInboxEnabled"] = digital_inbox_enabled
|
|
44
|
+
if limit > 0:
|
|
45
|
+
params["max"] = limit
|
|
46
|
+
if offset > 0:
|
|
47
|
+
params["start"] = offset
|
|
48
|
+
org_id = get_org_id()
|
|
49
|
+
if org_id is not None:
|
|
50
|
+
params["orgId"] = org_id
|
|
51
|
+
try:
|
|
52
|
+
if limit > 0:
|
|
53
|
+
result = api.session.rest_get(url, params=params)
|
|
54
|
+
result = result or {}
|
|
55
|
+
items = result.get("queues", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
56
|
+
else:
|
|
57
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="queues"))
|
|
58
|
+
except WebexError as e:
|
|
59
|
+
handle_rest_error(e)
|
|
60
|
+
if output == "json":
|
|
61
|
+
print_json(items)
|
|
62
|
+
else:
|
|
63
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@app.command("show-org-settings")
|
|
68
|
+
def show_org_settings(
|
|
69
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
70
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
71
|
+
):
|
|
72
|
+
"""Get Call Queue Settings."""
|
|
73
|
+
api = get_api(debug=debug)
|
|
74
|
+
url = f"https://webexapis.com/v1/telephony/config/queues/settings"
|
|
75
|
+
params = {}
|
|
76
|
+
org_id = get_org_id()
|
|
77
|
+
if org_id is not None:
|
|
78
|
+
params["orgId"] = org_id
|
|
79
|
+
try:
|
|
80
|
+
result = api.session.rest_get(url, params=params)
|
|
81
|
+
except WebexError as e:
|
|
82
|
+
handle_rest_error(e)
|
|
83
|
+
if output == "json":
|
|
84
|
+
print_json(result)
|
|
85
|
+
else:
|
|
86
|
+
if isinstance(result, dict):
|
|
87
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
88
|
+
elif isinstance(result, list):
|
|
89
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
90
|
+
else:
|
|
91
|
+
print_json(result)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@app.command("update-org-settings")
|
|
96
|
+
def update_org_settings(
|
|
97
|
+
maintain_queue_position_for_sim_ring_enabled: bool = typer.Option(None, "--maintain-queue-position-for-sim-ring-enabled/--no-maintain-queue-position-for-sim-ring-enabled", help="Indicates whether callers keep their queue position when sim"),
|
|
98
|
+
force_agent_unavailable_on_bounced_enabled: bool = typer.Option(None, "--force-agent-unavailable-on-bounced-enabled/--no-force-agent-unavailable-on-bounced-enabled", help="Indicates whether Customer Assist agents are changed to unav"),
|
|
99
|
+
play_tone_to_agent_for_barge_in_enabled: bool = typer.Option(None, "--play-tone-to-agent-for-barge-in-enabled/--no-play-tone-to-agent-for-barge-in-enabled", help="Organization-wide default that plays a tone to agents when a"),
|
|
100
|
+
play_tone_to_agent_for_silent_monitoring_enabled: bool = typer.Option(None, "--play-tone-to-agent-for-silent-monitoring-enabled/--no-play-tone-to-agent-for-silent-monitoring-enabled", help="Organization-wide default that plays a tone to agents when a"),
|
|
101
|
+
play_tone_to_agent_for_supervisor_coaching_enabled: bool = typer.Option(None, "--play-tone-to-agent-for-supervisor-coaching-enabled/--no-play-tone-to-agent-for-supervisor-coaching-enabled", help="Organization-wide default that plays a tone to agents when a"),
|
|
102
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
103
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
104
|
+
):
|
|
105
|
+
"""Update Call Queue Settings."""
|
|
106
|
+
api = get_api(debug=debug)
|
|
107
|
+
url = f"https://webexapis.com/v1/telephony/config/queues/settings"
|
|
108
|
+
params = {}
|
|
109
|
+
org_id = get_org_id()
|
|
110
|
+
if org_id is not None:
|
|
111
|
+
params["orgId"] = org_id
|
|
112
|
+
if json_body:
|
|
113
|
+
body = json.loads(json_body)
|
|
114
|
+
else:
|
|
115
|
+
body = {}
|
|
116
|
+
if maintain_queue_position_for_sim_ring_enabled is not None:
|
|
117
|
+
body["maintainQueuePositionForSimRingEnabled"] = maintain_queue_position_for_sim_ring_enabled
|
|
118
|
+
if force_agent_unavailable_on_bounced_enabled is not None:
|
|
119
|
+
body["forceAgentUnavailableOnBouncedEnabled"] = force_agent_unavailable_on_bounced_enabled
|
|
120
|
+
if play_tone_to_agent_for_barge_in_enabled is not None:
|
|
121
|
+
body["playToneToAgentForBargeInEnabled"] = play_tone_to_agent_for_barge_in_enabled
|
|
122
|
+
if play_tone_to_agent_for_silent_monitoring_enabled is not None:
|
|
123
|
+
body["playToneToAgentForSilentMonitoringEnabled"] = play_tone_to_agent_for_silent_monitoring_enabled
|
|
124
|
+
if play_tone_to_agent_for_supervisor_coaching_enabled is not None:
|
|
125
|
+
body["playToneToAgentForSupervisorCoachingEnabled"] = play_tone_to_agent_for_supervisor_coaching_enabled
|
|
126
|
+
try:
|
|
127
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
128
|
+
except WebexError as e:
|
|
129
|
+
handle_rest_error(e)
|
|
130
|
+
typer.echo(f"Updated.")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@app.command("create")
|
|
135
|
+
def create(
|
|
136
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
137
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Creates a Customer Assist call queue, when `true`. This requ"),
|
|
138
|
+
name: str = typer.Option(None, "--name", help="(required) Unique name for the call queue."),
|
|
139
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Primary phone number of the call queue. Either a `phoneNumbe"),
|
|
140
|
+
extension: str = typer.Option(None, "--extension", help="Primary phone extension of the call queue. Either a `phoneNu"),
|
|
141
|
+
language_code: str = typer.Option(None, "--language-code", help="Language code."),
|
|
142
|
+
first_name: str = typer.Option(None, "--first-name", help="First name to be shown when calls are forwarded out of this"),
|
|
143
|
+
last_name: str = typer.Option(None, "--last-name", help="Last name to be shown when calls are forwarded out of this c"),
|
|
144
|
+
time_zone: str = typer.Option(None, "--time-zone", help="Time zone for the call queue."),
|
|
145
|
+
calling_line_id_policy: str = typer.Option(None, "--calling-line-id-policy", help="Choices: DIRECT_LINE, LOCATION_NUMBER, CUSTOM"),
|
|
146
|
+
calling_line_id_phone_number: str = typer.Option(None, "--calling-line-id-phone-number", help="Calling line ID Phone number which will be shown if CUSTOM i"),
|
|
147
|
+
allow_agent_join_enabled: bool = typer.Option(None, "--allow-agent-join-enabled/--no-allow-agent-join-enabled", help="Whether or not to allow agents to join or unjoin a queue."),
|
|
148
|
+
phone_number_for_outgoing_calls_enabled: bool = typer.Option(None, "--phone-number-for-outgoing-calls-enabled/--no-phone-number-for-outgoing-calls-enabled", help="When `true`, indicates that the agent's configuration allows"),
|
|
149
|
+
dial_by_name: str = typer.Option(None, "--dial-by-name", help="The name to be used for dial by name functions. Characters o"),
|
|
150
|
+
digital_inbox_enabled: bool = typer.Option(None, "--digital-inbox-enabled/--no-digital-inbox-enabled", help="Digital Inbox enabled for Queue. This field is applicable fo"),
|
|
151
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
152
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
153
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
154
|
+
):
|
|
155
|
+
"""Create a Call Queue with Customer Assist\n\nExample --json-body:\n '{"name":"...","callPolicies":{"routingType":"PRIORITY_BASED","policy":"CIRCULAR","callBounce":{"callBounceEnabled":"...","callBounceMaxRings":"...","agentUnavailableEnabled":"...","alertAgentEnabled":"...","alertAgentMaxSeconds":"...","callBounceOnHoldEnabled":"...","callBounceOnHoldMaxSeconds":"..."},"distinctiveRing":{"enabled":"...","ringPattern":"..."}},"queueSettings":{"queueSize":0,"overflow":{"action":"...","greeting":"...","sendToVoicemail":"...","transferNumber":"...","overflowAfterWaitEnabled":"...","overflowAfterWaitTime":"...","playOverflowGreetingEnabled":"...","audioAnnouncementFiles":"..."},"callOfferToneEnabled":true,"resetCallStatisticsEnabled":true,"welcomeMessage":{"greeting":"...","enabled":"...","alwaysEnabled":"...","audioAnnouncementFiles":"..."},"waitMessage":{"waitMode":"...","enabled":"...","handlingTime":"...","defaultHandlingTime":"...","queuePosition":"...","highVolumeMessageEnabled":"...","estimatedWaitingTime":"...","callbackOptionEnabled":"..."},"comfortMessage":{"greeting":"...","enabled":"...","timeBetweenMessages":"...","audioAnnouncementFiles":"..."},"comfortMessageBypass":{"greeting":"...","enabled":"...","callWaitingAgeThreshold":"...","audioAnnouncementFiles":"..."}},"agents":[{"id":"...","weight":"...","skillLevel":"..."}],"phoneNumber":"...","extension":"...","languageCode":"...","firstName":"..."}'."""
|
|
156
|
+
api = get_api(debug=debug)
|
|
157
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues"
|
|
158
|
+
params = {}
|
|
159
|
+
if has_cx_essentials is not None:
|
|
160
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
161
|
+
org_id = get_org_id()
|
|
162
|
+
if org_id is not None:
|
|
163
|
+
params["orgId"] = org_id
|
|
164
|
+
if json_body:
|
|
165
|
+
body = json.loads(json_body)
|
|
166
|
+
else:
|
|
167
|
+
body = {}
|
|
168
|
+
if name is not None:
|
|
169
|
+
body["name"] = name
|
|
170
|
+
if phone_number is not None:
|
|
171
|
+
body["phoneNumber"] = phone_number
|
|
172
|
+
if extension is not None:
|
|
173
|
+
body["extension"] = extension
|
|
174
|
+
if language_code is not None:
|
|
175
|
+
body["languageCode"] = language_code
|
|
176
|
+
if first_name is not None:
|
|
177
|
+
body["firstName"] = first_name
|
|
178
|
+
if last_name is not None:
|
|
179
|
+
body["lastName"] = last_name
|
|
180
|
+
if time_zone is not None:
|
|
181
|
+
body["timeZone"] = time_zone
|
|
182
|
+
if calling_line_id_policy is not None:
|
|
183
|
+
body["callingLineIdPolicy"] = calling_line_id_policy
|
|
184
|
+
if calling_line_id_phone_number is not None:
|
|
185
|
+
body["callingLineIdPhoneNumber"] = calling_line_id_phone_number
|
|
186
|
+
if allow_agent_join_enabled is not None:
|
|
187
|
+
body["allowAgentJoinEnabled"] = allow_agent_join_enabled
|
|
188
|
+
if phone_number_for_outgoing_calls_enabled is not None:
|
|
189
|
+
body["phoneNumberForOutgoingCallsEnabled"] = phone_number_for_outgoing_calls_enabled
|
|
190
|
+
if dial_by_name is not None:
|
|
191
|
+
body["dialByName"] = dial_by_name
|
|
192
|
+
if digital_inbox_enabled is not None:
|
|
193
|
+
body["digitalInboxEnabled"] = digital_inbox_enabled
|
|
194
|
+
_missing = [f for f in ['name'] if f not in body or body[f] is None]
|
|
195
|
+
if _missing:
|
|
196
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
197
|
+
raise typer.Exit(1)
|
|
198
|
+
try:
|
|
199
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
200
|
+
except WebexError as e:
|
|
201
|
+
handle_rest_error(e)
|
|
202
|
+
if output == "json":
|
|
203
|
+
print_json(result)
|
|
204
|
+
elif isinstance(result, dict) and "id" in result:
|
|
205
|
+
typer.echo(f"Created: {result['id']}")
|
|
206
|
+
elif not result or result == {}:
|
|
207
|
+
typer.echo("Created.")
|
|
208
|
+
else:
|
|
209
|
+
print_json(result)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@app.command("show")
|
|
214
|
+
def show(
|
|
215
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
216
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
217
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Must be set to `true`, to view the details of a call queue w"),
|
|
218
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
219
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
220
|
+
):
|
|
221
|
+
"""Get Details for a Call Queue with Customer Assist."""
|
|
222
|
+
api = get_api(debug=debug)
|
|
223
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}"
|
|
224
|
+
params = {}
|
|
225
|
+
if has_cx_essentials is not None:
|
|
226
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
227
|
+
org_id = get_org_id()
|
|
228
|
+
if org_id is not None:
|
|
229
|
+
params["orgId"] = org_id
|
|
230
|
+
try:
|
|
231
|
+
result = api.session.rest_get(url, params=params)
|
|
232
|
+
except WebexError as e:
|
|
233
|
+
handle_rest_error(e)
|
|
234
|
+
if output == "json":
|
|
235
|
+
print_json(result)
|
|
236
|
+
else:
|
|
237
|
+
if isinstance(result, dict):
|
|
238
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
239
|
+
elif isinstance(result, list):
|
|
240
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
241
|
+
else:
|
|
242
|
+
print_json(result)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@app.command("update")
|
|
247
|
+
def update(
|
|
248
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
249
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
250
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Whether or not the call queue is enabled."),
|
|
251
|
+
name: str = typer.Option(None, "--name", help="Unique name for the call queue."),
|
|
252
|
+
language_code: str = typer.Option(None, "--language-code", help="Language code."),
|
|
253
|
+
first_name: str = typer.Option(None, "--first-name", help="First name to be shown when calls are forwarded out of this"),
|
|
254
|
+
last_name: str = typer.Option(None, "--last-name", help="Last name to be shown when calls are forwarded out of this c"),
|
|
255
|
+
time_zone: str = typer.Option(None, "--time-zone", help="Time zone for the hunt group."),
|
|
256
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Primary phone number of the call queue."),
|
|
257
|
+
extension: str = typer.Option(None, "--extension", help="Extension of the call queue."),
|
|
258
|
+
calling_line_id_policy: str = typer.Option(None, "--calling-line-id-policy", help="Choices: DIRECT_LINE, LOCATION_NUMBER, CUSTOM"),
|
|
259
|
+
calling_line_id_phone_number: str = typer.Option(None, "--calling-line-id-phone-number", help="Calling line ID Phone number which will be shown if CUSTOM i"),
|
|
260
|
+
allow_call_waiting_for_agents_enabled: bool = typer.Option(None, "--allow-call-waiting-for-agents-enabled/--no-allow-call-waiting-for-agents-enabled", help="Flag to indicate whether call waiting is enabled for agents."),
|
|
261
|
+
allow_agent_join_enabled: bool = typer.Option(None, "--allow-agent-join-enabled/--no-allow-agent-join-enabled", help="Whether or not to allow agents to join or unjoin a queue."),
|
|
262
|
+
phone_number_for_outgoing_calls_enabled: bool = typer.Option(None, "--phone-number-for-outgoing-calls-enabled/--no-phone-number-for-outgoing-calls-enabled", help="When `true`, indicates that the agent's configuration allows"),
|
|
263
|
+
dial_by_name: str = typer.Option(None, "--dial-by-name", help="Sets or clears the name to be used for dial by name function"),
|
|
264
|
+
digital_inbox_enabled: bool = typer.Option(None, "--digital-inbox-enabled/--no-digital-inbox-enabled", help="Digital Inbox enabled for Queue. This field is applicable fo"),
|
|
265
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
266
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
267
|
+
):
|
|
268
|
+
"""Update a Call Queue\n\nExample --json-body:\n '{"queueSettings":{"queueSize":0,"overflow":{"action":"...","greeting":"...","sendToVoicemail":"...","transferNumber":"...","overflowAfterWaitEnabled":"...","overflowAfterWaitTime":"...","playOverflowGreetingEnabled":"...","audioAnnouncementFiles":"..."},"callOfferToneEnabled":true,"resetCallStatisticsEnabled":true,"welcomeMessage":{"greeting":"...","enabled":"...","alwaysEnabled":"...","audioAnnouncementFiles":"..."},"waitMessage":{"waitMode":"...","enabled":"...","handlingTime":"...","defaultHandlingTime":"...","queuePosition":"...","highVolumeMessageEnabled":"...","estimatedWaitingTime":"...","callbackOptionEnabled":"..."},"comfortMessage":{"greeting":"...","enabled":"...","timeBetweenMessages":"...","audioAnnouncementFiles":"..."},"comfortMessageBypass":{"greeting":"...","enabled":"...","callWaitingAgeThreshold":"...","audioAnnouncementFiles":"..."}},"enabled":true,"name":"...","languageCode":"...","firstName":"...","lastName":"...","timeZone":"...","phoneNumber":"..."}'."""
|
|
269
|
+
api = get_api(debug=debug)
|
|
270
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}"
|
|
271
|
+
params = {}
|
|
272
|
+
org_id = get_org_id()
|
|
273
|
+
if org_id is not None:
|
|
274
|
+
params["orgId"] = org_id
|
|
275
|
+
if json_body:
|
|
276
|
+
body = json.loads(json_body)
|
|
277
|
+
else:
|
|
278
|
+
body = {}
|
|
279
|
+
if enabled is not None:
|
|
280
|
+
body["enabled"] = enabled
|
|
281
|
+
if name is not None:
|
|
282
|
+
body["name"] = name
|
|
283
|
+
if language_code is not None:
|
|
284
|
+
body["languageCode"] = language_code
|
|
285
|
+
if first_name is not None:
|
|
286
|
+
body["firstName"] = first_name
|
|
287
|
+
if last_name is not None:
|
|
288
|
+
body["lastName"] = last_name
|
|
289
|
+
if time_zone is not None:
|
|
290
|
+
body["timeZone"] = time_zone
|
|
291
|
+
if phone_number is not None:
|
|
292
|
+
body["phoneNumber"] = phone_number
|
|
293
|
+
if extension is not None:
|
|
294
|
+
body["extension"] = extension
|
|
295
|
+
if calling_line_id_policy is not None:
|
|
296
|
+
body["callingLineIdPolicy"] = calling_line_id_policy
|
|
297
|
+
if calling_line_id_phone_number is not None:
|
|
298
|
+
body["callingLineIdPhoneNumber"] = calling_line_id_phone_number
|
|
299
|
+
if allow_call_waiting_for_agents_enabled is not None:
|
|
300
|
+
body["allowCallWaitingForAgentsEnabled"] = allow_call_waiting_for_agents_enabled
|
|
301
|
+
if allow_agent_join_enabled is not None:
|
|
302
|
+
body["allowAgentJoinEnabled"] = allow_agent_join_enabled
|
|
303
|
+
if phone_number_for_outgoing_calls_enabled is not None:
|
|
304
|
+
body["phoneNumberForOutgoingCallsEnabled"] = phone_number_for_outgoing_calls_enabled
|
|
305
|
+
if dial_by_name is not None:
|
|
306
|
+
body["dialByName"] = dial_by_name
|
|
307
|
+
if digital_inbox_enabled is not None:
|
|
308
|
+
body["digitalInboxEnabled"] = digital_inbox_enabled
|
|
309
|
+
try:
|
|
310
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
311
|
+
except WebexError as e:
|
|
312
|
+
handle_rest_error(e)
|
|
313
|
+
typer.echo(f"Updated.")
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@app.command("delete")
|
|
318
|
+
def delete(
|
|
319
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
320
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
321
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
322
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
323
|
+
):
|
|
324
|
+
"""Delete a Call Queue."""
|
|
325
|
+
if not force:
|
|
326
|
+
typer.confirm(f"Delete {queue_id}?", abort=True)
|
|
327
|
+
api = get_api(debug=debug)
|
|
328
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}"
|
|
329
|
+
params = {}
|
|
330
|
+
org_id = get_org_id()
|
|
331
|
+
if org_id is not None:
|
|
332
|
+
params["orgId"] = org_id
|
|
333
|
+
try:
|
|
334
|
+
api.session.rest_delete(url, params=params)
|
|
335
|
+
except WebexError as e:
|
|
336
|
+
handle_rest_error(e)
|
|
337
|
+
typer.echo(f"Deleted: {queue_id}")
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@app.command("list-announcements")
|
|
342
|
+
def list_announcements(
|
|
343
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
344
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
345
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
346
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
347
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
348
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
349
|
+
):
|
|
350
|
+
"""Read the List of Call Queue Announcement Files."""
|
|
351
|
+
api = get_api(debug=debug)
|
|
352
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/announcements"
|
|
353
|
+
params = {}
|
|
354
|
+
if limit > 0:
|
|
355
|
+
params["max"] = limit
|
|
356
|
+
if offset > 0:
|
|
357
|
+
params["start"] = offset
|
|
358
|
+
org_id = get_org_id()
|
|
359
|
+
if org_id is not None:
|
|
360
|
+
params["orgId"] = org_id
|
|
361
|
+
result = None
|
|
362
|
+
try:
|
|
363
|
+
result = api.session.rest_get(url, params=params)
|
|
364
|
+
except WebexError as e:
|
|
365
|
+
handle_rest_error(e)
|
|
366
|
+
result = result or []
|
|
367
|
+
items = result.get("announcements", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
368
|
+
if output == "json":
|
|
369
|
+
print_json(items)
|
|
370
|
+
else:
|
|
371
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@app.command("delete-announcements")
|
|
376
|
+
def delete_announcements(
|
|
377
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
378
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
379
|
+
file_name: str = typer.Argument(help="fileName"),
|
|
380
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
381
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
382
|
+
):
|
|
383
|
+
"""Delete a Call Queue Announcement File."""
|
|
384
|
+
if not force:
|
|
385
|
+
typer.confirm(f"Delete {file_name}?", abort=True)
|
|
386
|
+
api = get_api(debug=debug)
|
|
387
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/announcements/{file_name}"
|
|
388
|
+
params = {}
|
|
389
|
+
org_id = get_org_id()
|
|
390
|
+
if org_id is not None:
|
|
391
|
+
params["orgId"] = org_id
|
|
392
|
+
try:
|
|
393
|
+
api.session.rest_delete(url, params=params)
|
|
394
|
+
except WebexError as e:
|
|
395
|
+
handle_rest_error(e)
|
|
396
|
+
typer.echo(f"Deleted: {file_name}")
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
@app.command("show-call-forwarding")
|
|
401
|
+
def show_call_forwarding(
|
|
402
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
403
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
404
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
405
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
406
|
+
):
|
|
407
|
+
"""Get Call Forwarding Settings for a Call Queue."""
|
|
408
|
+
api = get_api(debug=debug)
|
|
409
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding"
|
|
410
|
+
params = {}
|
|
411
|
+
org_id = get_org_id()
|
|
412
|
+
if org_id is not None:
|
|
413
|
+
params["orgId"] = org_id
|
|
414
|
+
try:
|
|
415
|
+
result = api.session.rest_get(url, params=params)
|
|
416
|
+
except WebexError as e:
|
|
417
|
+
handle_rest_error(e)
|
|
418
|
+
if output == "json":
|
|
419
|
+
print_json(result)
|
|
420
|
+
else:
|
|
421
|
+
if isinstance(result, dict):
|
|
422
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
423
|
+
elif isinstance(result, list):
|
|
424
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
425
|
+
else:
|
|
426
|
+
print_json(result)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
@app.command("update-call-forwarding")
|
|
431
|
+
def update_call_forwarding(
|
|
432
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
433
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
434
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
435
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
436
|
+
):
|
|
437
|
+
"""Update Call Forwarding Settings for a Call Queue\n\nExample --json-body:\n '{"callForwarding":{"always":{"enabled":"...","destination":"...","ringReminderEnabled":"...","destinationVoicemailEnabled":"..."},"selective":{"enabled":"...","destination":"...","ringReminderEnabled":"...","destinationVoicemailEnabled":"..."},"rules":["..."],"operatingModes":{"enabled":"...","modes":"..."}}}'."""
|
|
438
|
+
api = get_api(debug=debug)
|
|
439
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding"
|
|
440
|
+
params = {}
|
|
441
|
+
org_id = get_org_id()
|
|
442
|
+
if org_id is not None:
|
|
443
|
+
params["orgId"] = org_id
|
|
444
|
+
if json_body:
|
|
445
|
+
body = json.loads(json_body)
|
|
446
|
+
else:
|
|
447
|
+
body = {}
|
|
448
|
+
try:
|
|
449
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
450
|
+
except WebexError as e:
|
|
451
|
+
handle_rest_error(e)
|
|
452
|
+
typer.echo(f"Updated.")
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
@app.command("create-selective-rules")
|
|
457
|
+
def create_selective_rules(
|
|
458
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
459
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
460
|
+
name: str = typer.Option(None, "--name", help="(required) Unique name for the selective rule in the hunt group."),
|
|
461
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Reflects if rule is enabled."),
|
|
462
|
+
holiday_schedule: str = typer.Option(None, "--holiday-schedule", help="Name of the location's holiday schedule which determines whe"),
|
|
463
|
+
business_schedule: str = typer.Option(None, "--business-schedule", help="Name of the location's business schedule which determines wh"),
|
|
464
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
465
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
466
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
467
|
+
):
|
|
468
|
+
"""Create a Selective Call Forwarding Rule for a Call Queue\n\nExample --json-body:\n '{"name":"...","callsFrom":{"selection":"ANY","customNumbers":{"privateNumberEnabled":"...","unavailableNumberEnabled":"...","numbers":"..."}},"callsTo":{"numbers":["..."]},"enabled":true,"holidaySchedule":"...","businessSchedule":"...","forwardTo":{"selection":"FORWARD_TO_DEFAULT_NUMBER","phoneNumber":"..."}}'."""
|
|
469
|
+
api = get_api(debug=debug)
|
|
470
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding/selectiveRules"
|
|
471
|
+
params = {}
|
|
472
|
+
org_id = get_org_id()
|
|
473
|
+
if org_id is not None:
|
|
474
|
+
params["orgId"] = org_id
|
|
475
|
+
if json_body:
|
|
476
|
+
body = json.loads(json_body)
|
|
477
|
+
else:
|
|
478
|
+
body = {}
|
|
479
|
+
if name is not None:
|
|
480
|
+
body["name"] = name
|
|
481
|
+
if enabled is not None:
|
|
482
|
+
body["enabled"] = enabled
|
|
483
|
+
if holiday_schedule is not None:
|
|
484
|
+
body["holidaySchedule"] = holiday_schedule
|
|
485
|
+
if business_schedule is not None:
|
|
486
|
+
body["businessSchedule"] = business_schedule
|
|
487
|
+
_missing = [f for f in ['name'] if f not in body or body[f] is None]
|
|
488
|
+
if _missing:
|
|
489
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
490
|
+
raise typer.Exit(1)
|
|
491
|
+
try:
|
|
492
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
493
|
+
except WebexError as e:
|
|
494
|
+
handle_rest_error(e)
|
|
495
|
+
if output == "json":
|
|
496
|
+
print_json(result)
|
|
497
|
+
elif isinstance(result, dict) and "id" in result:
|
|
498
|
+
typer.echo(f"Created: {result['id']}")
|
|
499
|
+
elif not result or result == {}:
|
|
500
|
+
typer.echo("Created.")
|
|
501
|
+
else:
|
|
502
|
+
print_json(result)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
@app.command("show-selective-rules")
|
|
507
|
+
def show_selective_rules(
|
|
508
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
509
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
510
|
+
rule_id: str = typer.Argument(help="ruleId"),
|
|
511
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
512
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
513
|
+
):
|
|
514
|
+
"""Get Selective Call Forwarding Rule for a Call Queue."""
|
|
515
|
+
api = get_api(debug=debug)
|
|
516
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding/selectiveRules/{rule_id}"
|
|
517
|
+
params = {}
|
|
518
|
+
org_id = get_org_id()
|
|
519
|
+
if org_id is not None:
|
|
520
|
+
params["orgId"] = org_id
|
|
521
|
+
try:
|
|
522
|
+
result = api.session.rest_get(url, params=params)
|
|
523
|
+
except WebexError as e:
|
|
524
|
+
handle_rest_error(e)
|
|
525
|
+
if output == "json":
|
|
526
|
+
print_json(result)
|
|
527
|
+
else:
|
|
528
|
+
if isinstance(result, dict):
|
|
529
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
530
|
+
elif isinstance(result, list):
|
|
531
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
532
|
+
else:
|
|
533
|
+
print_json(result)
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
@app.command("update-selective-rules")
|
|
538
|
+
def update_selective_rules(
|
|
539
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
540
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
541
|
+
rule_id: str = typer.Argument(help="ruleId"),
|
|
542
|
+
name: str = typer.Option(None, "--name", help="Unique name for the selective rule in the hunt group."),
|
|
543
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Reflects if rule is enabled."),
|
|
544
|
+
holiday_schedule: str = typer.Option(None, "--holiday-schedule", help="Name of the location's holiday schedule which determines whe"),
|
|
545
|
+
business_schedule: str = typer.Option(None, "--business-schedule", help="Name of the location's business schedule which determines wh"),
|
|
546
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
547
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
548
|
+
):
|
|
549
|
+
"""Update a Selective Call Forwarding Rule for a Call Queue\n\nExample --json-body:\n '{"name":"...","enabled":true,"holidaySchedule":"...","businessSchedule":"...","forwardTo":{"selection":"FORWARD_TO_DEFAULT_NUMBER","phoneNumber":"..."},"callsFrom":{"selection":"ANY","customNumbers":{"privateNumberEnabled":"...","unavailableNumberEnabled":"...","numbers":"..."}},"callsTo":{"numbers":["..."]}}'."""
|
|
550
|
+
api = get_api(debug=debug)
|
|
551
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding/selectiveRules/{rule_id}"
|
|
552
|
+
params = {}
|
|
553
|
+
org_id = get_org_id()
|
|
554
|
+
if org_id is not None:
|
|
555
|
+
params["orgId"] = org_id
|
|
556
|
+
if json_body:
|
|
557
|
+
body = json.loads(json_body)
|
|
558
|
+
else:
|
|
559
|
+
body = {}
|
|
560
|
+
if name is not None:
|
|
561
|
+
body["name"] = name
|
|
562
|
+
if enabled is not None:
|
|
563
|
+
body["enabled"] = enabled
|
|
564
|
+
if holiday_schedule is not None:
|
|
565
|
+
body["holidaySchedule"] = holiday_schedule
|
|
566
|
+
if business_schedule is not None:
|
|
567
|
+
body["businessSchedule"] = business_schedule
|
|
568
|
+
try:
|
|
569
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
570
|
+
except WebexError as e:
|
|
571
|
+
handle_rest_error(e)
|
|
572
|
+
typer.echo(f"Updated.")
|
|
573
|
+
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
@app.command("delete-selective-rules")
|
|
577
|
+
def delete_selective_rules(
|
|
578
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
579
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
580
|
+
rule_id: str = typer.Argument(help="ruleId"),
|
|
581
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
582
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
583
|
+
):
|
|
584
|
+
"""Delete a Selective Call Forwarding Rule for a Call Queue."""
|
|
585
|
+
if not force:
|
|
586
|
+
typer.confirm(f"Delete {rule_id}?", abort=True)
|
|
587
|
+
api = get_api(debug=debug)
|
|
588
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding/selectiveRules/{rule_id}"
|
|
589
|
+
params = {}
|
|
590
|
+
org_id = get_org_id()
|
|
591
|
+
if org_id is not None:
|
|
592
|
+
params["orgId"] = org_id
|
|
593
|
+
try:
|
|
594
|
+
api.session.rest_delete(url, params=params)
|
|
595
|
+
except WebexError as e:
|
|
596
|
+
handle_rest_error(e)
|
|
597
|
+
typer.echo(f"Deleted: {rule_id}")
|
|
598
|
+
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
@app.command("list-holiday-service")
|
|
602
|
+
def list_holiday_service(
|
|
603
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
604
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
605
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
606
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
607
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
608
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
609
|
+
):
|
|
610
|
+
"""Get Details for a Call Queue Holiday Service."""
|
|
611
|
+
api = get_api(debug=debug)
|
|
612
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/holidayService"
|
|
613
|
+
params = {}
|
|
614
|
+
if limit > 0:
|
|
615
|
+
params["max"] = limit
|
|
616
|
+
if offset > 0:
|
|
617
|
+
params["start"] = offset
|
|
618
|
+
org_id = get_org_id()
|
|
619
|
+
if org_id is not None:
|
|
620
|
+
params["orgId"] = org_id
|
|
621
|
+
result = None
|
|
622
|
+
try:
|
|
623
|
+
result = api.session.rest_get(url, params=params)
|
|
624
|
+
except WebexError as e:
|
|
625
|
+
handle_rest_error(e)
|
|
626
|
+
result = result or []
|
|
627
|
+
items = result.get("audioFiles", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
628
|
+
if output == "json":
|
|
629
|
+
print_json(items)
|
|
630
|
+
else:
|
|
631
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
@app.command("update-holiday-service")
|
|
636
|
+
def update_holiday_service(
|
|
637
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
638
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
639
|
+
holiday_service_enabled: bool = typer.Option(None, "--holiday-service-enabled/--no-holiday-service-enabled", help="Enable or Disable the call queue holiday service routing pol"),
|
|
640
|
+
action: str = typer.Option(None, "--action", help="Choices: BUSY, TRANSFER"),
|
|
641
|
+
holiday_schedule_level: str = typer.Option(None, "--holiday-schedule-level", help="Choices: LOCATION, ORGANIZATION"),
|
|
642
|
+
holiday_schedule_name: str = typer.Option(None, "--holiday-schedule-name", help="Name of the schedule configured for a holiday service as one"),
|
|
643
|
+
transfer_phone_number: str = typer.Option(None, "--transfer-phone-number", help="Call gets transferred to this number when action is set to `"),
|
|
644
|
+
play_announcement_before_enabled: bool = typer.Option(None, "--play-announcement-before-enabled/--no-play-announcement-before-enabled", help="Indicates whether an announcement plays to callers before th"),
|
|
645
|
+
audio_message_selection: str = typer.Option(None, "--audio-message-selection", help="Choices: DEFAULT, CUSTOM"),
|
|
646
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
647
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
648
|
+
):
|
|
649
|
+
"""Update a Call Queue Holiday Service\n\nExample --json-body:\n '{"holidayServiceEnabled":true,"action":"BUSY","holidayScheduleLevel":"LOCATION","playAnnouncementBeforeEnabled":true,"audioMessageSelection":"DEFAULT","holidayScheduleName":"...","transferPhoneNumber":"...","audioFiles":[{"id":"...","fileName":"...","mediaFileType":"...","level":"..."}]}'."""
|
|
650
|
+
api = get_api(debug=debug)
|
|
651
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/holidayService"
|
|
652
|
+
params = {}
|
|
653
|
+
org_id = get_org_id()
|
|
654
|
+
if org_id is not None:
|
|
655
|
+
params["orgId"] = org_id
|
|
656
|
+
if json_body:
|
|
657
|
+
body = json.loads(json_body)
|
|
658
|
+
else:
|
|
659
|
+
body = {}
|
|
660
|
+
if holiday_service_enabled is not None:
|
|
661
|
+
body["holidayServiceEnabled"] = holiday_service_enabled
|
|
662
|
+
if action is not None:
|
|
663
|
+
body["action"] = action
|
|
664
|
+
if holiday_schedule_level is not None:
|
|
665
|
+
body["holidayScheduleLevel"] = holiday_schedule_level
|
|
666
|
+
if holiday_schedule_name is not None:
|
|
667
|
+
body["holidayScheduleName"] = holiday_schedule_name
|
|
668
|
+
if transfer_phone_number is not None:
|
|
669
|
+
body["transferPhoneNumber"] = transfer_phone_number
|
|
670
|
+
if play_announcement_before_enabled is not None:
|
|
671
|
+
body["playAnnouncementBeforeEnabled"] = play_announcement_before_enabled
|
|
672
|
+
if audio_message_selection is not None:
|
|
673
|
+
body["audioMessageSelection"] = audio_message_selection
|
|
674
|
+
try:
|
|
675
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
676
|
+
except WebexError as e:
|
|
677
|
+
handle_rest_error(e)
|
|
678
|
+
typer.echo(f"Updated.")
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
@app.command("list-night-service")
|
|
683
|
+
def list_night_service(
|
|
684
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
685
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
686
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
687
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
688
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
689
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
690
|
+
):
|
|
691
|
+
"""Get Details for a Call Queue Night Service."""
|
|
692
|
+
api = get_api(debug=debug)
|
|
693
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/nightService"
|
|
694
|
+
params = {}
|
|
695
|
+
if limit > 0:
|
|
696
|
+
params["max"] = limit
|
|
697
|
+
if offset > 0:
|
|
698
|
+
params["start"] = offset
|
|
699
|
+
org_id = get_org_id()
|
|
700
|
+
if org_id is not None:
|
|
701
|
+
params["orgId"] = org_id
|
|
702
|
+
result = None
|
|
703
|
+
try:
|
|
704
|
+
result = api.session.rest_get(url, params=params)
|
|
705
|
+
except WebexError as e:
|
|
706
|
+
handle_rest_error(e)
|
|
707
|
+
result = result or []
|
|
708
|
+
items = result.get("audioFiles", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
709
|
+
if output == "json":
|
|
710
|
+
print_json(items)
|
|
711
|
+
else:
|
|
712
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
@app.command("update-night-service")
|
|
717
|
+
def update_night_service(
|
|
718
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
719
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
720
|
+
night_service_enabled: bool = typer.Option(None, "--night-service-enabled/--no-night-service-enabled", help="Enable or disable call queue night service routing policy."),
|
|
721
|
+
action: str = typer.Option(None, "--action", help="Choices: BUSY, TRANSFER"),
|
|
722
|
+
transfer_phone_number: str = typer.Option(None, "--transfer-phone-number", help="Call gets transferred to this number when action is set to `"),
|
|
723
|
+
play_announcement_before_enabled: bool = typer.Option(None, "--play-announcement-before-enabled/--no-play-announcement-before-enabled", help="Indicates whether an announcement plays to callers before th"),
|
|
724
|
+
announcement_mode: str = typer.Option(None, "--announcement-mode", help="Choices: NORMAL, MANUAL"),
|
|
725
|
+
audio_message_selection: str = typer.Option(None, "--audio-message-selection", help="Choices: DEFAULT, CUSTOM"),
|
|
726
|
+
business_hours_name: str = typer.Option(None, "--business-hours-name", help="Name of the schedule configured for a night service as one o"),
|
|
727
|
+
business_hours_level: str = typer.Option(None, "--business-hours-level", help="Choices: ORGANIZATION, LOCATION"),
|
|
728
|
+
force_night_service_enabled: bool = typer.Option(None, "--force-night-service-enabled/--no-force-night-service-enabled", help="Force night service regardless of business hour schedule."),
|
|
729
|
+
manual_audio_message_selection: str = typer.Option(None, "--manual-audio-message-selection", help="Choices: DEFAULT, CUSTOM"),
|
|
730
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
731
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
732
|
+
):
|
|
733
|
+
"""Update a Call Queue Night Service\n\nExample --json-body:\n '{"nightServiceEnabled":true,"playAnnouncementBeforeEnabled":true,"announcementMode":"NORMAL","audioMessageSelection":"DEFAULT","forceNightServiceEnabled":true,"manualAudioMessageSelection":"DEFAULT","action":"BUSY","transferPhoneNumber":"..."}'."""
|
|
734
|
+
api = get_api(debug=debug)
|
|
735
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/nightService"
|
|
736
|
+
params = {}
|
|
737
|
+
org_id = get_org_id()
|
|
738
|
+
if org_id is not None:
|
|
739
|
+
params["orgId"] = org_id
|
|
740
|
+
if json_body:
|
|
741
|
+
body = json.loads(json_body)
|
|
742
|
+
else:
|
|
743
|
+
body = {}
|
|
744
|
+
if night_service_enabled is not None:
|
|
745
|
+
body["nightServiceEnabled"] = night_service_enabled
|
|
746
|
+
if action is not None:
|
|
747
|
+
body["action"] = action
|
|
748
|
+
if transfer_phone_number is not None:
|
|
749
|
+
body["transferPhoneNumber"] = transfer_phone_number
|
|
750
|
+
if play_announcement_before_enabled is not None:
|
|
751
|
+
body["playAnnouncementBeforeEnabled"] = play_announcement_before_enabled
|
|
752
|
+
if announcement_mode is not None:
|
|
753
|
+
body["announcementMode"] = announcement_mode
|
|
754
|
+
if audio_message_selection is not None:
|
|
755
|
+
body["audioMessageSelection"] = audio_message_selection
|
|
756
|
+
if business_hours_name is not None:
|
|
757
|
+
body["businessHoursName"] = business_hours_name
|
|
758
|
+
if business_hours_level is not None:
|
|
759
|
+
body["businessHoursLevel"] = business_hours_level
|
|
760
|
+
if force_night_service_enabled is not None:
|
|
761
|
+
body["forceNightServiceEnabled"] = force_night_service_enabled
|
|
762
|
+
if manual_audio_message_selection is not None:
|
|
763
|
+
body["manualAudioMessageSelection"] = manual_audio_message_selection
|
|
764
|
+
try:
|
|
765
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
766
|
+
except WebexError as e:
|
|
767
|
+
handle_rest_error(e)
|
|
768
|
+
typer.echo(f"Updated.")
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
|
|
772
|
+
@app.command("list-forced-forward")
|
|
773
|
+
def list_forced_forward(
|
|
774
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
775
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
776
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
777
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
778
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
779
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
780
|
+
):
|
|
781
|
+
"""Get Details for a Call Queue Forced Forward."""
|
|
782
|
+
api = get_api(debug=debug)
|
|
783
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/forcedForward"
|
|
784
|
+
params = {}
|
|
785
|
+
if limit > 0:
|
|
786
|
+
params["max"] = limit
|
|
787
|
+
if offset > 0:
|
|
788
|
+
params["start"] = offset
|
|
789
|
+
org_id = get_org_id()
|
|
790
|
+
if org_id is not None:
|
|
791
|
+
params["orgId"] = org_id
|
|
792
|
+
result = None
|
|
793
|
+
try:
|
|
794
|
+
result = api.session.rest_get(url, params=params)
|
|
795
|
+
except WebexError as e:
|
|
796
|
+
handle_rest_error(e)
|
|
797
|
+
result = result or []
|
|
798
|
+
items = result.get("audioFiles", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
799
|
+
if output == "json":
|
|
800
|
+
print_json(items)
|
|
801
|
+
else:
|
|
802
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
803
|
+
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
@app.command("update-forced-forward")
|
|
807
|
+
def update_forced_forward(
|
|
808
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
809
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
810
|
+
forced_forward_enabled: bool = typer.Option(None, "--forced-forward-enabled/--no-forced-forward-enabled", help="Enable or disable call forced forward service routing policy"),
|
|
811
|
+
transfer_phone_number: str = typer.Option(None, "--transfer-phone-number", help="Call gets transferred to this number when action is set to `"),
|
|
812
|
+
play_announcement_before_enabled: bool = typer.Option(None, "--play-announcement-before-enabled/--no-play-announcement-before-enabled", help="Indicates whether an announcement plays to callers before th"),
|
|
813
|
+
audio_message_selection: str = typer.Option(None, "--audio-message-selection", help="Choices: DEFAULT, CUSTOM"),
|
|
814
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
815
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
816
|
+
):
|
|
817
|
+
"""Update a Call Queue Forced Forward Service\n\nExample --json-body:\n '{"forcedForwardEnabled":true,"playAnnouncementBeforeEnabled":true,"audioMessageSelection":"DEFAULT","transferPhoneNumber":"...","audioFiles":[{"id":"...","fileName":"...","mediaFileType":"...","level":"..."}]}'."""
|
|
818
|
+
api = get_api(debug=debug)
|
|
819
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/forcedForward"
|
|
820
|
+
params = {}
|
|
821
|
+
org_id = get_org_id()
|
|
822
|
+
if org_id is not None:
|
|
823
|
+
params["orgId"] = org_id
|
|
824
|
+
if json_body:
|
|
825
|
+
body = json.loads(json_body)
|
|
826
|
+
else:
|
|
827
|
+
body = {}
|
|
828
|
+
if forced_forward_enabled is not None:
|
|
829
|
+
body["forcedForwardEnabled"] = forced_forward_enabled
|
|
830
|
+
if transfer_phone_number is not None:
|
|
831
|
+
body["transferPhoneNumber"] = transfer_phone_number
|
|
832
|
+
if play_announcement_before_enabled is not None:
|
|
833
|
+
body["playAnnouncementBeforeEnabled"] = play_announcement_before_enabled
|
|
834
|
+
if audio_message_selection is not None:
|
|
835
|
+
body["audioMessageSelection"] = audio_message_selection
|
|
836
|
+
try:
|
|
837
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
838
|
+
except WebexError as e:
|
|
839
|
+
handle_rest_error(e)
|
|
840
|
+
typer.echo(f"Updated.")
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
@app.command("list-stranded-calls")
|
|
845
|
+
def list_stranded_calls(
|
|
846
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
847
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
848
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
849
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
850
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
851
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
852
|
+
):
|
|
853
|
+
"""Get Details for a Call Queue Stranded Calls."""
|
|
854
|
+
api = get_api(debug=debug)
|
|
855
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/strandedCalls"
|
|
856
|
+
params = {}
|
|
857
|
+
if limit > 0:
|
|
858
|
+
params["max"] = limit
|
|
859
|
+
if offset > 0:
|
|
860
|
+
params["start"] = offset
|
|
861
|
+
org_id = get_org_id()
|
|
862
|
+
if org_id is not None:
|
|
863
|
+
params["orgId"] = org_id
|
|
864
|
+
result = None
|
|
865
|
+
try:
|
|
866
|
+
result = api.session.rest_get(url, params=params)
|
|
867
|
+
except WebexError as e:
|
|
868
|
+
handle_rest_error(e)
|
|
869
|
+
result = result or []
|
|
870
|
+
items = result.get("audioFiles", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
871
|
+
if output == "json":
|
|
872
|
+
print_json(items)
|
|
873
|
+
else:
|
|
874
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
@app.command("update-stranded-calls")
|
|
879
|
+
def update_stranded_calls(
|
|
880
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
881
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
882
|
+
action: str = typer.Option(None, "--action", help="Choices: NONE, BUSY, TRANSFER, NIGHT_SERVICE, RINGING, ANNOUNCEMENT"),
|
|
883
|
+
transfer_phone_number: str = typer.Option(None, "--transfer-phone-number", help="Call gets transferred to this number when action is set to `"),
|
|
884
|
+
audio_message_selection: str = typer.Option(None, "--audio-message-selection", help="Choices: DEFAULT, CUSTOM"),
|
|
885
|
+
trigger_policy_when_all_agents_are_unreachable_enabled: bool = typer.Option(None, "--trigger-policy-when-all-agents-are-unreachable-enabled/--no-trigger-policy-when-all-agents-are-unreachable-enabled", help="Trigger stranded calls queue policy when all agents are unre"),
|
|
886
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
887
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
888
|
+
):
|
|
889
|
+
"""Update a Call Queue Stranded Calls Service\n\nExample --json-body:\n '{"action":"NONE","audioMessageSelection":"DEFAULT","transferPhoneNumber":"...","audioFiles":[{"id":"...","fileName":"...","mediaFileType":"...","level":"..."}],"triggerPolicyWhenAllAgentsAreUnreachableEnabled":true}'."""
|
|
890
|
+
api = get_api(debug=debug)
|
|
891
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/strandedCalls"
|
|
892
|
+
params = {}
|
|
893
|
+
org_id = get_org_id()
|
|
894
|
+
if org_id is not None:
|
|
895
|
+
params["orgId"] = org_id
|
|
896
|
+
if json_body:
|
|
897
|
+
body = json.loads(json_body)
|
|
898
|
+
else:
|
|
899
|
+
body = {}
|
|
900
|
+
if action is not None:
|
|
901
|
+
body["action"] = action
|
|
902
|
+
if transfer_phone_number is not None:
|
|
903
|
+
body["transferPhoneNumber"] = transfer_phone_number
|
|
904
|
+
if audio_message_selection is not None:
|
|
905
|
+
body["audioMessageSelection"] = audio_message_selection
|
|
906
|
+
if trigger_policy_when_all_agents_are_unreachable_enabled is not None:
|
|
907
|
+
body["triggerPolicyWhenAllAgentsAreUnreachableEnabled"] = trigger_policy_when_all_agents_are_unreachable_enabled
|
|
908
|
+
try:
|
|
909
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
910
|
+
except WebexError as e:
|
|
911
|
+
handle_rest_error(e)
|
|
912
|
+
typer.echo(f"Updated.")
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
@app.command("list-available-numbers-queues")
|
|
917
|
+
def list_available_numbers_queues(
|
|
918
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
919
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
920
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
921
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
922
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
923
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
924
|
+
):
|
|
925
|
+
"""Get Call Queue Primary Available Phone Numbers."""
|
|
926
|
+
api = get_api(debug=debug)
|
|
927
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/availableNumbers"
|
|
928
|
+
params = {}
|
|
929
|
+
if phone_number is not None:
|
|
930
|
+
params["phoneNumber"] = phone_number
|
|
931
|
+
if limit > 0:
|
|
932
|
+
params["max"] = limit
|
|
933
|
+
if offset > 0:
|
|
934
|
+
params["start"] = offset
|
|
935
|
+
org_id = get_org_id()
|
|
936
|
+
if org_id is not None:
|
|
937
|
+
params["orgId"] = org_id
|
|
938
|
+
result = None
|
|
939
|
+
try:
|
|
940
|
+
result = api.session.rest_get(url, params=params)
|
|
941
|
+
except WebexError as e:
|
|
942
|
+
handle_rest_error(e)
|
|
943
|
+
result = result or []
|
|
944
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
945
|
+
if output == "json":
|
|
946
|
+
print_json(items)
|
|
947
|
+
else:
|
|
948
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
@app.command("list-available-numbers-alternate")
|
|
953
|
+
def list_available_numbers_alternate(
|
|
954
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
955
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
956
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
957
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
958
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
959
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
960
|
+
):
|
|
961
|
+
"""Get Call Queue Alternate Available Phone Numbers."""
|
|
962
|
+
api = get_api(debug=debug)
|
|
963
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/alternate/availableNumbers"
|
|
964
|
+
params = {}
|
|
965
|
+
if phone_number is not None:
|
|
966
|
+
params["phoneNumber"] = phone_number
|
|
967
|
+
if limit > 0:
|
|
968
|
+
params["max"] = limit
|
|
969
|
+
if offset > 0:
|
|
970
|
+
params["start"] = offset
|
|
971
|
+
org_id = get_org_id()
|
|
972
|
+
if org_id is not None:
|
|
973
|
+
params["orgId"] = org_id
|
|
974
|
+
result = None
|
|
975
|
+
try:
|
|
976
|
+
result = api.session.rest_get(url, params=params)
|
|
977
|
+
except WebexError as e:
|
|
978
|
+
handle_rest_error(e)
|
|
979
|
+
result = result or []
|
|
980
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
981
|
+
if output == "json":
|
|
982
|
+
print_json(items)
|
|
983
|
+
else:
|
|
984
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
@app.command("list-available-numbers-call-forwarding")
|
|
989
|
+
def list_available_numbers_call_forwarding(
|
|
990
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
991
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
992
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
993
|
+
extension: str = typer.Option(None, "--extension", help="Returns the list of PSTN phone numbers with the given `exten"),
|
|
994
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
995
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
996
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
997
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
998
|
+
):
|
|
999
|
+
"""Get Call Queue Call Forward Available Phone Numbers."""
|
|
1000
|
+
api = get_api(debug=debug)
|
|
1001
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/callForwarding/availableNumbers"
|
|
1002
|
+
params = {}
|
|
1003
|
+
if phone_number is not None:
|
|
1004
|
+
params["phoneNumber"] = phone_number
|
|
1005
|
+
if owner_name is not None:
|
|
1006
|
+
params["ownerName"] = owner_name
|
|
1007
|
+
if extension is not None:
|
|
1008
|
+
params["extension"] = extension
|
|
1009
|
+
if limit > 0:
|
|
1010
|
+
params["max"] = limit
|
|
1011
|
+
if offset > 0:
|
|
1012
|
+
params["start"] = offset
|
|
1013
|
+
org_id = get_org_id()
|
|
1014
|
+
if org_id is not None:
|
|
1015
|
+
params["orgId"] = org_id
|
|
1016
|
+
result = None
|
|
1017
|
+
try:
|
|
1018
|
+
result = api.session.rest_get(url, params=params)
|
|
1019
|
+
except WebexError as e:
|
|
1020
|
+
handle_rest_error(e)
|
|
1021
|
+
result = result or []
|
|
1022
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1023
|
+
if output == "json":
|
|
1024
|
+
print_json(items)
|
|
1025
|
+
else:
|
|
1026
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1027
|
+
|
|
1028
|
+
|
|
1029
|
+
|
|
1030
|
+
@app.command("list-available-agents-queues")
|
|
1031
|
+
def list_available_agents_queues(
|
|
1032
|
+
location_id: str = typer.Option(..., "--location-id", help="The location ID of the call queue. Temporary mandatory query"),
|
|
1033
|
+
name: str = typer.Option(None, "--name", help="Search based on name (user first and last name combination)."),
|
|
1034
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Search based on number or extension."),
|
|
1035
|
+
order: str = typer.Option(None, "--order", help="Order the available agents according to the designated field"),
|
|
1036
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1037
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1038
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1039
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1040
|
+
):
|
|
1041
|
+
"""Get Call Queue Available Agents."""
|
|
1042
|
+
api = get_api(debug=debug)
|
|
1043
|
+
url = f"https://webexapis.com/v1/telephony/config/queues/agents/availableAgents"
|
|
1044
|
+
params = {}
|
|
1045
|
+
if location_id is not None:
|
|
1046
|
+
params["locationId"] = location_id
|
|
1047
|
+
if name is not None:
|
|
1048
|
+
params["name"] = name
|
|
1049
|
+
if phone_number is not None:
|
|
1050
|
+
params["phoneNumber"] = phone_number
|
|
1051
|
+
if order is not None:
|
|
1052
|
+
params["order"] = order
|
|
1053
|
+
if limit > 0:
|
|
1054
|
+
params["max"] = limit
|
|
1055
|
+
if offset > 0:
|
|
1056
|
+
params["start"] = offset
|
|
1057
|
+
org_id = get_org_id()
|
|
1058
|
+
if org_id is not None:
|
|
1059
|
+
params["orgId"] = org_id
|
|
1060
|
+
result = None
|
|
1061
|
+
try:
|
|
1062
|
+
result = api.session.rest_get(url, params=params)
|
|
1063
|
+
except WebexError as e:
|
|
1064
|
+
handle_rest_error(e)
|
|
1065
|
+
result = result or []
|
|
1066
|
+
items = result.get("agents", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1067
|
+
if output == "json":
|
|
1068
|
+
print_json(items)
|
|
1069
|
+
else:
|
|
1070
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
|
|
1074
|
+
@app.command("list-supervisors")
|
|
1075
|
+
def list_supervisors(
|
|
1076
|
+
name: str = typer.Option(None, "--name", help="Only return the supervisors that match the given name."),
|
|
1077
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Only return the supervisors that match the given phone numbe"),
|
|
1078
|
+
order: str = typer.Option(None, "--order", help="Sort results alphabetically by supervisor name, in ascending"),
|
|
1079
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Returns only the list of supervisors with Customer Assist li"),
|
|
1080
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1081
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1082
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1083
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1084
|
+
):
|
|
1085
|
+
"""Get List of Supervisors with Customer Assist."""
|
|
1086
|
+
api = get_api(debug=debug)
|
|
1087
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors"
|
|
1088
|
+
params = {}
|
|
1089
|
+
if name is not None:
|
|
1090
|
+
params["name"] = name
|
|
1091
|
+
if phone_number is not None:
|
|
1092
|
+
params["phoneNumber"] = phone_number
|
|
1093
|
+
if order is not None:
|
|
1094
|
+
params["order"] = order
|
|
1095
|
+
if has_cx_essentials is not None:
|
|
1096
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1097
|
+
if limit > 0:
|
|
1098
|
+
params["max"] = limit
|
|
1099
|
+
if offset > 0:
|
|
1100
|
+
params["start"] = offset
|
|
1101
|
+
org_id = get_org_id()
|
|
1102
|
+
if org_id is not None:
|
|
1103
|
+
params["orgId"] = org_id
|
|
1104
|
+
result = None
|
|
1105
|
+
try:
|
|
1106
|
+
result = api.session.rest_get(url, params=params)
|
|
1107
|
+
except WebexError as e:
|
|
1108
|
+
handle_rest_error(e)
|
|
1109
|
+
result = result or []
|
|
1110
|
+
items = result.get("supervisors", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1111
|
+
if output == "json":
|
|
1112
|
+
print_json(items)
|
|
1113
|
+
else:
|
|
1114
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
|
|
1118
|
+
@app.command("create-supervisors")
|
|
1119
|
+
def create_supervisors(
|
|
1120
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Creates a Customer Assist queue supervisor, when `true`. Cus"),
|
|
1121
|
+
id_param: str = typer.Option(None, "--id", help="(required) A unique identifier for the supervisor."),
|
|
1122
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1123
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1124
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1125
|
+
):
|
|
1126
|
+
"""Create a Supervisor with Customer Assist\n\nExample --json-body:\n '{"id":"...","agents":[{"id":"..."}]}'."""
|
|
1127
|
+
api = get_api(debug=debug)
|
|
1128
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors"
|
|
1129
|
+
params = {}
|
|
1130
|
+
if has_cx_essentials is not None:
|
|
1131
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1132
|
+
org_id = get_org_id()
|
|
1133
|
+
if org_id is not None:
|
|
1134
|
+
params["orgId"] = org_id
|
|
1135
|
+
if json_body:
|
|
1136
|
+
body = json.loads(json_body)
|
|
1137
|
+
else:
|
|
1138
|
+
body = {}
|
|
1139
|
+
if id_param is not None:
|
|
1140
|
+
body["id"] = id_param
|
|
1141
|
+
_missing = [f for f in ['id'] if f not in body or body[f] is None]
|
|
1142
|
+
if _missing:
|
|
1143
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1144
|
+
raise typer.Exit(1)
|
|
1145
|
+
try:
|
|
1146
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1147
|
+
except WebexError as e:
|
|
1148
|
+
handle_rest_error(e)
|
|
1149
|
+
if output == "json":
|
|
1150
|
+
print_json(result)
|
|
1151
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1152
|
+
typer.echo(f"Created: {result['id']}")
|
|
1153
|
+
elif not result or result == {}:
|
|
1154
|
+
typer.echo("Created.")
|
|
1155
|
+
else:
|
|
1156
|
+
print_json(result)
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
|
|
1160
|
+
@app.command("delete-supervisors-config")
|
|
1161
|
+
def delete_supervisors_config(
|
|
1162
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1163
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1164
|
+
):
|
|
1165
|
+
"""Delete the Call Queue or Customer Assist Supervisors."""
|
|
1166
|
+
if not force:
|
|
1167
|
+
typer.confirm("Delete this resource?", abort=True)
|
|
1168
|
+
api = get_api(debug=debug)
|
|
1169
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors"
|
|
1170
|
+
params = {}
|
|
1171
|
+
org_id = get_org_id()
|
|
1172
|
+
if org_id is not None:
|
|
1173
|
+
params["orgId"] = org_id
|
|
1174
|
+
try:
|
|
1175
|
+
api.session.rest_delete(url, params=params)
|
|
1176
|
+
except WebexError as e:
|
|
1177
|
+
handle_rest_error(e)
|
|
1178
|
+
typer.echo("Deleted.")
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
|
|
1182
|
+
@app.command("show-supervisors")
|
|
1183
|
+
def show_supervisors(
|
|
1184
|
+
supervisor_id: str = typer.Argument(help="supervisorId"),
|
|
1185
|
+
max: str = typer.Option(None, "--max", help="Limit the number of objects returned to this maximum count."),
|
|
1186
|
+
start: str = typer.Option(None, "--start", help="Start at the zero-based offset in the list of matching objec"),
|
|
1187
|
+
name: str = typer.Option(None, "--name", help="Only return the agents that match the given name."),
|
|
1188
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Only return agents that match the given phone number, extens"),
|
|
1189
|
+
order: str = typer.Option(None, "--order", help="Sort results alphabetically by supervisor name, in ascending"),
|
|
1190
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Must be set to `true`, to view the details of a supervisor w"),
|
|
1191
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1192
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1193
|
+
):
|
|
1194
|
+
"""Get Supervisor Detail with Customer Assist."""
|
|
1195
|
+
api = get_api(debug=debug)
|
|
1196
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors/{supervisor_id}"
|
|
1197
|
+
params = {}
|
|
1198
|
+
if max is not None:
|
|
1199
|
+
params["max"] = max
|
|
1200
|
+
if start is not None:
|
|
1201
|
+
params["start"] = start
|
|
1202
|
+
if name is not None:
|
|
1203
|
+
params["name"] = name
|
|
1204
|
+
if phone_number is not None:
|
|
1205
|
+
params["phoneNumber"] = phone_number
|
|
1206
|
+
if order is not None:
|
|
1207
|
+
params["order"] = order
|
|
1208
|
+
if has_cx_essentials is not None:
|
|
1209
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1210
|
+
org_id = get_org_id()
|
|
1211
|
+
if org_id is not None:
|
|
1212
|
+
params["orgId"] = org_id
|
|
1213
|
+
try:
|
|
1214
|
+
result = api.session.rest_get(url, params=params)
|
|
1215
|
+
except WebexError as e:
|
|
1216
|
+
handle_rest_error(e)
|
|
1217
|
+
if output == "json":
|
|
1218
|
+
print_json(result)
|
|
1219
|
+
else:
|
|
1220
|
+
if isinstance(result, dict):
|
|
1221
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1222
|
+
elif isinstance(result, list):
|
|
1223
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1224
|
+
else:
|
|
1225
|
+
print_json(result)
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
|
|
1229
|
+
@app.command("update-supervisors")
|
|
1230
|
+
def update_supervisors(
|
|
1231
|
+
supervisor_id: str = typer.Argument(help="supervisorId"),
|
|
1232
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Must be set to `true` to modify a supervisor with Customer A"),
|
|
1233
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1234
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1235
|
+
):
|
|
1236
|
+
"""Assign or Unassign Agents to Supervisor with Customer Assist\n\nExample --json-body:\n '{"agents":[{"id":"...","action":"..."}]}'."""
|
|
1237
|
+
api = get_api(debug=debug)
|
|
1238
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors/{supervisor_id}"
|
|
1239
|
+
params = {}
|
|
1240
|
+
if has_cx_essentials is not None:
|
|
1241
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1242
|
+
org_id = get_org_id()
|
|
1243
|
+
if org_id is not None:
|
|
1244
|
+
params["orgId"] = org_id
|
|
1245
|
+
if json_body:
|
|
1246
|
+
body = json.loads(json_body)
|
|
1247
|
+
else:
|
|
1248
|
+
body = {}
|
|
1249
|
+
try:
|
|
1250
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1251
|
+
except WebexError as e:
|
|
1252
|
+
handle_rest_error(e)
|
|
1253
|
+
typer.echo(f"Updated.")
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
|
|
1257
|
+
@app.command("delete-supervisors-config-1")
|
|
1258
|
+
def delete_supervisors_config_1(
|
|
1259
|
+
supervisor_id: str = typer.Argument(help="supervisorId"),
|
|
1260
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1261
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1262
|
+
):
|
|
1263
|
+
"""Delete a Supervisor."""
|
|
1264
|
+
if not force:
|
|
1265
|
+
typer.confirm(f"Delete {supervisor_id}?", abort=True)
|
|
1266
|
+
api = get_api(debug=debug)
|
|
1267
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors/{supervisor_id}"
|
|
1268
|
+
params = {}
|
|
1269
|
+
org_id = get_org_id()
|
|
1270
|
+
if org_id is not None:
|
|
1271
|
+
params["orgId"] = org_id
|
|
1272
|
+
try:
|
|
1273
|
+
api.session.rest_delete(url, params=params)
|
|
1274
|
+
except WebexError as e:
|
|
1275
|
+
handle_rest_error(e)
|
|
1276
|
+
typer.echo(f"Deleted: {supervisor_id}")
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
@app.command("list-available-supervisors")
|
|
1281
|
+
def list_available_supervisors(
|
|
1282
|
+
name: str = typer.Option(None, "--name", help="Only return the supervisors that match the given name."),
|
|
1283
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Only return the supervisors that match the given phone numbe"),
|
|
1284
|
+
order: str = typer.Option(None, "--order", help="Sort results alphabetically by supervisor name, in ascending"),
|
|
1285
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Returns only the list of available supervisors with Customer"),
|
|
1286
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1287
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1288
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1289
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1290
|
+
):
|
|
1291
|
+
"""List Available Supervisors with Customer Assist."""
|
|
1292
|
+
api = get_api(debug=debug)
|
|
1293
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors/availableSupervisors"
|
|
1294
|
+
params = {}
|
|
1295
|
+
if name is not None:
|
|
1296
|
+
params["name"] = name
|
|
1297
|
+
if phone_number is not None:
|
|
1298
|
+
params["phoneNumber"] = phone_number
|
|
1299
|
+
if order is not None:
|
|
1300
|
+
params["order"] = order
|
|
1301
|
+
if has_cx_essentials is not None:
|
|
1302
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1303
|
+
if limit > 0:
|
|
1304
|
+
params["max"] = limit
|
|
1305
|
+
if offset > 0:
|
|
1306
|
+
params["start"] = offset
|
|
1307
|
+
org_id = get_org_id()
|
|
1308
|
+
if org_id is not None:
|
|
1309
|
+
params["orgId"] = org_id
|
|
1310
|
+
result = None
|
|
1311
|
+
try:
|
|
1312
|
+
result = api.session.rest_get(url, params=params)
|
|
1313
|
+
except WebexError as e:
|
|
1314
|
+
handle_rest_error(e)
|
|
1315
|
+
result = result or []
|
|
1316
|
+
items = result.get("supervisors", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1317
|
+
if output == "json":
|
|
1318
|
+
print_json(items)
|
|
1319
|
+
else:
|
|
1320
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
@app.command("list-available-agents-supervisors")
|
|
1325
|
+
def list_available_agents_supervisors(
|
|
1326
|
+
name: str = typer.Option(None, "--name", help="Returns only the agents that match the given name."),
|
|
1327
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Returns only the agents that match the phone number, extensi"),
|
|
1328
|
+
order: str = typer.Option(None, "--order", help="Sort results alphabetically by supervisor name, in ascending"),
|
|
1329
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Returns only the list of available agents with Customer Assi"),
|
|
1330
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1331
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1332
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1333
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1334
|
+
):
|
|
1335
|
+
"""List Available Agents with Customer Assist."""
|
|
1336
|
+
api = get_api(debug=debug)
|
|
1337
|
+
url = f"https://webexapis.com/v1/telephony/config/supervisors/availableAgents"
|
|
1338
|
+
params = {}
|
|
1339
|
+
if name is not None:
|
|
1340
|
+
params["name"] = name
|
|
1341
|
+
if phone_number is not None:
|
|
1342
|
+
params["phoneNumber"] = phone_number
|
|
1343
|
+
if order is not None:
|
|
1344
|
+
params["order"] = order
|
|
1345
|
+
if has_cx_essentials is not None:
|
|
1346
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1347
|
+
if limit > 0:
|
|
1348
|
+
params["max"] = limit
|
|
1349
|
+
if offset > 0:
|
|
1350
|
+
params["start"] = offset
|
|
1351
|
+
org_id = get_org_id()
|
|
1352
|
+
if org_id is not None:
|
|
1353
|
+
params["orgId"] = org_id
|
|
1354
|
+
result = None
|
|
1355
|
+
try:
|
|
1356
|
+
result = api.session.rest_get(url, params=params)
|
|
1357
|
+
except WebexError as e:
|
|
1358
|
+
handle_rest_error(e)
|
|
1359
|
+
result = result or []
|
|
1360
|
+
items = result.get("agents", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1361
|
+
if output == "json":
|
|
1362
|
+
print_json(items)
|
|
1363
|
+
else:
|
|
1364
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
@app.command("list-agents")
|
|
1369
|
+
def list_agents(
|
|
1370
|
+
location_id: str = typer.Option(None, "--location-id", help="Return only the call queue agents in this location."),
|
|
1371
|
+
queue_id: str = typer.Option(None, "--queue-id", help="Only return call queue agents with the matching queue ID."),
|
|
1372
|
+
name: str = typer.Option(None, "--name", help="Returns only the list of call queue agents that match the gi"),
|
|
1373
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Returns only the list of call queue agents that match the gi"),
|
|
1374
|
+
join_enabled: str = typer.Option(None, "--join-enabled", help="Returns only the list of call queue agents that match the gi"),
|
|
1375
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Returns only the list of call queues with Customer Assist li"),
|
|
1376
|
+
order: str = typer.Option(None, "--order", help="Sort results alphabetically by call queue agent's name, in a"),
|
|
1377
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1378
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1379
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1380
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1381
|
+
):
|
|
1382
|
+
"""Read the List of Call Queue Agents with Customer Assist."""
|
|
1383
|
+
api = get_api(debug=debug)
|
|
1384
|
+
url = f"https://webexapis.com/v1/telephony/config/queues/agents"
|
|
1385
|
+
params = {}
|
|
1386
|
+
if location_id is not None:
|
|
1387
|
+
params["locationId"] = location_id
|
|
1388
|
+
if queue_id is not None:
|
|
1389
|
+
params["queueId"] = queue_id
|
|
1390
|
+
if name is not None:
|
|
1391
|
+
params["name"] = name
|
|
1392
|
+
if phone_number is not None:
|
|
1393
|
+
params["phoneNumber"] = phone_number
|
|
1394
|
+
if join_enabled is not None:
|
|
1395
|
+
params["joinEnabled"] = join_enabled
|
|
1396
|
+
if has_cx_essentials is not None:
|
|
1397
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1398
|
+
if order is not None:
|
|
1399
|
+
params["order"] = order
|
|
1400
|
+
if limit > 0:
|
|
1401
|
+
params["max"] = limit
|
|
1402
|
+
if offset > 0:
|
|
1403
|
+
params["start"] = offset
|
|
1404
|
+
org_id = get_org_id()
|
|
1405
|
+
if org_id is not None:
|
|
1406
|
+
params["orgId"] = org_id
|
|
1407
|
+
try:
|
|
1408
|
+
if limit > 0:
|
|
1409
|
+
result = api.session.rest_get(url, params=params)
|
|
1410
|
+
result = result or {}
|
|
1411
|
+
items = result.get("agents", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1412
|
+
else:
|
|
1413
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="agents"))
|
|
1414
|
+
except WebexError as e:
|
|
1415
|
+
handle_rest_error(e)
|
|
1416
|
+
if output == "json":
|
|
1417
|
+
print_json(items)
|
|
1418
|
+
else:
|
|
1419
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1420
|
+
|
|
1421
|
+
|
|
1422
|
+
|
|
1423
|
+
@app.command("show-agents")
|
|
1424
|
+
def show_agents(
|
|
1425
|
+
id: str = typer.Argument(help="id"),
|
|
1426
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Must be set to `true` to view the details of an agent with C"),
|
|
1427
|
+
max: str = typer.Option(..., "--max", help="Limit the number of objects returned to this maximum count."),
|
|
1428
|
+
start: str = typer.Option(..., "--start", help="Start at the zero-based offset in the list of matching objec"),
|
|
1429
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1430
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1431
|
+
):
|
|
1432
|
+
"""Get Details for a Call Queue Agent with Customer Assist."""
|
|
1433
|
+
api = get_api(debug=debug)
|
|
1434
|
+
url = f"https://webexapis.com/v1/telephony/config/queues/agents/{id}"
|
|
1435
|
+
params = {}
|
|
1436
|
+
if has_cx_essentials is not None:
|
|
1437
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1438
|
+
if max is not None:
|
|
1439
|
+
params["max"] = max
|
|
1440
|
+
if start is not None:
|
|
1441
|
+
params["start"] = start
|
|
1442
|
+
org_id = get_org_id()
|
|
1443
|
+
if org_id is not None:
|
|
1444
|
+
params["orgId"] = org_id
|
|
1445
|
+
try:
|
|
1446
|
+
result = api.session.rest_get(url, params=params)
|
|
1447
|
+
except WebexError as e:
|
|
1448
|
+
handle_rest_error(e)
|
|
1449
|
+
if output == "json":
|
|
1450
|
+
print_json(result)
|
|
1451
|
+
else:
|
|
1452
|
+
if isinstance(result, dict):
|
|
1453
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1454
|
+
elif isinstance(result, list):
|
|
1455
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1456
|
+
else:
|
|
1457
|
+
print_json(result)
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
@app.command("update-settings-agents")
|
|
1462
|
+
def update_settings_agents(
|
|
1463
|
+
id: str = typer.Argument(help="id"),
|
|
1464
|
+
has_cx_essentials: str = typer.Option(None, "--has-cx-essentials", help="Must be set to `true` to modify an agent that has Customer A"),
|
|
1465
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1466
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1467
|
+
):
|
|
1468
|
+
"""Update an Agent's Settings of One or More Call Queues with Customer Assist\n\nExample --json-body:\n '{"settings":[{"queueId":"...","joinEnabled":"..."}]}'."""
|
|
1469
|
+
api = get_api(debug=debug)
|
|
1470
|
+
url = f"https://webexapis.com/v1/telephony/config/queues/agents/{id}/settings"
|
|
1471
|
+
params = {}
|
|
1472
|
+
if has_cx_essentials is not None:
|
|
1473
|
+
params["hasCxEssentials"] = has_cx_essentials
|
|
1474
|
+
org_id = get_org_id()
|
|
1475
|
+
if org_id is not None:
|
|
1476
|
+
params["orgId"] = org_id
|
|
1477
|
+
if json_body:
|
|
1478
|
+
body = json.loads(json_body)
|
|
1479
|
+
else:
|
|
1480
|
+
body = {}
|
|
1481
|
+
try:
|
|
1482
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1483
|
+
except WebexError as e:
|
|
1484
|
+
handle_rest_error(e)
|
|
1485
|
+
typer.echo(f"Updated.")
|
|
1486
|
+
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
@app.command("switch-mode-for")
|
|
1490
|
+
def switch_mode_for(
|
|
1491
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1492
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1493
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1494
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1495
|
+
):
|
|
1496
|
+
"""Switch Mode for Call Forwarding Settings for a Call Queue."""
|
|
1497
|
+
api = get_api(debug=debug)
|
|
1498
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/callForwarding/actions/switchMode/invoke"
|
|
1499
|
+
params = {}
|
|
1500
|
+
org_id = get_org_id()
|
|
1501
|
+
if org_id is not None:
|
|
1502
|
+
params["orgId"] = org_id
|
|
1503
|
+
if json_body:
|
|
1504
|
+
body = json.loads(json_body)
|
|
1505
|
+
else:
|
|
1506
|
+
body = {}
|
|
1507
|
+
try:
|
|
1508
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1509
|
+
except WebexError as e:
|
|
1510
|
+
handle_rest_error(e)
|
|
1511
|
+
print_json(result)
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
@app.command("list-dnis")
|
|
1516
|
+
def list_dnis(
|
|
1517
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1518
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1519
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1520
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1521
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1522
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1523
|
+
):
|
|
1524
|
+
"""Get List of DNIS for a Call Queue."""
|
|
1525
|
+
api = get_api(debug=debug)
|
|
1526
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis"
|
|
1527
|
+
params = {}
|
|
1528
|
+
if limit > 0:
|
|
1529
|
+
params["max"] = limit
|
|
1530
|
+
if offset > 0:
|
|
1531
|
+
params["start"] = offset
|
|
1532
|
+
org_id = get_org_id()
|
|
1533
|
+
if org_id is not None:
|
|
1534
|
+
params["orgId"] = org_id
|
|
1535
|
+
result = None
|
|
1536
|
+
try:
|
|
1537
|
+
result = api.session.rest_get(url, params=params)
|
|
1538
|
+
except WebexError as e:
|
|
1539
|
+
handle_rest_error(e)
|
|
1540
|
+
result = result or []
|
|
1541
|
+
items = result.get("dnisList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1542
|
+
if output == "json":
|
|
1543
|
+
print_json(items)
|
|
1544
|
+
else:
|
|
1545
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1546
|
+
|
|
1547
|
+
|
|
1548
|
+
|
|
1549
|
+
@app.command("create-dnis")
|
|
1550
|
+
def create_dnis(
|
|
1551
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1552
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1553
|
+
name: str = typer.Option(None, "--name", help="(required) Name of the DNIS. Must be unique across the call queue."),
|
|
1554
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Phone number of the DNIS. Must be a valid phone number from"),
|
|
1555
|
+
extension: str = typer.Option(None, "--extension", help="Extension of the DNIS. Either phoneNumber or extension is re"),
|
|
1556
|
+
ring_pattern: str = typer.Option(None, "--ring-pattern", help="(required) Choices: NORMAL, LONG_LONG, SHORT_SHORT_LONG, SHORT_LONG_SHORT"),
|
|
1557
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1558
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1559
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1560
|
+
):
|
|
1561
|
+
"""Create a DNIS for a Call Queue."""
|
|
1562
|
+
api = get_api(debug=debug)
|
|
1563
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis"
|
|
1564
|
+
params = {}
|
|
1565
|
+
org_id = get_org_id()
|
|
1566
|
+
if org_id is not None:
|
|
1567
|
+
params["orgId"] = org_id
|
|
1568
|
+
if json_body:
|
|
1569
|
+
body = json.loads(json_body)
|
|
1570
|
+
else:
|
|
1571
|
+
body = {}
|
|
1572
|
+
if name is not None:
|
|
1573
|
+
body["name"] = name
|
|
1574
|
+
if phone_number is not None:
|
|
1575
|
+
body["phoneNumber"] = phone_number
|
|
1576
|
+
if extension is not None:
|
|
1577
|
+
body["extension"] = extension
|
|
1578
|
+
if ring_pattern is not None:
|
|
1579
|
+
body["ringPattern"] = ring_pattern
|
|
1580
|
+
_missing = [f for f in ['name', 'ringPattern'] if f not in body or body[f] is None]
|
|
1581
|
+
if _missing:
|
|
1582
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1583
|
+
raise typer.Exit(1)
|
|
1584
|
+
try:
|
|
1585
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1586
|
+
except WebexError as e:
|
|
1587
|
+
handle_rest_error(e)
|
|
1588
|
+
if output == "json":
|
|
1589
|
+
print_json(result)
|
|
1590
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1591
|
+
typer.echo(f"Created: {result['id']}")
|
|
1592
|
+
elif not result or result == {}:
|
|
1593
|
+
typer.echo("Created.")
|
|
1594
|
+
else:
|
|
1595
|
+
print_json(result)
|
|
1596
|
+
|
|
1597
|
+
|
|
1598
|
+
|
|
1599
|
+
@app.command("delete-dnis-queues")
|
|
1600
|
+
def delete_dnis_queues(
|
|
1601
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1602
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1603
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1604
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1605
|
+
):
|
|
1606
|
+
"""Bulk Delete DNIS for a Call Queue."""
|
|
1607
|
+
if not force:
|
|
1608
|
+
typer.confirm(f"Delete {queue_id}?", abort=True)
|
|
1609
|
+
api = get_api(debug=debug)
|
|
1610
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis"
|
|
1611
|
+
params = {}
|
|
1612
|
+
org_id = get_org_id()
|
|
1613
|
+
if org_id is not None:
|
|
1614
|
+
params["orgId"] = org_id
|
|
1615
|
+
try:
|
|
1616
|
+
api.session.rest_delete(url, params=params)
|
|
1617
|
+
except WebexError as e:
|
|
1618
|
+
handle_rest_error(e)
|
|
1619
|
+
typer.echo(f"Deleted: {queue_id}")
|
|
1620
|
+
|
|
1621
|
+
|
|
1622
|
+
|
|
1623
|
+
@app.command("show-dnis")
|
|
1624
|
+
def show_dnis(
|
|
1625
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1626
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1627
|
+
dnis_id: str = typer.Argument(help="dnisId"),
|
|
1628
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1629
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1630
|
+
):
|
|
1631
|
+
"""Get a DNIS for a Call Queue."""
|
|
1632
|
+
api = get_api(debug=debug)
|
|
1633
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/{dnis_id}"
|
|
1634
|
+
params = {}
|
|
1635
|
+
org_id = get_org_id()
|
|
1636
|
+
if org_id is not None:
|
|
1637
|
+
params["orgId"] = org_id
|
|
1638
|
+
try:
|
|
1639
|
+
result = api.session.rest_get(url, params=params)
|
|
1640
|
+
except WebexError as e:
|
|
1641
|
+
handle_rest_error(e)
|
|
1642
|
+
if output == "json":
|
|
1643
|
+
print_json(result)
|
|
1644
|
+
else:
|
|
1645
|
+
if isinstance(result, dict):
|
|
1646
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1647
|
+
elif isinstance(result, list):
|
|
1648
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1649
|
+
else:
|
|
1650
|
+
print_json(result)
|
|
1651
|
+
|
|
1652
|
+
|
|
1653
|
+
|
|
1654
|
+
@app.command("update-dnis")
|
|
1655
|
+
def update_dnis(
|
|
1656
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1657
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1658
|
+
dnis_id: str = typer.Argument(help="dnisId"),
|
|
1659
|
+
name: str = typer.Option(None, "--name", help="Name of the DNIS. Must be unique across the call queue."),
|
|
1660
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Phone number of the DNIS. Set to `null` to remove the phone"),
|
|
1661
|
+
extension: str = typer.Option(None, "--extension", help="Extension of the DNIS. Set to `null` to remove the extension"),
|
|
1662
|
+
ring_pattern: str = typer.Option(None, "--ring-pattern", help="Choices: NORMAL, LONG_LONG, SHORT_SHORT_LONG, SHORT_LONG_SHORT"),
|
|
1663
|
+
custom_dnis_announcement_settings_enabled: bool = typer.Option(None, "--custom-dnis-announcement-settings-enabled/--no-custom-dnis-announcement-settings-enabled", help="Use custom announcement settings for the DNIS."),
|
|
1664
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1665
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1666
|
+
):
|
|
1667
|
+
"""Modify a DNIS for a Call Queue."""
|
|
1668
|
+
api = get_api(debug=debug)
|
|
1669
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/{dnis_id}"
|
|
1670
|
+
params = {}
|
|
1671
|
+
org_id = get_org_id()
|
|
1672
|
+
if org_id is not None:
|
|
1673
|
+
params["orgId"] = org_id
|
|
1674
|
+
if json_body:
|
|
1675
|
+
body = json.loads(json_body)
|
|
1676
|
+
else:
|
|
1677
|
+
body = {}
|
|
1678
|
+
if name is not None:
|
|
1679
|
+
body["name"] = name
|
|
1680
|
+
if phone_number is not None:
|
|
1681
|
+
body["phoneNumber"] = phone_number
|
|
1682
|
+
if extension is not None:
|
|
1683
|
+
body["extension"] = extension
|
|
1684
|
+
if ring_pattern is not None:
|
|
1685
|
+
body["ringPattern"] = ring_pattern
|
|
1686
|
+
if custom_dnis_announcement_settings_enabled is not None:
|
|
1687
|
+
body["customDnisAnnouncementSettingsEnabled"] = custom_dnis_announcement_settings_enabled
|
|
1688
|
+
try:
|
|
1689
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1690
|
+
except WebexError as e:
|
|
1691
|
+
handle_rest_error(e)
|
|
1692
|
+
typer.echo(f"Updated.")
|
|
1693
|
+
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
@app.command("delete-dnis-queues-1")
|
|
1697
|
+
def delete_dnis_queues_1(
|
|
1698
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1699
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1700
|
+
dnis_id: str = typer.Argument(help="dnisId"),
|
|
1701
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1702
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1703
|
+
):
|
|
1704
|
+
"""Delete a DNIS for a Call Queue."""
|
|
1705
|
+
if not force:
|
|
1706
|
+
typer.confirm(f"Delete {dnis_id}?", abort=True)
|
|
1707
|
+
api = get_api(debug=debug)
|
|
1708
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/{dnis_id}"
|
|
1709
|
+
params = {}
|
|
1710
|
+
org_id = get_org_id()
|
|
1711
|
+
if org_id is not None:
|
|
1712
|
+
params["orgId"] = org_id
|
|
1713
|
+
try:
|
|
1714
|
+
api.session.rest_delete(url, params=params)
|
|
1715
|
+
except WebexError as e:
|
|
1716
|
+
handle_rest_error(e)
|
|
1717
|
+
typer.echo(f"Deleted: {dnis_id}")
|
|
1718
|
+
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
@app.command("show-settings")
|
|
1722
|
+
def show_settings(
|
|
1723
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1724
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1725
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1726
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1727
|
+
):
|
|
1728
|
+
"""Get DNIS Settings for a Call Queue."""
|
|
1729
|
+
api = get_api(debug=debug)
|
|
1730
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/settings"
|
|
1731
|
+
params = {}
|
|
1732
|
+
org_id = get_org_id()
|
|
1733
|
+
if org_id is not None:
|
|
1734
|
+
params["orgId"] = org_id
|
|
1735
|
+
try:
|
|
1736
|
+
result = api.session.rest_get(url, params=params)
|
|
1737
|
+
except WebexError as e:
|
|
1738
|
+
handle_rest_error(e)
|
|
1739
|
+
if output == "json":
|
|
1740
|
+
print_json(result)
|
|
1741
|
+
else:
|
|
1742
|
+
if isinstance(result, dict):
|
|
1743
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1744
|
+
elif isinstance(result, list):
|
|
1745
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1746
|
+
else:
|
|
1747
|
+
print_json(result)
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
|
|
1751
|
+
@app.command("update-settings-dnis")
|
|
1752
|
+
def update_settings_dnis(
|
|
1753
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1754
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1755
|
+
distinctive_ringing_enabled: bool = typer.Option(None, "--distinctive-ringing-enabled/--no-distinctive-ringing-enabled", help="Whether distinctive ringing is enabled for the queue."),
|
|
1756
|
+
display_dnis_name_and_number_enabled: bool = typer.Option(None, "--display-dnis-name-and-number-enabled/--no-display-dnis-name-and-number-enabled", help="Whether the DNIS name and number is displayed to agents."),
|
|
1757
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1758
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1759
|
+
):
|
|
1760
|
+
"""Modify DNIS Settings for a Call Queue."""
|
|
1761
|
+
api = get_api(debug=debug)
|
|
1762
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/settings"
|
|
1763
|
+
params = {}
|
|
1764
|
+
org_id = get_org_id()
|
|
1765
|
+
if org_id is not None:
|
|
1766
|
+
params["orgId"] = org_id
|
|
1767
|
+
if json_body:
|
|
1768
|
+
body = json.loads(json_body)
|
|
1769
|
+
else:
|
|
1770
|
+
body = {}
|
|
1771
|
+
if distinctive_ringing_enabled is not None:
|
|
1772
|
+
body["distinctiveRingingEnabled"] = distinctive_ringing_enabled
|
|
1773
|
+
if display_dnis_name_and_number_enabled is not None:
|
|
1774
|
+
body["displayDnisNameAndNumberEnabled"] = display_dnis_name_and_number_enabled
|
|
1775
|
+
try:
|
|
1776
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1777
|
+
except WebexError as e:
|
|
1778
|
+
handle_rest_error(e)
|
|
1779
|
+
typer.echo(f"Updated.")
|
|
1780
|
+
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
@app.command("show-announcements")
|
|
1784
|
+
def show_announcements(
|
|
1785
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1786
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1787
|
+
dnis_id: str = typer.Argument(help="dnisId"),
|
|
1788
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1789
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1790
|
+
):
|
|
1791
|
+
"""Get DNIS Announcements for a Call Queue."""
|
|
1792
|
+
api = get_api(debug=debug)
|
|
1793
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/{dnis_id}/announcements"
|
|
1794
|
+
params = {}
|
|
1795
|
+
org_id = get_org_id()
|
|
1796
|
+
if org_id is not None:
|
|
1797
|
+
params["orgId"] = org_id
|
|
1798
|
+
try:
|
|
1799
|
+
result = api.session.rest_get(url, params=params)
|
|
1800
|
+
except WebexError as e:
|
|
1801
|
+
handle_rest_error(e)
|
|
1802
|
+
if output == "json":
|
|
1803
|
+
print_json(result)
|
|
1804
|
+
else:
|
|
1805
|
+
if isinstance(result, dict):
|
|
1806
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1807
|
+
elif isinstance(result, list):
|
|
1808
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1809
|
+
else:
|
|
1810
|
+
print_json(result)
|
|
1811
|
+
|
|
1812
|
+
|
|
1813
|
+
|
|
1814
|
+
@app.command("update-announcements")
|
|
1815
|
+
def update_announcements(
|
|
1816
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1817
|
+
queue_id: str = typer.Argument(help="queueId"),
|
|
1818
|
+
dnis_id: str = typer.Argument(help="dnisId"),
|
|
1819
|
+
custom_dnis_announcement_settings_enabled: bool = typer.Option(None, "--custom-dnis-announcement-settings-enabled/--no-custom-dnis-announcement-settings-enabled", help="Whether custom DNIS announcement settings are enabled for th"),
|
|
1820
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1821
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1822
|
+
):
|
|
1823
|
+
"""Modify DNIS Announcements for a Call Queue\n\nExample --json-body:\n '{"customDnisAnnouncementSettingsEnabled":true,"welcomeMessage":{"enabled":true,"alwaysEnabled":true,"greeting":"DEFAULT","audioAnnouncementFiles":["..."]},"comfortMessage":{"enabled":true,"timeBetweenMessages":0,"greeting":"DEFAULT","audioAnnouncementFiles":["..."]},"comfortMessageBypass":{"enabled":true,"callWaitingAgeThreshold":0,"greeting":"DEFAULT","audioAnnouncementFiles":["..."]},"mohMessage":{"normalSource":{"enabled":"...","greeting":"...","audioAnnouncementFiles":"...","audioPlaylistId":"..."},"alternateSource":{"enabled":"...","greeting":"...","audioAnnouncementFiles":"...","audioPlaylistId":"..."}},"waitMessage":{"enabled":true,"waitMode":"TIME","handlingTime":0,"defaultHandlingTime":0,"queuePosition":0,"highVolumeMessageEnabled":true,"estimatedWaitingTime":0,"callbackOptionEnabled":true},"whisperMessage":{"enabled":true,"greeting":"DEFAULT","audioAnnouncementFiles":["..."]}}'."""
|
|
1824
|
+
api = get_api(debug=debug)
|
|
1825
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/{queue_id}/dnis/{dnis_id}/announcements"
|
|
1826
|
+
params = {}
|
|
1827
|
+
org_id = get_org_id()
|
|
1828
|
+
if org_id is not None:
|
|
1829
|
+
params["orgId"] = org_id
|
|
1830
|
+
if json_body:
|
|
1831
|
+
body = json.loads(json_body)
|
|
1832
|
+
else:
|
|
1833
|
+
body = {}
|
|
1834
|
+
if custom_dnis_announcement_settings_enabled is not None:
|
|
1835
|
+
body["customDnisAnnouncementSettingsEnabled"] = custom_dnis_announcement_settings_enabled
|
|
1836
|
+
try:
|
|
1837
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1838
|
+
except WebexError as e:
|
|
1839
|
+
handle_rest_error(e)
|
|
1840
|
+
typer.echo(f"Updated.")
|
|
1841
|
+
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
@app.command("list-available-numbers-dnis")
|
|
1845
|
+
def list_available_numbers_dnis(
|
|
1846
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1847
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter by phone number."),
|
|
1848
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1849
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1850
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1851
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1852
|
+
):
|
|
1853
|
+
"""Get Available Phone Numbers for DNIS."""
|
|
1854
|
+
api = get_api(debug=debug)
|
|
1855
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/queues/dnis/availableNumbers"
|
|
1856
|
+
params = {}
|
|
1857
|
+
if phone_number is not None:
|
|
1858
|
+
params["phoneNumber"] = phone_number
|
|
1859
|
+
if limit > 0:
|
|
1860
|
+
params["max"] = limit
|
|
1861
|
+
if offset > 0:
|
|
1862
|
+
params["start"] = offset
|
|
1863
|
+
org_id = get_org_id()
|
|
1864
|
+
if org_id is not None:
|
|
1865
|
+
params["orgId"] = org_id
|
|
1866
|
+
result = None
|
|
1867
|
+
try:
|
|
1868
|
+
result = api.session.rest_get(url, params=params)
|
|
1869
|
+
except WebexError as e:
|
|
1870
|
+
handle_rest_error(e)
|
|
1871
|
+
result = result or []
|
|
1872
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1873
|
+
if output == "json":
|
|
1874
|
+
print_json(items)
|
|
1875
|
+
else:
|
|
1876
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1877
|
+
|
|
1878
|
+
|