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,1610 @@
|
|
|
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-routing.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("test-call-routing")
|
|
13
|
+
def test_call_routing(
|
|
14
|
+
originator_id: str = typer.Option(None, "--originator-id", help="This element is used to identify the originating party. It c"),
|
|
15
|
+
originator_type: str = typer.Option(None, "--originator-type", help="Choices: PEOPLE, TRUNK"),
|
|
16
|
+
originator_number: str = typer.Option(None, "--originator-number", help="Only used when `originatorType` is `TRUNK`. The `originatorN"),
|
|
17
|
+
destination: str = typer.Option(None, "--destination", help="This element specifies the called party. It can be any diala"),
|
|
18
|
+
include_applied_services: str = typer.Option(None, "--include-applied-services", help="This element is used to retrieve if any translation pattern,"),
|
|
19
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
20
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
21
|
+
):
|
|
22
|
+
"""Test Call Routing\n\nExample --json-body:\n '{"originatorId":"...","originatorType":"PEOPLE","destination":"...","originatorNumber":"...","includeAppliedServices":true}'."""
|
|
23
|
+
api = get_api(debug=debug)
|
|
24
|
+
url = f"https://webexapis.com/v1/telephony/config/actions/testCallRouting/invoke"
|
|
25
|
+
params = {}
|
|
26
|
+
org_id = get_org_id()
|
|
27
|
+
if org_id is not None:
|
|
28
|
+
params["orgId"] = org_id
|
|
29
|
+
if json_body:
|
|
30
|
+
body = json.loads(json_body)
|
|
31
|
+
else:
|
|
32
|
+
body = {}
|
|
33
|
+
if originator_id is not None:
|
|
34
|
+
body["originatorId"] = originator_id
|
|
35
|
+
if originator_type is not None:
|
|
36
|
+
body["originatorType"] = originator_type
|
|
37
|
+
if originator_number is not None:
|
|
38
|
+
body["originatorNumber"] = originator_number
|
|
39
|
+
if destination is not None:
|
|
40
|
+
body["destination"] = destination
|
|
41
|
+
if include_applied_services is not None:
|
|
42
|
+
body["includeAppliedServices"] = include_applied_services
|
|
43
|
+
try:
|
|
44
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
45
|
+
except WebexError as e:
|
|
46
|
+
handle_rest_error(e)
|
|
47
|
+
print_json(result)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@app.command("list")
|
|
52
|
+
def cmd_list(
|
|
53
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
54
|
+
order: str = typer.Option(None, "--order", help="Order the trunks according to the designated fields. Availa"),
|
|
55
|
+
name: str = typer.Option(None, "--name", help="Return the list of trunks matching the local gateway names"),
|
|
56
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
57
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
58
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
59
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
60
|
+
):
|
|
61
|
+
"""Get Local Gateway Dial Plan Usage for a Trunk."""
|
|
62
|
+
api = get_api(debug=debug)
|
|
63
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}/usageDialPlan"
|
|
64
|
+
params = {}
|
|
65
|
+
if order is not None:
|
|
66
|
+
params["order"] = order
|
|
67
|
+
if name is not None:
|
|
68
|
+
params["name"] = name
|
|
69
|
+
if limit > 0:
|
|
70
|
+
params["max"] = limit
|
|
71
|
+
if offset > 0:
|
|
72
|
+
params["start"] = offset
|
|
73
|
+
org_id = get_org_id()
|
|
74
|
+
if org_id is not None:
|
|
75
|
+
params["orgId"] = org_id
|
|
76
|
+
result = None
|
|
77
|
+
try:
|
|
78
|
+
result = api.session.rest_get(url, params=params)
|
|
79
|
+
except WebexError as e:
|
|
80
|
+
handle_rest_error(e)
|
|
81
|
+
result = result or []
|
|
82
|
+
items = result.get("dialPlans", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
83
|
+
if output == "json":
|
|
84
|
+
print_json(items)
|
|
85
|
+
else:
|
|
86
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@app.command("list-usage-pstn-connection-trunks")
|
|
91
|
+
def list_usage_pstn_connection_trunks(
|
|
92
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
93
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
94
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
95
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
96
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
97
|
+
):
|
|
98
|
+
"""Get Locations Using the Local Gateway as PSTN Connection Routing."""
|
|
99
|
+
api = get_api(debug=debug)
|
|
100
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}/usagePstnConnection"
|
|
101
|
+
params = {}
|
|
102
|
+
if limit > 0:
|
|
103
|
+
params["max"] = limit
|
|
104
|
+
if offset > 0:
|
|
105
|
+
params["start"] = offset
|
|
106
|
+
org_id = get_org_id()
|
|
107
|
+
if org_id is not None:
|
|
108
|
+
params["orgId"] = org_id
|
|
109
|
+
result = None
|
|
110
|
+
try:
|
|
111
|
+
result = api.session.rest_get(url, params=params)
|
|
112
|
+
except WebexError as e:
|
|
113
|
+
handle_rest_error(e)
|
|
114
|
+
result = result or []
|
|
115
|
+
items = result.get("locations", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
116
|
+
if output == "json":
|
|
117
|
+
print_json(items)
|
|
118
|
+
else:
|
|
119
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@app.command("list-usage-route-group")
|
|
124
|
+
def list_usage_route_group(
|
|
125
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
126
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
127
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
128
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
129
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
130
|
+
):
|
|
131
|
+
"""Get Route Groups Using the Local Gateway."""
|
|
132
|
+
api = get_api(debug=debug)
|
|
133
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}/usageRouteGroup"
|
|
134
|
+
params = {}
|
|
135
|
+
if limit > 0:
|
|
136
|
+
params["max"] = limit
|
|
137
|
+
if offset > 0:
|
|
138
|
+
params["start"] = offset
|
|
139
|
+
org_id = get_org_id()
|
|
140
|
+
if org_id is not None:
|
|
141
|
+
params["orgId"] = org_id
|
|
142
|
+
result = None
|
|
143
|
+
try:
|
|
144
|
+
result = api.session.rest_get(url, params=params)
|
|
145
|
+
except WebexError as e:
|
|
146
|
+
handle_rest_error(e)
|
|
147
|
+
result = result or []
|
|
148
|
+
items = result.get("routeGroup", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
149
|
+
if output == "json":
|
|
150
|
+
print_json(items)
|
|
151
|
+
else:
|
|
152
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@app.command("show")
|
|
157
|
+
def show(
|
|
158
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
159
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
160
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
161
|
+
):
|
|
162
|
+
"""Get Local Gateway Usage Count."""
|
|
163
|
+
api = get_api(debug=debug)
|
|
164
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}/usage"
|
|
165
|
+
params = {}
|
|
166
|
+
org_id = get_org_id()
|
|
167
|
+
if org_id is not None:
|
|
168
|
+
params["orgId"] = org_id
|
|
169
|
+
try:
|
|
170
|
+
result = api.session.rest_get(url, params=params)
|
|
171
|
+
except WebexError as e:
|
|
172
|
+
handle_rest_error(e)
|
|
173
|
+
if output == "json":
|
|
174
|
+
print_json(result)
|
|
175
|
+
else:
|
|
176
|
+
if isinstance(result, dict):
|
|
177
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
178
|
+
elif isinstance(result, list):
|
|
179
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
180
|
+
else:
|
|
181
|
+
print_json(result)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
@app.command("update")
|
|
186
|
+
def update(
|
|
187
|
+
dial_plan_id: str = typer.Argument(help="dialPlanId"),
|
|
188
|
+
delete_all_dial_patterns: bool = typer.Option(None, "--delete-all-dial-patterns/--no-delete-all-dial-patterns", help="Delete all the dial patterns for a dial plan."),
|
|
189
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
190
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
191
|
+
):
|
|
192
|
+
"""Modify Dial Patterns\n\nExample --json-body:\n '{"dialPatterns":[{"dialPattern":"...","action":"..."}],"deleteAllDialPatterns":true}'."""
|
|
193
|
+
api = get_api(debug=debug)
|
|
194
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/dialPlans/{dial_plan_id}/dialPatterns"
|
|
195
|
+
params = {}
|
|
196
|
+
org_id = get_org_id()
|
|
197
|
+
if org_id is not None:
|
|
198
|
+
params["orgId"] = org_id
|
|
199
|
+
if json_body:
|
|
200
|
+
body = json.loads(json_body)
|
|
201
|
+
else:
|
|
202
|
+
body = {}
|
|
203
|
+
if delete_all_dial_patterns is not None:
|
|
204
|
+
body["deleteAllDialPatterns"] = delete_all_dial_patterns
|
|
205
|
+
try:
|
|
206
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
207
|
+
except WebexError as e:
|
|
208
|
+
handle_rest_error(e)
|
|
209
|
+
typer.echo(f"Updated.")
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@app.command("validate-a-dial")
|
|
214
|
+
def validate_a_dial(
|
|
215
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
216
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
217
|
+
):
|
|
218
|
+
"""Validate a Dial Pattern\n\nExample --json-body:\n '{"dialPatterns":["..."]}'."""
|
|
219
|
+
api = get_api(debug=debug)
|
|
220
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/actions/validateDialPatterns/invoke"
|
|
221
|
+
params = {}
|
|
222
|
+
org_id = get_org_id()
|
|
223
|
+
if org_id is not None:
|
|
224
|
+
params["orgId"] = org_id
|
|
225
|
+
if json_body:
|
|
226
|
+
body = json.loads(json_body)
|
|
227
|
+
else:
|
|
228
|
+
body = {}
|
|
229
|
+
try:
|
|
230
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
231
|
+
except WebexError as e:
|
|
232
|
+
handle_rest_error(e)
|
|
233
|
+
print_json(result)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@app.command("list-dial-plans")
|
|
238
|
+
def list_dial_plans(
|
|
239
|
+
dial_plan_name: str = typer.Option(None, "--dial-plan-name", help="Return the list of dial plans matching the dial plan name."),
|
|
240
|
+
route_group_name: str = typer.Option(None, "--route-group-name", help="Return the list of dial plans matching the Route group name."),
|
|
241
|
+
trunk_name: str = typer.Option(None, "--trunk-name", help="Return the list of dial plans matching the Trunk name.."),
|
|
242
|
+
order: str = typer.Option(None, "--order", help="Order the dial plans according to the designated fields. Av"),
|
|
243
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
244
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
245
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
246
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
247
|
+
):
|
|
248
|
+
"""Read the List of Dial Plans."""
|
|
249
|
+
api = get_api(debug=debug)
|
|
250
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/dialPlans"
|
|
251
|
+
params = {}
|
|
252
|
+
if dial_plan_name is not None:
|
|
253
|
+
params["dialPlanName"] = dial_plan_name
|
|
254
|
+
if route_group_name is not None:
|
|
255
|
+
params["routeGroupName"] = route_group_name
|
|
256
|
+
if trunk_name is not None:
|
|
257
|
+
params["trunkName"] = trunk_name
|
|
258
|
+
if order is not None:
|
|
259
|
+
params["order"] = order
|
|
260
|
+
if limit > 0:
|
|
261
|
+
params["max"] = limit
|
|
262
|
+
if offset > 0:
|
|
263
|
+
params["start"] = offset
|
|
264
|
+
org_id = get_org_id()
|
|
265
|
+
if org_id is not None:
|
|
266
|
+
params["orgId"] = org_id
|
|
267
|
+
result = None
|
|
268
|
+
try:
|
|
269
|
+
result = api.session.rest_get(url, params=params)
|
|
270
|
+
except WebexError as e:
|
|
271
|
+
handle_rest_error(e)
|
|
272
|
+
result = result or []
|
|
273
|
+
items = result.get("dialPlans", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
274
|
+
if output == "json":
|
|
275
|
+
print_json(items)
|
|
276
|
+
else:
|
|
277
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@app.command("create")
|
|
282
|
+
def create(
|
|
283
|
+
name: str = typer.Option(None, "--name", help="(required) A unique name for the dial plan."),
|
|
284
|
+
route_id: str = typer.Option(None, "--route-id", help="(required) ID of route type associated with the dial plan."),
|
|
285
|
+
route_type: str = typer.Option(None, "--route-type", help="(required) Choices: ROUTE_GROUP, TRUNK"),
|
|
286
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
287
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
288
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
289
|
+
):
|
|
290
|
+
"""Create a Dial Plan\n\nExample --json-body:\n '{"name":"...","routeId":"...","routeType":"ROUTE_GROUP","dialPatterns":["..."]}'."""
|
|
291
|
+
api = get_api(debug=debug)
|
|
292
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/dialPlans"
|
|
293
|
+
params = {}
|
|
294
|
+
org_id = get_org_id()
|
|
295
|
+
if org_id is not None:
|
|
296
|
+
params["orgId"] = org_id
|
|
297
|
+
if json_body:
|
|
298
|
+
body = json.loads(json_body)
|
|
299
|
+
else:
|
|
300
|
+
body = {}
|
|
301
|
+
if name is not None:
|
|
302
|
+
body["name"] = name
|
|
303
|
+
if route_id is not None:
|
|
304
|
+
body["routeId"] = route_id
|
|
305
|
+
if route_type is not None:
|
|
306
|
+
body["routeType"] = route_type
|
|
307
|
+
_missing = [f for f in ['name', 'routeId', 'routeType'] if f not in body or body[f] is None]
|
|
308
|
+
if _missing:
|
|
309
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
310
|
+
raise typer.Exit(1)
|
|
311
|
+
try:
|
|
312
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
313
|
+
except WebexError as e:
|
|
314
|
+
handle_rest_error(e)
|
|
315
|
+
if output == "json":
|
|
316
|
+
print_json(result)
|
|
317
|
+
elif isinstance(result, dict) and "id" in result:
|
|
318
|
+
typer.echo(f"Created: {result['id']}")
|
|
319
|
+
elif not result or result == {}:
|
|
320
|
+
typer.echo("Created.")
|
|
321
|
+
else:
|
|
322
|
+
print_json(result)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
@app.command("show-dial-plans")
|
|
327
|
+
def show_dial_plans(
|
|
328
|
+
dial_plan_id: str = typer.Argument(help="dialPlanId"),
|
|
329
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
330
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
331
|
+
):
|
|
332
|
+
"""Get a Dial Plan."""
|
|
333
|
+
api = get_api(debug=debug)
|
|
334
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/dialPlans/{dial_plan_id}"
|
|
335
|
+
params = {}
|
|
336
|
+
org_id = get_org_id()
|
|
337
|
+
if org_id is not None:
|
|
338
|
+
params["orgId"] = org_id
|
|
339
|
+
try:
|
|
340
|
+
result = api.session.rest_get(url, params=params)
|
|
341
|
+
except WebexError as e:
|
|
342
|
+
handle_rest_error(e)
|
|
343
|
+
if output == "json":
|
|
344
|
+
print_json(result)
|
|
345
|
+
else:
|
|
346
|
+
if isinstance(result, dict):
|
|
347
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
348
|
+
elif isinstance(result, list):
|
|
349
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
350
|
+
else:
|
|
351
|
+
print_json(result)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
@app.command("update-dial-plans")
|
|
356
|
+
def update_dial_plans(
|
|
357
|
+
dial_plan_id: str = typer.Argument(help="dialPlanId"),
|
|
358
|
+
name: str = typer.Option(None, "--name", help="A unique name for the dial plan."),
|
|
359
|
+
route_id: str = typer.Option(None, "--route-id", help="ID of route type associated with the dial plan."),
|
|
360
|
+
route_type: str = typer.Option(None, "--route-type", help="Choices: ROUTE_GROUP, TRUNK"),
|
|
361
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
362
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
363
|
+
):
|
|
364
|
+
"""Modify a Dial Plan\n\nExample --json-body:\n '{"name":"...","routeId":"...","routeType":"ROUTE_GROUP"}'."""
|
|
365
|
+
api = get_api(debug=debug)
|
|
366
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/dialPlans/{dial_plan_id}"
|
|
367
|
+
params = {}
|
|
368
|
+
org_id = get_org_id()
|
|
369
|
+
if org_id is not None:
|
|
370
|
+
params["orgId"] = org_id
|
|
371
|
+
if json_body:
|
|
372
|
+
body = json.loads(json_body)
|
|
373
|
+
else:
|
|
374
|
+
body = {}
|
|
375
|
+
if name is not None:
|
|
376
|
+
body["name"] = name
|
|
377
|
+
if route_id is not None:
|
|
378
|
+
body["routeId"] = route_id
|
|
379
|
+
if route_type is not None:
|
|
380
|
+
body["routeType"] = route_type
|
|
381
|
+
try:
|
|
382
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
383
|
+
except WebexError as e:
|
|
384
|
+
handle_rest_error(e)
|
|
385
|
+
typer.echo(f"Updated.")
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@app.command("delete")
|
|
390
|
+
def delete(
|
|
391
|
+
dial_plan_id: str = typer.Argument(help="dialPlanId"),
|
|
392
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
393
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
394
|
+
):
|
|
395
|
+
"""Delete a Dial Plan."""
|
|
396
|
+
if not force:
|
|
397
|
+
typer.confirm(f"Delete {dial_plan_id}?", abort=True)
|
|
398
|
+
api = get_api(debug=debug)
|
|
399
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/dialPlans/{dial_plan_id}"
|
|
400
|
+
params = {}
|
|
401
|
+
org_id = get_org_id()
|
|
402
|
+
if org_id is not None:
|
|
403
|
+
params["orgId"] = org_id
|
|
404
|
+
try:
|
|
405
|
+
api.session.rest_delete(url, params=params)
|
|
406
|
+
except WebexError as e:
|
|
407
|
+
handle_rest_error(e)
|
|
408
|
+
typer.echo(f"Deleted: {dial_plan_id}")
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
@app.command("validate-local-gateway")
|
|
413
|
+
def validate_local_gateway(
|
|
414
|
+
address: str = typer.Option(None, "--address", help="FQDN or SRV address of the trunk."),
|
|
415
|
+
domain: str = typer.Option(None, "--domain", help="Domain name of the trunk."),
|
|
416
|
+
port: str = typer.Option(None, "--port", help="FQDN port of the trunk."),
|
|
417
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
418
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
419
|
+
):
|
|
420
|
+
"""Validate Local Gateway FQDN and Domain for a Trunk."""
|
|
421
|
+
api = get_api(debug=debug)
|
|
422
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/actions/fqdnValidation/invoke"
|
|
423
|
+
params = {}
|
|
424
|
+
org_id = get_org_id()
|
|
425
|
+
if org_id is not None:
|
|
426
|
+
params["orgId"] = org_id
|
|
427
|
+
if json_body:
|
|
428
|
+
body = json.loads(json_body)
|
|
429
|
+
else:
|
|
430
|
+
body = {}
|
|
431
|
+
if address is not None:
|
|
432
|
+
body["address"] = address
|
|
433
|
+
if domain is not None:
|
|
434
|
+
body["domain"] = domain
|
|
435
|
+
if port is not None:
|
|
436
|
+
body["port"] = port
|
|
437
|
+
try:
|
|
438
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
439
|
+
except WebexError as e:
|
|
440
|
+
handle_rest_error(e)
|
|
441
|
+
print_json(result)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
@app.command("list-trunks")
|
|
446
|
+
def list_trunks(
|
|
447
|
+
name: str = typer.Option(None, "--name", help="Return the list of trunks matching the local gateway names."),
|
|
448
|
+
location_name: str = typer.Option(None, "--location-name", help="Return the list of trunks matching the location names."),
|
|
449
|
+
trunk_type: str = typer.Option(None, "--trunk-type", help="Return the list of trunks matching the trunk type."),
|
|
450
|
+
order: str = typer.Option(None, "--order", help="Order the trunks according to the designated fields. Availa"),
|
|
451
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
452
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
453
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
454
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
455
|
+
):
|
|
456
|
+
"""Read the List of Trunks."""
|
|
457
|
+
api = get_api(debug=debug)
|
|
458
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks"
|
|
459
|
+
params = {}
|
|
460
|
+
if name is not None:
|
|
461
|
+
params["name"] = name
|
|
462
|
+
if location_name is not None:
|
|
463
|
+
params["locationName"] = location_name
|
|
464
|
+
if trunk_type is not None:
|
|
465
|
+
params["trunkType"] = trunk_type
|
|
466
|
+
if order is not None:
|
|
467
|
+
params["order"] = order
|
|
468
|
+
if limit > 0:
|
|
469
|
+
params["max"] = limit
|
|
470
|
+
if offset > 0:
|
|
471
|
+
params["start"] = offset
|
|
472
|
+
org_id = get_org_id()
|
|
473
|
+
if org_id is not None:
|
|
474
|
+
params["orgId"] = org_id
|
|
475
|
+
result = None
|
|
476
|
+
try:
|
|
477
|
+
result = api.session.rest_get(url, params=params)
|
|
478
|
+
except WebexError as e:
|
|
479
|
+
handle_rest_error(e)
|
|
480
|
+
result = result or []
|
|
481
|
+
items = result.get("trunks", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
482
|
+
if output == "json":
|
|
483
|
+
print_json(items)
|
|
484
|
+
else:
|
|
485
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
@app.command("create-trunks")
|
|
490
|
+
def create_trunks(
|
|
491
|
+
name: str = typer.Option(None, "--name", help="(required) A unique name for the trunk."),
|
|
492
|
+
location_id: str = typer.Option(None, "--location-id", help="(required) ID of location associated with the trunk."),
|
|
493
|
+
password: str = typer.Option(None, "--password", help="(required) A password to use on the trunk."),
|
|
494
|
+
dual_identity_support_enabled: bool = typer.Option(None, "--dual-identity-support-enabled/--no-dual-identity-support-enabled", help="Dual Identity Support setting impacts the handling of the Fr"),
|
|
495
|
+
trunk_type: str = typer.Option(None, "--trunk-type", help="(required) Choices: REGISTERING, CERTIFICATE_BASED"),
|
|
496
|
+
device_type: str = typer.Option(None, "--device-type", help="Device type assosiated with trunk."),
|
|
497
|
+
address: str = typer.Option(None, "--address", help="FQDN or SRV address. Required to create a static certificate"),
|
|
498
|
+
domain: str = typer.Option(None, "--domain", help="Domain name. Required to create a static certificate based t"),
|
|
499
|
+
port: str = typer.Option(None, "--port", help="FQDN port. Required to create a static certificate-based tru"),
|
|
500
|
+
max_concurrent_calls: str = typer.Option(None, "--max-concurrent-calls", help="Max Concurrent call. Required to create a static certificate"),
|
|
501
|
+
p_charge_info_support_policy: str = typer.Option(None, "--p-charge-info-support-policy", help="Choices: DISABLED, ASSERTED_IDENTITY, CONFIGURABLE_CHARGE_NUMBER"),
|
|
502
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
503
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
504
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
505
|
+
):
|
|
506
|
+
"""Create a Trunk\n\nExample --json-body:\n '{"name":"...","locationId":"...","password":"...","trunkType":"REGISTERING","dualIdentitySupportEnabled":true,"deviceType":"...","address":"...","domain":"..."}'."""
|
|
507
|
+
api = get_api(debug=debug)
|
|
508
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks"
|
|
509
|
+
params = {}
|
|
510
|
+
org_id = get_org_id()
|
|
511
|
+
if org_id is not None:
|
|
512
|
+
params["orgId"] = org_id
|
|
513
|
+
if json_body:
|
|
514
|
+
body = json.loads(json_body)
|
|
515
|
+
else:
|
|
516
|
+
body = {}
|
|
517
|
+
if name is not None:
|
|
518
|
+
body["name"] = name
|
|
519
|
+
if location_id is not None:
|
|
520
|
+
body["locationId"] = location_id
|
|
521
|
+
if password is not None:
|
|
522
|
+
body["password"] = password
|
|
523
|
+
if dual_identity_support_enabled is not None:
|
|
524
|
+
body["dualIdentitySupportEnabled"] = dual_identity_support_enabled
|
|
525
|
+
if trunk_type is not None:
|
|
526
|
+
body["trunkType"] = trunk_type
|
|
527
|
+
if device_type is not None:
|
|
528
|
+
body["deviceType"] = device_type
|
|
529
|
+
if address is not None:
|
|
530
|
+
body["address"] = address
|
|
531
|
+
if domain is not None:
|
|
532
|
+
body["domain"] = domain
|
|
533
|
+
if port is not None:
|
|
534
|
+
body["port"] = port
|
|
535
|
+
if max_concurrent_calls is not None:
|
|
536
|
+
body["maxConcurrentCalls"] = max_concurrent_calls
|
|
537
|
+
if p_charge_info_support_policy is not None:
|
|
538
|
+
body["pChargeInfoSupportPolicy"] = p_charge_info_support_policy
|
|
539
|
+
_missing = [f for f in ['name', 'locationId', 'password', 'trunkType'] if f not in body or body[f] is None]
|
|
540
|
+
if _missing:
|
|
541
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
542
|
+
raise typer.Exit(1)
|
|
543
|
+
try:
|
|
544
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
545
|
+
except WebexError as e:
|
|
546
|
+
handle_rest_error(e)
|
|
547
|
+
if output == "json":
|
|
548
|
+
print_json(result)
|
|
549
|
+
elif isinstance(result, dict) and "id" in result:
|
|
550
|
+
typer.echo(f"Created: {result['id']}")
|
|
551
|
+
elif not result or result == {}:
|
|
552
|
+
typer.echo("Created.")
|
|
553
|
+
else:
|
|
554
|
+
print_json(result)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
@app.command("show-trunks")
|
|
559
|
+
def show_trunks(
|
|
560
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
561
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
562
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
563
|
+
):
|
|
564
|
+
"""Get a Trunk."""
|
|
565
|
+
api = get_api(debug=debug)
|
|
566
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}"
|
|
567
|
+
params = {}
|
|
568
|
+
org_id = get_org_id()
|
|
569
|
+
if org_id is not None:
|
|
570
|
+
params["orgId"] = org_id
|
|
571
|
+
try:
|
|
572
|
+
result = api.session.rest_get(url, params=params)
|
|
573
|
+
except WebexError as e:
|
|
574
|
+
handle_rest_error(e)
|
|
575
|
+
if output == "json":
|
|
576
|
+
print_json(result)
|
|
577
|
+
else:
|
|
578
|
+
if isinstance(result, dict):
|
|
579
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
580
|
+
elif isinstance(result, list):
|
|
581
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
582
|
+
else:
|
|
583
|
+
print_json(result)
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
@app.command("update-trunks")
|
|
588
|
+
def update_trunks(
|
|
589
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
590
|
+
name: str = typer.Option(None, "--name", help="A unique name for the dial plan."),
|
|
591
|
+
password: str = typer.Option(None, "--password", help="A password to use on the trunk."),
|
|
592
|
+
dual_identity_support_enabled: bool = typer.Option(None, "--dual-identity-support-enabled/--no-dual-identity-support-enabled", help="Determines the behavior of the From and PAI headers on outbo"),
|
|
593
|
+
max_concurrent_calls: str = typer.Option(None, "--max-concurrent-calls", help="Max Concurrent call. Required to create a static certificate"),
|
|
594
|
+
p_charge_info_support_policy: str = typer.Option(None, "--p-charge-info-support-policy", help="Choices: DISABLED, ASSERTED_IDENTITY, CONFIGURABLE_CHARGE_NUMBER"),
|
|
595
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
596
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
597
|
+
):
|
|
598
|
+
"""Modify a Trunk\n\nExample --json-body:\n '{"name":"...","password":"...","dualIdentitySupportEnabled":true,"maxConcurrentCalls":0,"pChargeInfoSupportPolicy":"DISABLED"}'."""
|
|
599
|
+
api = get_api(debug=debug)
|
|
600
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}"
|
|
601
|
+
params = {}
|
|
602
|
+
org_id = get_org_id()
|
|
603
|
+
if org_id is not None:
|
|
604
|
+
params["orgId"] = org_id
|
|
605
|
+
if json_body:
|
|
606
|
+
body = json.loads(json_body)
|
|
607
|
+
else:
|
|
608
|
+
body = {}
|
|
609
|
+
if name is not None:
|
|
610
|
+
body["name"] = name
|
|
611
|
+
if password is not None:
|
|
612
|
+
body["password"] = password
|
|
613
|
+
if dual_identity_support_enabled is not None:
|
|
614
|
+
body["dualIdentitySupportEnabled"] = dual_identity_support_enabled
|
|
615
|
+
if max_concurrent_calls is not None:
|
|
616
|
+
body["maxConcurrentCalls"] = max_concurrent_calls
|
|
617
|
+
if p_charge_info_support_policy is not None:
|
|
618
|
+
body["pChargeInfoSupportPolicy"] = p_charge_info_support_policy
|
|
619
|
+
try:
|
|
620
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
621
|
+
except WebexError as e:
|
|
622
|
+
handle_rest_error(e)
|
|
623
|
+
typer.echo(f"Updated.")
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
@app.command("delete-trunks")
|
|
628
|
+
def delete_trunks(
|
|
629
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
630
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
631
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
632
|
+
):
|
|
633
|
+
"""Delete a Trunk."""
|
|
634
|
+
if not force:
|
|
635
|
+
typer.confirm(f"Delete {trunk_id}?", abort=True)
|
|
636
|
+
api = get_api(debug=debug)
|
|
637
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}"
|
|
638
|
+
params = {}
|
|
639
|
+
org_id = get_org_id()
|
|
640
|
+
if org_id is not None:
|
|
641
|
+
params["orgId"] = org_id
|
|
642
|
+
try:
|
|
643
|
+
api.session.rest_delete(url, params=params)
|
|
644
|
+
except WebexError as e:
|
|
645
|
+
handle_rest_error(e)
|
|
646
|
+
typer.echo(f"Deleted: {trunk_id}")
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
@app.command("list-trunk-types")
|
|
651
|
+
def list_trunk_types(
|
|
652
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
653
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
654
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
655
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
656
|
+
):
|
|
657
|
+
"""Read the List of Trunk Types."""
|
|
658
|
+
api = get_api(debug=debug)
|
|
659
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/trunkTypes"
|
|
660
|
+
params = {}
|
|
661
|
+
if limit > 0:
|
|
662
|
+
params["max"] = limit
|
|
663
|
+
if offset > 0:
|
|
664
|
+
params["start"] = offset
|
|
665
|
+
org_id = get_org_id()
|
|
666
|
+
if org_id is not None:
|
|
667
|
+
params["orgId"] = org_id
|
|
668
|
+
result = None
|
|
669
|
+
try:
|
|
670
|
+
result = api.session.rest_get(url, params=params)
|
|
671
|
+
except WebexError as e:
|
|
672
|
+
handle_rest_error(e)
|
|
673
|
+
result = result or []
|
|
674
|
+
items = result.get("trunkTypes", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
675
|
+
if output == "json":
|
|
676
|
+
print_json(items)
|
|
677
|
+
else:
|
|
678
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
679
|
+
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
@app.command("list-route-groups")
|
|
683
|
+
def list_route_groups(
|
|
684
|
+
name: str = typer.Option(None, "--name", help="Return the list of route groups matching the Route group nam"),
|
|
685
|
+
order: str = typer.Option(None, "--order", help="Order the route groups according to designated fields. Avai"),
|
|
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
|
+
"""Read the List of Routing Groups."""
|
|
692
|
+
api = get_api(debug=debug)
|
|
693
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups"
|
|
694
|
+
params = {}
|
|
695
|
+
if name is not None:
|
|
696
|
+
params["name"] = name
|
|
697
|
+
if order is not None:
|
|
698
|
+
params["order"] = order
|
|
699
|
+
if limit > 0:
|
|
700
|
+
params["max"] = limit
|
|
701
|
+
if offset > 0:
|
|
702
|
+
params["start"] = offset
|
|
703
|
+
org_id = get_org_id()
|
|
704
|
+
if org_id is not None:
|
|
705
|
+
params["orgId"] = org_id
|
|
706
|
+
result = None
|
|
707
|
+
try:
|
|
708
|
+
result = api.session.rest_get(url, params=params)
|
|
709
|
+
except WebexError as e:
|
|
710
|
+
handle_rest_error(e)
|
|
711
|
+
result = result or []
|
|
712
|
+
items = result.get("routeGroups", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
713
|
+
if output == "json":
|
|
714
|
+
print_json(items)
|
|
715
|
+
else:
|
|
716
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
@app.command("create-route-groups")
|
|
721
|
+
def create_route_groups(
|
|
722
|
+
name: str = typer.Option(None, "--name", help="(required) A unique name for the Route Group."),
|
|
723
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
724
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
725
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
726
|
+
):
|
|
727
|
+
"""Create Route Group for a Organization\n\nExample --json-body:\n '{"name":"...","localGateways":[{"id":"...","priority":"...","name":"...","locationId":"..."}]}'."""
|
|
728
|
+
api = get_api(debug=debug)
|
|
729
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups"
|
|
730
|
+
params = {}
|
|
731
|
+
org_id = get_org_id()
|
|
732
|
+
if org_id is not None:
|
|
733
|
+
params["orgId"] = org_id
|
|
734
|
+
if json_body:
|
|
735
|
+
body = json.loads(json_body)
|
|
736
|
+
else:
|
|
737
|
+
body = {}
|
|
738
|
+
if name is not None:
|
|
739
|
+
body["name"] = name
|
|
740
|
+
_missing = [f for f in ['name'] if f not in body or body[f] is None]
|
|
741
|
+
if _missing:
|
|
742
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
743
|
+
raise typer.Exit(1)
|
|
744
|
+
try:
|
|
745
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
746
|
+
except WebexError as e:
|
|
747
|
+
handle_rest_error(e)
|
|
748
|
+
if output == "json":
|
|
749
|
+
print_json(result)
|
|
750
|
+
elif isinstance(result, dict) and "id" in result:
|
|
751
|
+
typer.echo(f"Created: {result['id']}")
|
|
752
|
+
elif not result or result == {}:
|
|
753
|
+
typer.echo("Created.")
|
|
754
|
+
else:
|
|
755
|
+
print_json(result)
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
|
|
759
|
+
@app.command("show-route-groups")
|
|
760
|
+
def show_route_groups(
|
|
761
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
762
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
763
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
764
|
+
):
|
|
765
|
+
"""Read a Route Group for a Organization."""
|
|
766
|
+
api = get_api(debug=debug)
|
|
767
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}"
|
|
768
|
+
params = {}
|
|
769
|
+
org_id = get_org_id()
|
|
770
|
+
if org_id is not None:
|
|
771
|
+
params["orgId"] = org_id
|
|
772
|
+
try:
|
|
773
|
+
result = api.session.rest_get(url, params=params)
|
|
774
|
+
except WebexError as e:
|
|
775
|
+
handle_rest_error(e)
|
|
776
|
+
if output == "json":
|
|
777
|
+
print_json(result)
|
|
778
|
+
else:
|
|
779
|
+
if isinstance(result, dict):
|
|
780
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
781
|
+
elif isinstance(result, list):
|
|
782
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
783
|
+
else:
|
|
784
|
+
print_json(result)
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
@app.command("update-route-groups")
|
|
789
|
+
def update_route_groups(
|
|
790
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
791
|
+
name: str = typer.Option(None, "--name", help="A unique name for the Route Group."),
|
|
792
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
793
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
794
|
+
):
|
|
795
|
+
"""Modify a Route Group for a Organization\n\nExample --json-body:\n '{"name":"...","localGateways":[{"id":"...","priority":"...","name":"...","locationId":"..."}]}'."""
|
|
796
|
+
api = get_api(debug=debug)
|
|
797
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}"
|
|
798
|
+
params = {}
|
|
799
|
+
org_id = get_org_id()
|
|
800
|
+
if org_id is not None:
|
|
801
|
+
params["orgId"] = org_id
|
|
802
|
+
if json_body:
|
|
803
|
+
body = json.loads(json_body)
|
|
804
|
+
else:
|
|
805
|
+
body = {}
|
|
806
|
+
if name is not None:
|
|
807
|
+
body["name"] = name
|
|
808
|
+
try:
|
|
809
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
810
|
+
except WebexError as e:
|
|
811
|
+
handle_rest_error(e)
|
|
812
|
+
typer.echo(f"Updated.")
|
|
813
|
+
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
@app.command("delete-route-groups")
|
|
817
|
+
def delete_route_groups(
|
|
818
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
819
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
820
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
821
|
+
):
|
|
822
|
+
"""Remove a Route Group from an Organization."""
|
|
823
|
+
if not force:
|
|
824
|
+
typer.confirm(f"Delete {route_group_id}?", abort=True)
|
|
825
|
+
api = get_api(debug=debug)
|
|
826
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}"
|
|
827
|
+
params = {}
|
|
828
|
+
org_id = get_org_id()
|
|
829
|
+
if org_id is not None:
|
|
830
|
+
params["orgId"] = org_id
|
|
831
|
+
try:
|
|
832
|
+
api.session.rest_delete(url, params=params)
|
|
833
|
+
except WebexError as e:
|
|
834
|
+
handle_rest_error(e)
|
|
835
|
+
typer.echo(f"Deleted: {route_group_id}")
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
@app.command("show-usage")
|
|
840
|
+
def show_usage(
|
|
841
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
842
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
843
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
844
|
+
):
|
|
845
|
+
"""Read the Usage of a Routing Group."""
|
|
846
|
+
api = get_api(debug=debug)
|
|
847
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}/usage"
|
|
848
|
+
params = {}
|
|
849
|
+
org_id = get_org_id()
|
|
850
|
+
if org_id is not None:
|
|
851
|
+
params["orgId"] = org_id
|
|
852
|
+
try:
|
|
853
|
+
result = api.session.rest_get(url, params=params)
|
|
854
|
+
except WebexError as e:
|
|
855
|
+
handle_rest_error(e)
|
|
856
|
+
if output == "json":
|
|
857
|
+
print_json(result)
|
|
858
|
+
else:
|
|
859
|
+
if isinstance(result, dict):
|
|
860
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
861
|
+
elif isinstance(result, list):
|
|
862
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
863
|
+
else:
|
|
864
|
+
print_json(result)
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
@app.command("list-usage-call-to-extension-route-groups")
|
|
869
|
+
def list_usage_call_to_extension_route_groups(
|
|
870
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
871
|
+
location_name: str = typer.Option(None, "--location-name", help="Return the list of locations matching the location name."),
|
|
872
|
+
order: str = typer.Option(None, "--order", help="Order the locations according to designated fields. Availab"),
|
|
873
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
874
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
875
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
876
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
877
|
+
):
|
|
878
|
+
"""Read the Call to Extension Locations of a Routing Group."""
|
|
879
|
+
api = get_api(debug=debug)
|
|
880
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}/usageCallToExtension"
|
|
881
|
+
params = {}
|
|
882
|
+
if location_name is not None:
|
|
883
|
+
params["locationName"] = location_name
|
|
884
|
+
if order is not None:
|
|
885
|
+
params["order"] = order
|
|
886
|
+
if limit > 0:
|
|
887
|
+
params["max"] = limit
|
|
888
|
+
if offset > 0:
|
|
889
|
+
params["start"] = offset
|
|
890
|
+
org_id = get_org_id()
|
|
891
|
+
if org_id is not None:
|
|
892
|
+
params["orgId"] = org_id
|
|
893
|
+
result = None
|
|
894
|
+
try:
|
|
895
|
+
result = api.session.rest_get(url, params=params)
|
|
896
|
+
except WebexError as e:
|
|
897
|
+
handle_rest_error(e)
|
|
898
|
+
result = result or []
|
|
899
|
+
items = result.get("locations", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
900
|
+
if output == "json":
|
|
901
|
+
print_json(items)
|
|
902
|
+
else:
|
|
903
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
@app.command("list-usage-dial-plan")
|
|
908
|
+
def list_usage_dial_plan(
|
|
909
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
910
|
+
location_name: str = typer.Option(None, "--location-name", help="Return the list of locations matching the location name."),
|
|
911
|
+
order: str = typer.Option(None, "--order", help="Order the locations according to designated fields. Availab"),
|
|
912
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
913
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
914
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
915
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
916
|
+
):
|
|
917
|
+
"""Read the Dial Plan Locations of a Routing Group."""
|
|
918
|
+
api = get_api(debug=debug)
|
|
919
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}/usageDialPlan"
|
|
920
|
+
params = {}
|
|
921
|
+
if location_name is not None:
|
|
922
|
+
params["locationName"] = location_name
|
|
923
|
+
if order is not None:
|
|
924
|
+
params["order"] = order
|
|
925
|
+
if limit > 0:
|
|
926
|
+
params["max"] = limit
|
|
927
|
+
if offset > 0:
|
|
928
|
+
params["start"] = offset
|
|
929
|
+
org_id = get_org_id()
|
|
930
|
+
if org_id is not None:
|
|
931
|
+
params["orgId"] = org_id
|
|
932
|
+
result = None
|
|
933
|
+
try:
|
|
934
|
+
result = api.session.rest_get(url, params=params)
|
|
935
|
+
except WebexError as e:
|
|
936
|
+
handle_rest_error(e)
|
|
937
|
+
result = result or []
|
|
938
|
+
items = result.get("locations", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
939
|
+
if output == "json":
|
|
940
|
+
print_json(items)
|
|
941
|
+
else:
|
|
942
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
|
|
946
|
+
@app.command("list-usage-pstn-connection-route-groups")
|
|
947
|
+
def list_usage_pstn_connection_route_groups(
|
|
948
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
949
|
+
location_name: str = typer.Option(None, "--location-name", help="Return the list of locations matching the location name."),
|
|
950
|
+
order: str = typer.Option(None, "--order", help="Order the locations according to designated fields. Availab"),
|
|
951
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
952
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
953
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
954
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
955
|
+
):
|
|
956
|
+
"""Read the PSTN Connection Locations of a Routing Group."""
|
|
957
|
+
api = get_api(debug=debug)
|
|
958
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}/usagePstnConnection"
|
|
959
|
+
params = {}
|
|
960
|
+
if location_name is not None:
|
|
961
|
+
params["locationName"] = location_name
|
|
962
|
+
if order is not None:
|
|
963
|
+
params["order"] = order
|
|
964
|
+
if limit > 0:
|
|
965
|
+
params["max"] = limit
|
|
966
|
+
if offset > 0:
|
|
967
|
+
params["start"] = offset
|
|
968
|
+
org_id = get_org_id()
|
|
969
|
+
if org_id is not None:
|
|
970
|
+
params["orgId"] = org_id
|
|
971
|
+
result = None
|
|
972
|
+
try:
|
|
973
|
+
result = api.session.rest_get(url, params=params)
|
|
974
|
+
except WebexError as e:
|
|
975
|
+
handle_rest_error(e)
|
|
976
|
+
result = result or []
|
|
977
|
+
items = result.get("locations", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
978
|
+
if output == "json":
|
|
979
|
+
print_json(items)
|
|
980
|
+
else:
|
|
981
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
@app.command("list-usage-route-list")
|
|
986
|
+
def list_usage_route_list(
|
|
987
|
+
route_group_id: str = typer.Argument(help="routeGroupId"),
|
|
988
|
+
name: str = typer.Option(None, "--name", help="Return the list of locations matching the location name."),
|
|
989
|
+
order: str = typer.Option(None, "--order", help="Order the locations according to designated fields. Availab"),
|
|
990
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
991
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
992
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
993
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
994
|
+
):
|
|
995
|
+
"""Read the Route Lists of a Routing Group."""
|
|
996
|
+
api = get_api(debug=debug)
|
|
997
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeGroups/{route_group_id}/usageRouteList"
|
|
998
|
+
params = {}
|
|
999
|
+
if name is not None:
|
|
1000
|
+
params["name"] = name
|
|
1001
|
+
if order is not None:
|
|
1002
|
+
params["order"] = order
|
|
1003
|
+
if limit > 0:
|
|
1004
|
+
params["max"] = limit
|
|
1005
|
+
if offset > 0:
|
|
1006
|
+
params["start"] = offset
|
|
1007
|
+
org_id = get_org_id()
|
|
1008
|
+
if org_id is not None:
|
|
1009
|
+
params["orgId"] = org_id
|
|
1010
|
+
result = None
|
|
1011
|
+
try:
|
|
1012
|
+
result = api.session.rest_get(url, params=params)
|
|
1013
|
+
except WebexError as e:
|
|
1014
|
+
handle_rest_error(e)
|
|
1015
|
+
result = result or []
|
|
1016
|
+
items = result.get("routeGroupUsageRouteListGet", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1017
|
+
if output == "json":
|
|
1018
|
+
print_json(items)
|
|
1019
|
+
else:
|
|
1020
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
@app.command("list-route-lists")
|
|
1025
|
+
def list_route_lists(
|
|
1026
|
+
order: str = typer.Option(None, "--order", help="Order the Route List according to the designated fields. Ava"),
|
|
1027
|
+
name: str = typer.Option(None, "--name", help="Return the list of Route List matching the route list name."),
|
|
1028
|
+
location_id: str = typer.Option(None, "--location-id", help="Return the list of Route Lists matching the location id."),
|
|
1029
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1030
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1031
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1032
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1033
|
+
):
|
|
1034
|
+
"""Read the List of Route Lists."""
|
|
1035
|
+
api = get_api(debug=debug)
|
|
1036
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists"
|
|
1037
|
+
params = {}
|
|
1038
|
+
if order is not None:
|
|
1039
|
+
params["order"] = order
|
|
1040
|
+
if name is not None:
|
|
1041
|
+
params["name"] = name
|
|
1042
|
+
if location_id is not None:
|
|
1043
|
+
params["locationId"] = location_id
|
|
1044
|
+
if limit > 0:
|
|
1045
|
+
params["max"] = limit
|
|
1046
|
+
if offset > 0:
|
|
1047
|
+
params["start"] = offset
|
|
1048
|
+
org_id = get_org_id()
|
|
1049
|
+
if org_id is not None:
|
|
1050
|
+
params["orgId"] = org_id
|
|
1051
|
+
result = None
|
|
1052
|
+
try:
|
|
1053
|
+
result = api.session.rest_get(url, params=params)
|
|
1054
|
+
except WebexError as e:
|
|
1055
|
+
handle_rest_error(e)
|
|
1056
|
+
result = result or []
|
|
1057
|
+
items = result.get("routeLists", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1058
|
+
if output == "json":
|
|
1059
|
+
print_json(items)
|
|
1060
|
+
else:
|
|
1061
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
@app.command("create-route-lists")
|
|
1066
|
+
def create_route_lists(
|
|
1067
|
+
name: str = typer.Option(None, "--name", help="(required) Name of the Route List"),
|
|
1068
|
+
location_id: str = typer.Option(None, "--location-id", help="(required) Location associated with the Route List."),
|
|
1069
|
+
route_group_id: str = typer.Option(None, "--route-group-id", help="(required) ID of the route group associated with Route List."),
|
|
1070
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1071
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1072
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1073
|
+
):
|
|
1074
|
+
"""Create a Route List."""
|
|
1075
|
+
api = get_api(debug=debug)
|
|
1076
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists"
|
|
1077
|
+
params = {}
|
|
1078
|
+
org_id = get_org_id()
|
|
1079
|
+
if org_id is not None:
|
|
1080
|
+
params["orgId"] = org_id
|
|
1081
|
+
if json_body:
|
|
1082
|
+
body = json.loads(json_body)
|
|
1083
|
+
else:
|
|
1084
|
+
body = {}
|
|
1085
|
+
if name is not None:
|
|
1086
|
+
body["name"] = name
|
|
1087
|
+
if location_id is not None:
|
|
1088
|
+
body["locationId"] = location_id
|
|
1089
|
+
if route_group_id is not None:
|
|
1090
|
+
body["routeGroupId"] = route_group_id
|
|
1091
|
+
_missing = [f for f in ['name', 'locationId', 'routeGroupId'] if f not in body or body[f] is None]
|
|
1092
|
+
if _missing:
|
|
1093
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1094
|
+
raise typer.Exit(1)
|
|
1095
|
+
try:
|
|
1096
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1097
|
+
except WebexError as e:
|
|
1098
|
+
handle_rest_error(e)
|
|
1099
|
+
if output == "json":
|
|
1100
|
+
print_json(result)
|
|
1101
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1102
|
+
typer.echo(f"Created: {result['id']}")
|
|
1103
|
+
elif not result or result == {}:
|
|
1104
|
+
typer.echo("Created.")
|
|
1105
|
+
else:
|
|
1106
|
+
print_json(result)
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
@app.command("show-route-lists")
|
|
1111
|
+
def show_route_lists(
|
|
1112
|
+
route_list_id: str = typer.Argument(help="routeListId"),
|
|
1113
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1114
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1115
|
+
):
|
|
1116
|
+
"""Get a Route List."""
|
|
1117
|
+
api = get_api(debug=debug)
|
|
1118
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists/{route_list_id}"
|
|
1119
|
+
params = {}
|
|
1120
|
+
org_id = get_org_id()
|
|
1121
|
+
if org_id is not None:
|
|
1122
|
+
params["orgId"] = org_id
|
|
1123
|
+
try:
|
|
1124
|
+
result = api.session.rest_get(url, params=params)
|
|
1125
|
+
except WebexError as e:
|
|
1126
|
+
handle_rest_error(e)
|
|
1127
|
+
if output == "json":
|
|
1128
|
+
print_json(result)
|
|
1129
|
+
else:
|
|
1130
|
+
if isinstance(result, dict):
|
|
1131
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1132
|
+
elif isinstance(result, list):
|
|
1133
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1134
|
+
else:
|
|
1135
|
+
print_json(result)
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
@app.command("update-route-lists")
|
|
1140
|
+
def update_route_lists(
|
|
1141
|
+
route_list_id: str = typer.Argument(help="routeListId"),
|
|
1142
|
+
name: str = typer.Option(None, "--name", help="Route List new name."),
|
|
1143
|
+
route_group_id: str = typer.Option(None, "--route-group-id", help="New route group ID."),
|
|
1144
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1145
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1146
|
+
):
|
|
1147
|
+
"""Modify a Route List."""
|
|
1148
|
+
api = get_api(debug=debug)
|
|
1149
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists/{route_list_id}"
|
|
1150
|
+
params = {}
|
|
1151
|
+
org_id = get_org_id()
|
|
1152
|
+
if org_id is not None:
|
|
1153
|
+
params["orgId"] = org_id
|
|
1154
|
+
if json_body:
|
|
1155
|
+
body = json.loads(json_body)
|
|
1156
|
+
else:
|
|
1157
|
+
body = {}
|
|
1158
|
+
if name is not None:
|
|
1159
|
+
body["name"] = name
|
|
1160
|
+
if route_group_id is not None:
|
|
1161
|
+
body["routeGroupId"] = route_group_id
|
|
1162
|
+
try:
|
|
1163
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1164
|
+
except WebexError as e:
|
|
1165
|
+
handle_rest_error(e)
|
|
1166
|
+
typer.echo(f"Updated.")
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
@app.command("delete-route-lists")
|
|
1171
|
+
def delete_route_lists(
|
|
1172
|
+
route_list_id: str = typer.Argument(help="routeListId"),
|
|
1173
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1174
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1175
|
+
):
|
|
1176
|
+
"""Delete a Route List."""
|
|
1177
|
+
if not force:
|
|
1178
|
+
typer.confirm(f"Delete {route_list_id}?", abort=True)
|
|
1179
|
+
api = get_api(debug=debug)
|
|
1180
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists/{route_list_id}"
|
|
1181
|
+
params = {}
|
|
1182
|
+
org_id = get_org_id()
|
|
1183
|
+
if org_id is not None:
|
|
1184
|
+
params["orgId"] = org_id
|
|
1185
|
+
try:
|
|
1186
|
+
api.session.rest_delete(url, params=params)
|
|
1187
|
+
except WebexError as e:
|
|
1188
|
+
handle_rest_error(e)
|
|
1189
|
+
typer.echo(f"Deleted: {route_list_id}")
|
|
1190
|
+
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
@app.command("list-numbers")
|
|
1194
|
+
def list_numbers(
|
|
1195
|
+
route_list_id: str = typer.Argument(help="routeListId"),
|
|
1196
|
+
number: str = typer.Option(None, "--number", help="Number assigned to the route list."),
|
|
1197
|
+
order: str = typer.Option(None, "--order", help="Order the Route Lists according to number, ascending or desc"),
|
|
1198
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1199
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1200
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1201
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1202
|
+
):
|
|
1203
|
+
"""Get Numbers assigned to a Route List."""
|
|
1204
|
+
api = get_api(debug=debug)
|
|
1205
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists/{route_list_id}/numbers"
|
|
1206
|
+
params = {}
|
|
1207
|
+
if number is not None:
|
|
1208
|
+
params["number"] = number
|
|
1209
|
+
if order is not None:
|
|
1210
|
+
params["order"] = order
|
|
1211
|
+
if limit > 0:
|
|
1212
|
+
params["max"] = limit
|
|
1213
|
+
if offset > 0:
|
|
1214
|
+
params["start"] = offset
|
|
1215
|
+
org_id = get_org_id()
|
|
1216
|
+
if org_id is not None:
|
|
1217
|
+
params["orgId"] = org_id
|
|
1218
|
+
result = None
|
|
1219
|
+
try:
|
|
1220
|
+
result = api.session.rest_get(url, params=params)
|
|
1221
|
+
except WebexError as e:
|
|
1222
|
+
handle_rest_error(e)
|
|
1223
|
+
result = result or []
|
|
1224
|
+
items = result.get("numbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1225
|
+
if output == "json":
|
|
1226
|
+
print_json(items)
|
|
1227
|
+
else:
|
|
1228
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
@app.command("update-numbers")
|
|
1233
|
+
def update_numbers(
|
|
1234
|
+
route_list_id: str = typer.Argument(help="routeListId"),
|
|
1235
|
+
delete_all_numbers: bool = typer.Option(None, "--delete-all-numbers/--no-delete-all-numbers", help="If present, the numbers array is ignored and all numbers in"),
|
|
1236
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1237
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1238
|
+
):
|
|
1239
|
+
"""Modify Numbers for Route List\n\nExample --json-body:\n '{"numbers":[{"number":"...","action":"..."}],"deleteAllNumbers":true}'."""
|
|
1240
|
+
api = get_api(debug=debug)
|
|
1241
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/routeLists/{route_list_id}/numbers"
|
|
1242
|
+
params = {}
|
|
1243
|
+
org_id = get_org_id()
|
|
1244
|
+
if org_id is not None:
|
|
1245
|
+
params["orgId"] = org_id
|
|
1246
|
+
if json_body:
|
|
1247
|
+
body = json.loads(json_body)
|
|
1248
|
+
else:
|
|
1249
|
+
body = {}
|
|
1250
|
+
if delete_all_numbers is not None:
|
|
1251
|
+
body["deleteAllNumbers"] = delete_all_numbers
|
|
1252
|
+
try:
|
|
1253
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1254
|
+
except WebexError as e:
|
|
1255
|
+
handle_rest_error(e)
|
|
1256
|
+
typer.echo(f"Updated.")
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
@app.command("list-usage-call-to-extension-trunks")
|
|
1261
|
+
def list_usage_call_to_extension_trunks(
|
|
1262
|
+
trunk_id: str = typer.Argument(help="trunkId"),
|
|
1263
|
+
order: str = typer.Option(None, "--order", help="Order the trunks according to the designated fields. Availa"),
|
|
1264
|
+
name: str = typer.Option(None, "--name", help="Return the list of trunks matching the local gateway names"),
|
|
1265
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1266
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1267
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1268
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1269
|
+
):
|
|
1270
|
+
"""Get Local Gateway Call to On-Premises Extension Usage for a Trunk."""
|
|
1271
|
+
api = get_api(debug=debug)
|
|
1272
|
+
url = f"https://webexapis.com/v1/telephony/config/premisePstn/trunks/{trunk_id}/usageCallToExtension"
|
|
1273
|
+
params = {}
|
|
1274
|
+
if order is not None:
|
|
1275
|
+
params["order"] = order
|
|
1276
|
+
if name is not None:
|
|
1277
|
+
params["name"] = name
|
|
1278
|
+
if limit > 0:
|
|
1279
|
+
params["max"] = limit
|
|
1280
|
+
if offset > 0:
|
|
1281
|
+
params["start"] = offset
|
|
1282
|
+
org_id = get_org_id()
|
|
1283
|
+
if org_id is not None:
|
|
1284
|
+
params["orgId"] = org_id
|
|
1285
|
+
result = None
|
|
1286
|
+
try:
|
|
1287
|
+
result = api.session.rest_get(url, params=params)
|
|
1288
|
+
except WebexError as e:
|
|
1289
|
+
handle_rest_error(e)
|
|
1290
|
+
result = result or []
|
|
1291
|
+
items = result.get("locations", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1292
|
+
if output == "json":
|
|
1293
|
+
print_json(items)
|
|
1294
|
+
else:
|
|
1295
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
1296
|
+
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
@app.command("list-translation-patterns")
|
|
1300
|
+
def list_translation_patterns(
|
|
1301
|
+
limit_to_location_id: str = typer.Option(None, "--limit-to-location-id", help="When a location ID is passed, then return only the correspon"),
|
|
1302
|
+
limit_to_org_level_enabled: str = typer.Option(None, "--limit-to-org-level-enabled", help="When set to be `true`, then return only the organization-lev"),
|
|
1303
|
+
order: str = typer.Option(None, "--order", help="Sort the list of translation patterns according to translati"),
|
|
1304
|
+
name: str = typer.Option(None, "--name", help="Only return translation patterns with the matching `name`."),
|
|
1305
|
+
matching_pattern: str = typer.Option(None, "--matching-pattern", help="Only return translation patterns with the matching `matching"),
|
|
1306
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1307
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1308
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1309
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1310
|
+
):
|
|
1311
|
+
"""Retrieve the list of Translation Patterns."""
|
|
1312
|
+
api = get_api(debug=debug)
|
|
1313
|
+
url = f"https://webexapis.com/v1/telephony/config/callRouting/translationPatterns"
|
|
1314
|
+
params = {}
|
|
1315
|
+
if limit_to_location_id is not None:
|
|
1316
|
+
params["limitToLocationId"] = limit_to_location_id
|
|
1317
|
+
if limit_to_org_level_enabled is not None:
|
|
1318
|
+
params["limitToOrgLevelEnabled"] = limit_to_org_level_enabled
|
|
1319
|
+
if order is not None:
|
|
1320
|
+
params["order"] = order
|
|
1321
|
+
if name is not None:
|
|
1322
|
+
params["name"] = name
|
|
1323
|
+
if matching_pattern is not None:
|
|
1324
|
+
params["matchingPattern"] = matching_pattern
|
|
1325
|
+
if limit > 0:
|
|
1326
|
+
params["max"] = limit
|
|
1327
|
+
if offset > 0:
|
|
1328
|
+
params["start"] = offset
|
|
1329
|
+
org_id = get_org_id()
|
|
1330
|
+
if org_id is not None:
|
|
1331
|
+
params["orgId"] = org_id
|
|
1332
|
+
result = None
|
|
1333
|
+
try:
|
|
1334
|
+
result = api.session.rest_get(url, params=params)
|
|
1335
|
+
except WebexError as e:
|
|
1336
|
+
handle_rest_error(e)
|
|
1337
|
+
result = result or []
|
|
1338
|
+
items = result.get("translationPatterns", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1339
|
+
if output == "json":
|
|
1340
|
+
print_json(items)
|
|
1341
|
+
else:
|
|
1342
|
+
print_table(items, columns=[('ID', 'id'), ('Name', 'name'), ('Route Type', 'routeType')], limit=limit)
|
|
1343
|
+
|
|
1344
|
+
|
|
1345
|
+
|
|
1346
|
+
@app.command("create-translation-patterns-call-routing")
|
|
1347
|
+
def create_translation_patterns_call_routing(
|
|
1348
|
+
name: str = typer.Option(None, "--name", help="(required) Name given to a translation pattern for an organization."),
|
|
1349
|
+
matching_pattern: str = typer.Option(None, "--matching-pattern", help="(required) Matching pattern given to a translation pattern for an organ"),
|
|
1350
|
+
replacement_pattern: str = typer.Option(None, "--replacement-pattern", help="(required) Replacement pattern given to a translation pattern for an or"),
|
|
1351
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1352
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1353
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1354
|
+
):
|
|
1355
|
+
"""Create a Translation Pattern for an Organization."""
|
|
1356
|
+
api = get_api(debug=debug)
|
|
1357
|
+
url = f"https://webexapis.com/v1/telephony/config/callRouting/translationPatterns"
|
|
1358
|
+
params = {}
|
|
1359
|
+
org_id = get_org_id()
|
|
1360
|
+
if org_id is not None:
|
|
1361
|
+
params["orgId"] = org_id
|
|
1362
|
+
if json_body:
|
|
1363
|
+
body = json.loads(json_body)
|
|
1364
|
+
else:
|
|
1365
|
+
body = {}
|
|
1366
|
+
if name is not None:
|
|
1367
|
+
body["name"] = name
|
|
1368
|
+
if matching_pattern is not None:
|
|
1369
|
+
body["matchingPattern"] = matching_pattern
|
|
1370
|
+
if replacement_pattern is not None:
|
|
1371
|
+
body["replacementPattern"] = replacement_pattern
|
|
1372
|
+
_missing = [f for f in ['name', 'matchingPattern', 'replacementPattern'] if f not in body or body[f] is None]
|
|
1373
|
+
if _missing:
|
|
1374
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1375
|
+
raise typer.Exit(1)
|
|
1376
|
+
try:
|
|
1377
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1378
|
+
except WebexError as e:
|
|
1379
|
+
handle_rest_error(e)
|
|
1380
|
+
if output == "json":
|
|
1381
|
+
print_json(result)
|
|
1382
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1383
|
+
typer.echo(f"Created: {result['id']}")
|
|
1384
|
+
elif not result or result == {}:
|
|
1385
|
+
typer.echo("Created.")
|
|
1386
|
+
else:
|
|
1387
|
+
print_json(result)
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
@app.command("show-translation-patterns-call-routing")
|
|
1392
|
+
def show_translation_patterns_call_routing(
|
|
1393
|
+
translation_id: str = typer.Argument(help="translationId"),
|
|
1394
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1395
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1396
|
+
):
|
|
1397
|
+
"""Retrieve a specific Translation Pattern for an Organization."""
|
|
1398
|
+
api = get_api(debug=debug)
|
|
1399
|
+
url = f"https://webexapis.com/v1/telephony/config/callRouting/translationPatterns/{translation_id}"
|
|
1400
|
+
params = {}
|
|
1401
|
+
org_id = get_org_id()
|
|
1402
|
+
if org_id is not None:
|
|
1403
|
+
params["orgId"] = org_id
|
|
1404
|
+
try:
|
|
1405
|
+
result = api.session.rest_get(url, params=params)
|
|
1406
|
+
except WebexError as e:
|
|
1407
|
+
handle_rest_error(e)
|
|
1408
|
+
if output == "json":
|
|
1409
|
+
print_json(result)
|
|
1410
|
+
else:
|
|
1411
|
+
if isinstance(result, dict):
|
|
1412
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1413
|
+
elif isinstance(result, list):
|
|
1414
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1415
|
+
else:
|
|
1416
|
+
print_json(result)
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
|
|
1420
|
+
@app.command("update-translation-patterns-call-routing")
|
|
1421
|
+
def update_translation_patterns_call_routing(
|
|
1422
|
+
translation_id: str = typer.Argument(help="translationId"),
|
|
1423
|
+
name: str = typer.Option(None, "--name", help="Name given to a translation pattern for an organization."),
|
|
1424
|
+
matching_pattern: str = typer.Option(None, "--matching-pattern", help="Matching pattern given to a translation pattern for an organ"),
|
|
1425
|
+
replacement_pattern: str = typer.Option(None, "--replacement-pattern", help="Replacement pattern given to a translation pattern for an or"),
|
|
1426
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1427
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1428
|
+
):
|
|
1429
|
+
"""Modify a specific Translation Pattern for an Organization."""
|
|
1430
|
+
api = get_api(debug=debug)
|
|
1431
|
+
url = f"https://webexapis.com/v1/telephony/config/callRouting/translationPatterns/{translation_id}"
|
|
1432
|
+
params = {}
|
|
1433
|
+
org_id = get_org_id()
|
|
1434
|
+
if org_id is not None:
|
|
1435
|
+
params["orgId"] = org_id
|
|
1436
|
+
if json_body:
|
|
1437
|
+
body = json.loads(json_body)
|
|
1438
|
+
else:
|
|
1439
|
+
body = {}
|
|
1440
|
+
if name is not None:
|
|
1441
|
+
body["name"] = name
|
|
1442
|
+
if matching_pattern is not None:
|
|
1443
|
+
body["matchingPattern"] = matching_pattern
|
|
1444
|
+
if replacement_pattern is not None:
|
|
1445
|
+
body["replacementPattern"] = replacement_pattern
|
|
1446
|
+
try:
|
|
1447
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1448
|
+
except WebexError as e:
|
|
1449
|
+
handle_rest_error(e)
|
|
1450
|
+
typer.echo(f"Updated.")
|
|
1451
|
+
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
@app.command("delete-translation-patterns-call-routing")
|
|
1455
|
+
def delete_translation_patterns_call_routing(
|
|
1456
|
+
translation_id: str = typer.Argument(help="translationId"),
|
|
1457
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1458
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1459
|
+
):
|
|
1460
|
+
"""Delete a specific Translation Pattern."""
|
|
1461
|
+
if not force:
|
|
1462
|
+
typer.confirm(f"Delete {translation_id}?", abort=True)
|
|
1463
|
+
api = get_api(debug=debug)
|
|
1464
|
+
url = f"https://webexapis.com/v1/telephony/config/callRouting/translationPatterns/{translation_id}"
|
|
1465
|
+
params = {}
|
|
1466
|
+
org_id = get_org_id()
|
|
1467
|
+
if org_id is not None:
|
|
1468
|
+
params["orgId"] = org_id
|
|
1469
|
+
try:
|
|
1470
|
+
api.session.rest_delete(url, params=params)
|
|
1471
|
+
except WebexError as e:
|
|
1472
|
+
handle_rest_error(e)
|
|
1473
|
+
typer.echo(f"Deleted: {translation_id}")
|
|
1474
|
+
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
@app.command("create-translation-patterns-call-routing-1")
|
|
1478
|
+
def create_translation_patterns_call_routing_1(
|
|
1479
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1480
|
+
name: str = typer.Option(None, "--name", help="(required) A name given to a translation pattern for a location."),
|
|
1481
|
+
matching_pattern: str = typer.Option(None, "--matching-pattern", help="(required) A matching pattern given to a translation pattern for a loca"),
|
|
1482
|
+
replacement_pattern: str = typer.Option(None, "--replacement-pattern", help="(required) A replacement pattern given to a translation pattern for a l"),
|
|
1483
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1484
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1485
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1486
|
+
):
|
|
1487
|
+
"""Create a Translation Pattern for a Location."""
|
|
1488
|
+
api = get_api(debug=debug)
|
|
1489
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRouting/translationPatterns"
|
|
1490
|
+
params = {}
|
|
1491
|
+
org_id = get_org_id()
|
|
1492
|
+
if org_id is not None:
|
|
1493
|
+
params["orgId"] = org_id
|
|
1494
|
+
if json_body:
|
|
1495
|
+
body = json.loads(json_body)
|
|
1496
|
+
else:
|
|
1497
|
+
body = {}
|
|
1498
|
+
if name is not None:
|
|
1499
|
+
body["name"] = name
|
|
1500
|
+
if matching_pattern is not None:
|
|
1501
|
+
body["matchingPattern"] = matching_pattern
|
|
1502
|
+
if replacement_pattern is not None:
|
|
1503
|
+
body["replacementPattern"] = replacement_pattern
|
|
1504
|
+
_missing = [f for f in ['name', 'matchingPattern', 'replacementPattern'] if f not in body or body[f] is None]
|
|
1505
|
+
if _missing:
|
|
1506
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1507
|
+
raise typer.Exit(1)
|
|
1508
|
+
try:
|
|
1509
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1510
|
+
except WebexError as e:
|
|
1511
|
+
handle_rest_error(e)
|
|
1512
|
+
if output == "json":
|
|
1513
|
+
print_json(result)
|
|
1514
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1515
|
+
typer.echo(f"Created: {result['id']}")
|
|
1516
|
+
elif not result or result == {}:
|
|
1517
|
+
typer.echo("Created.")
|
|
1518
|
+
else:
|
|
1519
|
+
print_json(result)
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
|
|
1523
|
+
@app.command("show-translation-patterns-call-routing-1")
|
|
1524
|
+
def show_translation_patterns_call_routing_1(
|
|
1525
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1526
|
+
translation_id: str = typer.Argument(help="translationId"),
|
|
1527
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1528
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1529
|
+
):
|
|
1530
|
+
"""Retrieve a specific Translation Pattern for a Location."""
|
|
1531
|
+
api = get_api(debug=debug)
|
|
1532
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRouting/translationPatterns/{translation_id}"
|
|
1533
|
+
params = {}
|
|
1534
|
+
org_id = get_org_id()
|
|
1535
|
+
if org_id is not None:
|
|
1536
|
+
params["orgId"] = org_id
|
|
1537
|
+
try:
|
|
1538
|
+
result = api.session.rest_get(url, params=params)
|
|
1539
|
+
except WebexError as e:
|
|
1540
|
+
handle_rest_error(e)
|
|
1541
|
+
if output == "json":
|
|
1542
|
+
print_json(result)
|
|
1543
|
+
else:
|
|
1544
|
+
if isinstance(result, dict):
|
|
1545
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1546
|
+
elif isinstance(result, list):
|
|
1547
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1548
|
+
else:
|
|
1549
|
+
print_json(result)
|
|
1550
|
+
|
|
1551
|
+
|
|
1552
|
+
|
|
1553
|
+
@app.command("update-translation-patterns-call-routing-1")
|
|
1554
|
+
def update_translation_patterns_call_routing_1(
|
|
1555
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1556
|
+
translation_id: str = typer.Argument(help="translationId"),
|
|
1557
|
+
name: str = typer.Option(None, "--name", help="A name given to a translation pattern for a location."),
|
|
1558
|
+
matching_pattern: str = typer.Option(None, "--matching-pattern", help="A matching pattern given to a translation pattern for a loca"),
|
|
1559
|
+
replacement_pattern: str = typer.Option(None, "--replacement-pattern", help="A replacement pattern given to a translation pattern for a l"),
|
|
1560
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1561
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1562
|
+
):
|
|
1563
|
+
"""Modify a specific Translation Pattern for a Location."""
|
|
1564
|
+
api = get_api(debug=debug)
|
|
1565
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRouting/translationPatterns/{translation_id}"
|
|
1566
|
+
params = {}
|
|
1567
|
+
org_id = get_org_id()
|
|
1568
|
+
if org_id is not None:
|
|
1569
|
+
params["orgId"] = org_id
|
|
1570
|
+
if json_body:
|
|
1571
|
+
body = json.loads(json_body)
|
|
1572
|
+
else:
|
|
1573
|
+
body = {}
|
|
1574
|
+
if name is not None:
|
|
1575
|
+
body["name"] = name
|
|
1576
|
+
if matching_pattern is not None:
|
|
1577
|
+
body["matchingPattern"] = matching_pattern
|
|
1578
|
+
if replacement_pattern is not None:
|
|
1579
|
+
body["replacementPattern"] = replacement_pattern
|
|
1580
|
+
try:
|
|
1581
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1582
|
+
except WebexError as e:
|
|
1583
|
+
handle_rest_error(e)
|
|
1584
|
+
typer.echo(f"Updated.")
|
|
1585
|
+
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
@app.command("delete-translation-patterns-call-routing-1")
|
|
1589
|
+
def delete_translation_patterns_call_routing_1(
|
|
1590
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
1591
|
+
translation_id: str = typer.Argument(help="translationId"),
|
|
1592
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1593
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1594
|
+
):
|
|
1595
|
+
"""Delete a specific Translation Pattern for a Location."""
|
|
1596
|
+
if not force:
|
|
1597
|
+
typer.confirm(f"Delete {translation_id}?", abort=True)
|
|
1598
|
+
api = get_api(debug=debug)
|
|
1599
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/callRouting/translationPatterns/{translation_id}"
|
|
1600
|
+
params = {}
|
|
1601
|
+
org_id = get_org_id()
|
|
1602
|
+
if org_id is not None:
|
|
1603
|
+
params["orgId"] = org_id
|
|
1604
|
+
try:
|
|
1605
|
+
api.session.rest_delete(url, params=params)
|
|
1606
|
+
except WebexError as e:
|
|
1607
|
+
handle_rest_error(e)
|
|
1608
|
+
typer.echo(f"Deleted: {translation_id}")
|
|
1609
|
+
|
|
1610
|
+
|