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,2072 @@
|
|
|
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 virtual-line-settings.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
location_id: str = typer.Option(None, "--location-id", help="Return the list of virtual lines matching these location ids"),
|
|
15
|
+
id_param: str = typer.Option(None, "--id", help="Return the list of virtual lines matching these virtualLineI"),
|
|
16
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of virtual lines matching these owner names."),
|
|
17
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Return the list of virtual lines matching these phone number"),
|
|
18
|
+
location_name: str = typer.Option(None, "--location-name", help="Return the list of virtual lines matching the location names"),
|
|
19
|
+
order: str = typer.Option(None, "--order", help="Return the list of virtual lines based on the order. Default"),
|
|
20
|
+
has_device_assigned: str = typer.Option(None, "--has-device-assigned", help="If `true`, includes only virtual lines with devices assigned"),
|
|
21
|
+
has_extension_assigned: str = typer.Option(None, "--has-extension-assigned", help="If `true`, includes only virtual lines with an extension ass"),
|
|
22
|
+
has_dn_assigned: str = typer.Option(None, "--has-dn-assigned", help="If `true`, includes only virtual lines with an assigned dire"),
|
|
23
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
24
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
25
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
26
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
27
|
+
):
|
|
28
|
+
"""Read the List of Virtual Lines."""
|
|
29
|
+
api = get_api(debug=debug)
|
|
30
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines"
|
|
31
|
+
params = {}
|
|
32
|
+
if location_id is not None:
|
|
33
|
+
params["locationId"] = location_id
|
|
34
|
+
if id_param is not None:
|
|
35
|
+
params["id"] = id_param
|
|
36
|
+
if owner_name is not None:
|
|
37
|
+
params["ownerName"] = owner_name
|
|
38
|
+
if phone_number is not None:
|
|
39
|
+
params["phoneNumber"] = phone_number
|
|
40
|
+
if location_name is not None:
|
|
41
|
+
params["locationName"] = location_name
|
|
42
|
+
if order is not None:
|
|
43
|
+
params["order"] = order
|
|
44
|
+
if has_device_assigned is not None:
|
|
45
|
+
params["hasDeviceAssigned"] = has_device_assigned
|
|
46
|
+
if has_extension_assigned is not None:
|
|
47
|
+
params["hasExtensionAssigned"] = has_extension_assigned
|
|
48
|
+
if has_dn_assigned is not None:
|
|
49
|
+
params["hasDnAssigned"] = has_dn_assigned
|
|
50
|
+
if limit > 0:
|
|
51
|
+
params["max"] = limit
|
|
52
|
+
if offset > 0:
|
|
53
|
+
params["start"] = offset
|
|
54
|
+
org_id = get_org_id()
|
|
55
|
+
if org_id is not None:
|
|
56
|
+
params["orgId"] = org_id
|
|
57
|
+
try:
|
|
58
|
+
if limit > 0:
|
|
59
|
+
result = api.session.rest_get(url, params=params)
|
|
60
|
+
result = result or {}
|
|
61
|
+
items = result.get("virtualLines", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
62
|
+
else:
|
|
63
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="virtualLines"))
|
|
64
|
+
except WebexError as e:
|
|
65
|
+
handle_rest_error(e)
|
|
66
|
+
if output == "json":
|
|
67
|
+
print_json(items)
|
|
68
|
+
else:
|
|
69
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@app.command("create")
|
|
74
|
+
def create(
|
|
75
|
+
first_name: str = typer.Option(None, "--first-name", help="(required) First name defined for a virtual line. Minimum length is 1."),
|
|
76
|
+
last_name: str = typer.Option(None, "--last-name", help="(required) Last name defined for a virtual line. Minimum length is 1. M"),
|
|
77
|
+
display_name: str = typer.Option(None, "--display-name", help="Display name defined for a virtual line."),
|
|
78
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Phone number of a virtual line. Minimum length is 1. Maximum"),
|
|
79
|
+
extension: str = typer.Option(None, "--extension", help="Extension of a virtual line. Minimum length is 2. Maximum le"),
|
|
80
|
+
location_id: str = typer.Option(None, "--location-id", help="(required) ID of location for virtual line."),
|
|
81
|
+
caller_id_last_name: str = typer.Option(None, "--caller-id-last-name", help="Last name used in the Calling Line ID and for dial-by-name f"),
|
|
82
|
+
caller_id_first_name: str = typer.Option(None, "--caller-id-first-name", help="First name used in the Calling Line ID and for dial-by-name"),
|
|
83
|
+
caller_id_number: str = typer.Option(None, "--caller-id-number", help="Phone number to appear as the CLID for all calls. Minimum le"),
|
|
84
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
85
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
86
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
87
|
+
):
|
|
88
|
+
"""Create a Virtual Line."""
|
|
89
|
+
api = get_api(debug=debug)
|
|
90
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines"
|
|
91
|
+
params = {}
|
|
92
|
+
org_id = get_org_id()
|
|
93
|
+
if org_id is not None:
|
|
94
|
+
params["orgId"] = org_id
|
|
95
|
+
if json_body:
|
|
96
|
+
body = json.loads(json_body)
|
|
97
|
+
else:
|
|
98
|
+
body = {}
|
|
99
|
+
if first_name is not None:
|
|
100
|
+
body["firstName"] = first_name
|
|
101
|
+
if last_name is not None:
|
|
102
|
+
body["lastName"] = last_name
|
|
103
|
+
if display_name is not None:
|
|
104
|
+
body["displayName"] = display_name
|
|
105
|
+
if phone_number is not None:
|
|
106
|
+
body["phoneNumber"] = phone_number
|
|
107
|
+
if extension is not None:
|
|
108
|
+
body["extension"] = extension
|
|
109
|
+
if location_id is not None:
|
|
110
|
+
body["locationId"] = location_id
|
|
111
|
+
if caller_id_last_name is not None:
|
|
112
|
+
body["callerIdLastName"] = caller_id_last_name
|
|
113
|
+
if caller_id_first_name is not None:
|
|
114
|
+
body["callerIdFirstName"] = caller_id_first_name
|
|
115
|
+
if caller_id_number is not None:
|
|
116
|
+
body["callerIdNumber"] = caller_id_number
|
|
117
|
+
_missing = [f for f in ['firstName', 'lastName', 'locationId'] if f not in body or body[f] is None]
|
|
118
|
+
if _missing:
|
|
119
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
120
|
+
raise typer.Exit(1)
|
|
121
|
+
try:
|
|
122
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
123
|
+
except WebexError as e:
|
|
124
|
+
handle_rest_error(e)
|
|
125
|
+
if output == "json":
|
|
126
|
+
print_json(result)
|
|
127
|
+
elif isinstance(result, dict) and "id" in result:
|
|
128
|
+
typer.echo(f"Created: {result['id']}")
|
|
129
|
+
elif not result or result == {}:
|
|
130
|
+
typer.echo("Created.")
|
|
131
|
+
else:
|
|
132
|
+
print_json(result)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@app.command("show")
|
|
137
|
+
def show(
|
|
138
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
139
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
140
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
141
|
+
):
|
|
142
|
+
"""Read Call Recording Settings for a Virtual Line."""
|
|
143
|
+
api = get_api(debug=debug)
|
|
144
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callRecording"
|
|
145
|
+
params = {}
|
|
146
|
+
org_id = get_org_id()
|
|
147
|
+
if org_id is not None:
|
|
148
|
+
params["orgId"] = org_id
|
|
149
|
+
try:
|
|
150
|
+
result = api.session.rest_get(url, params=params)
|
|
151
|
+
except WebexError as e:
|
|
152
|
+
handle_rest_error(e)
|
|
153
|
+
if output == "json":
|
|
154
|
+
print_json(result)
|
|
155
|
+
else:
|
|
156
|
+
if isinstance(result, dict):
|
|
157
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
158
|
+
elif isinstance(result, list):
|
|
159
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
160
|
+
else:
|
|
161
|
+
print_json(result)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@app.command("update")
|
|
166
|
+
def update(
|
|
167
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
168
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if call recording is enabled."),
|
|
169
|
+
record: str = typer.Option(None, "--record", help="Choices: Always, Never, Always with Pause/Resume, On Demand with User Initiated Start"),
|
|
170
|
+
record_voicemail_enabled: bool = typer.Option(None, "--record-voicemail-enabled/--no-record-voicemail-enabled", help="When `true`, voicemail messages are also recorded."),
|
|
171
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
172
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
173
|
+
):
|
|
174
|
+
"""Configure Call Recording Settings for a Virtual Line\n\nExample --json-body:\n '{"enabled":true,"record":"Always","recordVoicemailEnabled":true,"notification":{"type":"Beep","enabled":true},"repeat":{"interval":0,"enabled":true},"startStopAnnouncement":{"internalCallsEnabled":true,"pstnCallsEnabled":true}}'."""
|
|
175
|
+
api = get_api(debug=debug)
|
|
176
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callRecording"
|
|
177
|
+
params = {}
|
|
178
|
+
org_id = get_org_id()
|
|
179
|
+
if org_id is not None:
|
|
180
|
+
params["orgId"] = org_id
|
|
181
|
+
if json_body:
|
|
182
|
+
body = json.loads(json_body)
|
|
183
|
+
else:
|
|
184
|
+
body = {}
|
|
185
|
+
if enabled is not None:
|
|
186
|
+
body["enabled"] = enabled
|
|
187
|
+
if record is not None:
|
|
188
|
+
body["record"] = record
|
|
189
|
+
if record_voicemail_enabled is not None:
|
|
190
|
+
body["recordVoicemailEnabled"] = record_voicemail_enabled
|
|
191
|
+
try:
|
|
192
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
193
|
+
except WebexError as e:
|
|
194
|
+
handle_rest_error(e)
|
|
195
|
+
typer.echo(f"Updated.")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@app.command("show-virtual-lines")
|
|
200
|
+
def show_virtual_lines(
|
|
201
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
202
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
203
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
204
|
+
):
|
|
205
|
+
"""Get Details for a Virtual Line."""
|
|
206
|
+
api = get_api(debug=debug)
|
|
207
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}"
|
|
208
|
+
params = {}
|
|
209
|
+
org_id = get_org_id()
|
|
210
|
+
if org_id is not None:
|
|
211
|
+
params["orgId"] = org_id
|
|
212
|
+
try:
|
|
213
|
+
result = api.session.rest_get(url, params=params)
|
|
214
|
+
except WebexError as e:
|
|
215
|
+
handle_rest_error(e)
|
|
216
|
+
if output == "json":
|
|
217
|
+
print_json(result)
|
|
218
|
+
else:
|
|
219
|
+
if isinstance(result, dict):
|
|
220
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
221
|
+
elif isinstance(result, list):
|
|
222
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
223
|
+
else:
|
|
224
|
+
print_json(result)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@app.command("update-virtual-lines")
|
|
229
|
+
def update_virtual_lines(
|
|
230
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
231
|
+
first_name: str = typer.Option(None, "--first-name", help="First name defined for a virtual line. Minimum length is 1."),
|
|
232
|
+
last_name: str = typer.Option(None, "--last-name", help="Last name defined for a virtual line. Minimum length is 1. M"),
|
|
233
|
+
display_name: str = typer.Option(None, "--display-name", help="Display name defined for a virtual line."),
|
|
234
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Phone number of a virtual line. Minimum length is 1. Maximum"),
|
|
235
|
+
extension: str = typer.Option(None, "--extension", help="Extension of a virtual line. Minimum length is 2. Maximum le"),
|
|
236
|
+
announcement_language: str = typer.Option(None, "--announcement-language", help="Virtual Line's announcement language."),
|
|
237
|
+
caller_id_last_name: str = typer.Option(None, "--caller-id-last-name", help="Last name used in the Calling Line ID and for dial-by-name f"),
|
|
238
|
+
caller_id_first_name: str = typer.Option(None, "--caller-id-first-name", help="First name used in the Calling Line ID and for dial-by-name"),
|
|
239
|
+
caller_id_number: str = typer.Option(None, "--caller-id-number", help="Phone number to appear as the CLID for all calls. Minimum le"),
|
|
240
|
+
time_zone: str = typer.Option(None, "--time-zone", help="Time zone defined for the virtual line."),
|
|
241
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
242
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
243
|
+
):
|
|
244
|
+
"""Update a Virtual Line."""
|
|
245
|
+
api = get_api(debug=debug)
|
|
246
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}"
|
|
247
|
+
params = {}
|
|
248
|
+
org_id = get_org_id()
|
|
249
|
+
if org_id is not None:
|
|
250
|
+
params["orgId"] = org_id
|
|
251
|
+
if json_body:
|
|
252
|
+
body = json.loads(json_body)
|
|
253
|
+
else:
|
|
254
|
+
body = {}
|
|
255
|
+
if first_name is not None:
|
|
256
|
+
body["firstName"] = first_name
|
|
257
|
+
if last_name is not None:
|
|
258
|
+
body["lastName"] = last_name
|
|
259
|
+
if display_name is not None:
|
|
260
|
+
body["displayName"] = display_name
|
|
261
|
+
if phone_number is not None:
|
|
262
|
+
body["phoneNumber"] = phone_number
|
|
263
|
+
if extension is not None:
|
|
264
|
+
body["extension"] = extension
|
|
265
|
+
if announcement_language is not None:
|
|
266
|
+
body["announcementLanguage"] = announcement_language
|
|
267
|
+
if caller_id_last_name is not None:
|
|
268
|
+
body["callerIdLastName"] = caller_id_last_name
|
|
269
|
+
if caller_id_first_name is not None:
|
|
270
|
+
body["callerIdFirstName"] = caller_id_first_name
|
|
271
|
+
if caller_id_number is not None:
|
|
272
|
+
body["callerIdNumber"] = caller_id_number
|
|
273
|
+
if time_zone is not None:
|
|
274
|
+
body["timeZone"] = time_zone
|
|
275
|
+
try:
|
|
276
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
277
|
+
except WebexError as e:
|
|
278
|
+
handle_rest_error(e)
|
|
279
|
+
typer.echo(f"Updated.")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@app.command("delete")
|
|
284
|
+
def delete(
|
|
285
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
286
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
287
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
288
|
+
):
|
|
289
|
+
"""Delete a Virtual Line."""
|
|
290
|
+
if not force:
|
|
291
|
+
typer.confirm(f"Delete {virtual_line_id}?", abort=True)
|
|
292
|
+
api = get_api(debug=debug)
|
|
293
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}"
|
|
294
|
+
params = {}
|
|
295
|
+
org_id = get_org_id()
|
|
296
|
+
if org_id is not None:
|
|
297
|
+
params["orgId"] = org_id
|
|
298
|
+
try:
|
|
299
|
+
api.session.rest_delete(url, params=params)
|
|
300
|
+
except WebexError as e:
|
|
301
|
+
handle_rest_error(e)
|
|
302
|
+
typer.echo(f"Deleted: {virtual_line_id}")
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
@app.command("show-number")
|
|
307
|
+
def show_number(
|
|
308
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
309
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
310
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
311
|
+
):
|
|
312
|
+
"""Get Phone Number assigned for a Virtual Line."""
|
|
313
|
+
api = get_api(debug=debug)
|
|
314
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/number"
|
|
315
|
+
params = {}
|
|
316
|
+
org_id = get_org_id()
|
|
317
|
+
if org_id is not None:
|
|
318
|
+
params["orgId"] = org_id
|
|
319
|
+
try:
|
|
320
|
+
result = api.session.rest_get(url, params=params)
|
|
321
|
+
except WebexError as e:
|
|
322
|
+
handle_rest_error(e)
|
|
323
|
+
if output == "json":
|
|
324
|
+
print_json(result)
|
|
325
|
+
else:
|
|
326
|
+
if isinstance(result, dict):
|
|
327
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
328
|
+
elif isinstance(result, list):
|
|
329
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
330
|
+
else:
|
|
331
|
+
print_json(result)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@app.command("update-directory-search")
|
|
336
|
+
def update_directory_search(
|
|
337
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
338
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Whether or not the directory search for a virtual line is en"),
|
|
339
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
340
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
341
|
+
):
|
|
342
|
+
"""Update Directory search for a Virtual Line."""
|
|
343
|
+
api = get_api(debug=debug)
|
|
344
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/directorySearch"
|
|
345
|
+
params = {}
|
|
346
|
+
org_id = get_org_id()
|
|
347
|
+
if org_id is not None:
|
|
348
|
+
params["orgId"] = org_id
|
|
349
|
+
if json_body:
|
|
350
|
+
body = json.loads(json_body)
|
|
351
|
+
else:
|
|
352
|
+
body = {}
|
|
353
|
+
if enabled is not None:
|
|
354
|
+
body["enabled"] = enabled
|
|
355
|
+
try:
|
|
356
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
357
|
+
except WebexError as e:
|
|
358
|
+
handle_rest_error(e)
|
|
359
|
+
typer.echo(f"Updated.")
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@app.command("list-devices")
|
|
364
|
+
def list_devices(
|
|
365
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
366
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
367
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
368
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
369
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
370
|
+
):
|
|
371
|
+
"""Get List of Devices assigned for a Virtual Line."""
|
|
372
|
+
api = get_api(debug=debug)
|
|
373
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/devices"
|
|
374
|
+
params = {}
|
|
375
|
+
if limit > 0:
|
|
376
|
+
params["max"] = limit
|
|
377
|
+
if offset > 0:
|
|
378
|
+
params["start"] = offset
|
|
379
|
+
org_id = get_org_id()
|
|
380
|
+
if org_id is not None:
|
|
381
|
+
params["orgId"] = org_id
|
|
382
|
+
result = None
|
|
383
|
+
try:
|
|
384
|
+
result = api.session.rest_get(url, params=params)
|
|
385
|
+
except WebexError as e:
|
|
386
|
+
handle_rest_error(e)
|
|
387
|
+
result = result or []
|
|
388
|
+
items = result.get("devices", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
389
|
+
if output == "json":
|
|
390
|
+
print_json(items)
|
|
391
|
+
else:
|
|
392
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
@app.command("list-dect-networks")
|
|
397
|
+
def list_dect_networks(
|
|
398
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
399
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
400
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
401
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
402
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
403
|
+
):
|
|
404
|
+
"""Get List of DECT Networks Handsets for a Virtual Line."""
|
|
405
|
+
api = get_api(debug=debug)
|
|
406
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/dectNetworks"
|
|
407
|
+
params = {}
|
|
408
|
+
if limit > 0:
|
|
409
|
+
params["max"] = limit
|
|
410
|
+
if offset > 0:
|
|
411
|
+
params["start"] = offset
|
|
412
|
+
org_id = get_org_id()
|
|
413
|
+
if org_id is not None:
|
|
414
|
+
params["orgId"] = org_id
|
|
415
|
+
result = None
|
|
416
|
+
try:
|
|
417
|
+
result = api.session.rest_get(url, params=params)
|
|
418
|
+
except WebexError as e:
|
|
419
|
+
handle_rest_error(e)
|
|
420
|
+
result = result or []
|
|
421
|
+
items = result.get("dectNetworks", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
422
|
+
if output == "json":
|
|
423
|
+
print_json(items)
|
|
424
|
+
else:
|
|
425
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
@app.command("list-caller-id")
|
|
430
|
+
def list_caller_id(
|
|
431
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
432
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
433
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
434
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
435
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
436
|
+
):
|
|
437
|
+
"""Read Caller ID Settings for a Virtual Line."""
|
|
438
|
+
api = get_api(debug=debug)
|
|
439
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callerId"
|
|
440
|
+
params = {}
|
|
441
|
+
if limit > 0:
|
|
442
|
+
params["max"] = limit
|
|
443
|
+
if offset > 0:
|
|
444
|
+
params["start"] = offset
|
|
445
|
+
org_id = get_org_id()
|
|
446
|
+
if org_id is not None:
|
|
447
|
+
params["orgId"] = org_id
|
|
448
|
+
result = None
|
|
449
|
+
try:
|
|
450
|
+
result = api.session.rest_get(url, params=params)
|
|
451
|
+
except WebexError as e:
|
|
452
|
+
handle_rest_error(e)
|
|
453
|
+
result = result or []
|
|
454
|
+
items = result.get("types", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
455
|
+
if output == "json":
|
|
456
|
+
print_json(items)
|
|
457
|
+
else:
|
|
458
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
@app.command("update-caller-id-virtual-lines")
|
|
463
|
+
def update_caller_id_virtual_lines(
|
|
464
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
465
|
+
selected: str = typer.Option(None, "--selected", help="Choices: DIRECT_LINE, LOCATION_NUMBER, CUSTOM"),
|
|
466
|
+
custom_number: str = typer.Option(None, "--custom-number", help="Custom number which will be shown if CUSTOM is selected. Thi"),
|
|
467
|
+
first_name: str = typer.Option(None, "--first-name", help="Virtual line's Caller ID first name. The characters `%`, `+"),
|
|
468
|
+
last_name: str = typer.Option(None, "--last-name", help="Virtual line's Caller ID last name. The characters `%`, `+`"),
|
|
469
|
+
block_in_forward_calls_enabled: bool = typer.Option(None, "--block-in-forward-calls-enabled/--no-block-in-forward-calls-enabled", help="Block this virtual line's identity when receiving a call."),
|
|
470
|
+
external_caller_id_name_policy: str = typer.Option(None, "--external-caller-id-name-policy", help="Choices: DIRECT_LINE, LOCATION, OTHER"),
|
|
471
|
+
custom_external_caller_id_name: str = typer.Option(None, "--custom-external-caller-id-name", help="Custom external caller ID name which will be shown if extern"),
|
|
472
|
+
additional_external_caller_id_direct_line_enabled: bool = typer.Option(None, "--additional-external-caller-id-direct-line-enabled/--no-additional-external-caller-id-direct-line-enabled", help="Set the virtual line's direct line number as additional exte"),
|
|
473
|
+
additional_external_caller_id_location_number_enabled: bool = typer.Option(None, "--additional-external-caller-id-location-number-enabled/--no-additional-external-caller-id-location-number-enabled", help="Set the Location main number as additional external caller I"),
|
|
474
|
+
additional_external_caller_id_custom_number: str = typer.Option(None, "--additional-external-caller-id-custom-number", help="To set a custom number as additional external caller ID for"),
|
|
475
|
+
dial_by_first_name: str = typer.Option(None, "--dial-by-first-name", help="Sets or clears the first name to be used for dial-by-name fu"),
|
|
476
|
+
dial_by_last_name: str = typer.Option(None, "--dial-by-last-name", help="Sets or clears the last name to be used for dial-by-name fun"),
|
|
477
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
478
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
479
|
+
):
|
|
480
|
+
"""Configure Caller ID Settings for a Virtual Line\n\nExample --json-body:\n '{"selected":"DIRECT_LINE","customNumber":"...","firstName":"...","lastName":"...","blockInForwardCallsEnabled":true,"externalCallerIdNamePolicy":"DIRECT_LINE","customExternalCallerIdName":"...","additionalExternalCallerIdDirectLineEnabled":true}'."""
|
|
481
|
+
api = get_api(debug=debug)
|
|
482
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callerId"
|
|
483
|
+
params = {}
|
|
484
|
+
org_id = get_org_id()
|
|
485
|
+
if org_id is not None:
|
|
486
|
+
params["orgId"] = org_id
|
|
487
|
+
if json_body:
|
|
488
|
+
body = json.loads(json_body)
|
|
489
|
+
else:
|
|
490
|
+
body = {}
|
|
491
|
+
if selected is not None:
|
|
492
|
+
body["selected"] = selected
|
|
493
|
+
if custom_number is not None:
|
|
494
|
+
body["customNumber"] = custom_number
|
|
495
|
+
if first_name is not None:
|
|
496
|
+
body["firstName"] = first_name
|
|
497
|
+
if last_name is not None:
|
|
498
|
+
body["lastName"] = last_name
|
|
499
|
+
if block_in_forward_calls_enabled is not None:
|
|
500
|
+
body["blockInForwardCallsEnabled"] = block_in_forward_calls_enabled
|
|
501
|
+
if external_caller_id_name_policy is not None:
|
|
502
|
+
body["externalCallerIdNamePolicy"] = external_caller_id_name_policy
|
|
503
|
+
if custom_external_caller_id_name is not None:
|
|
504
|
+
body["customExternalCallerIdName"] = custom_external_caller_id_name
|
|
505
|
+
if additional_external_caller_id_direct_line_enabled is not None:
|
|
506
|
+
body["additionalExternalCallerIdDirectLineEnabled"] = additional_external_caller_id_direct_line_enabled
|
|
507
|
+
if additional_external_caller_id_location_number_enabled is not None:
|
|
508
|
+
body["additionalExternalCallerIdLocationNumberEnabled"] = additional_external_caller_id_location_number_enabled
|
|
509
|
+
if additional_external_caller_id_custom_number is not None:
|
|
510
|
+
body["additionalExternalCallerIdCustomNumber"] = additional_external_caller_id_custom_number
|
|
511
|
+
if dial_by_first_name is not None:
|
|
512
|
+
body["dialByFirstName"] = dial_by_first_name
|
|
513
|
+
if dial_by_last_name is not None:
|
|
514
|
+
body["dialByLastName"] = dial_by_last_name
|
|
515
|
+
try:
|
|
516
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
517
|
+
except WebexError as e:
|
|
518
|
+
handle_rest_error(e)
|
|
519
|
+
typer.echo(f"Updated.")
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
@app.command("show-call-waiting")
|
|
524
|
+
def show_call_waiting(
|
|
525
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
526
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
527
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
528
|
+
):
|
|
529
|
+
"""Read Call Waiting Settings for a Virtual Line."""
|
|
530
|
+
api = get_api(debug=debug)
|
|
531
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callWaiting"
|
|
532
|
+
params = {}
|
|
533
|
+
org_id = get_org_id()
|
|
534
|
+
if org_id is not None:
|
|
535
|
+
params["orgId"] = org_id
|
|
536
|
+
try:
|
|
537
|
+
result = api.session.rest_get(url, params=params)
|
|
538
|
+
except WebexError as e:
|
|
539
|
+
handle_rest_error(e)
|
|
540
|
+
if output == "json":
|
|
541
|
+
print_json(result)
|
|
542
|
+
else:
|
|
543
|
+
if isinstance(result, dict):
|
|
544
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
545
|
+
elif isinstance(result, list):
|
|
546
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
547
|
+
else:
|
|
548
|
+
print_json(result)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
@app.command("update-call-waiting")
|
|
553
|
+
def update_call_waiting(
|
|
554
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
555
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Call Waiting feature is enabled."),
|
|
556
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
557
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
558
|
+
):
|
|
559
|
+
"""Configure Call Waiting Settings for a Virtual Line."""
|
|
560
|
+
api = get_api(debug=debug)
|
|
561
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callWaiting"
|
|
562
|
+
params = {}
|
|
563
|
+
org_id = get_org_id()
|
|
564
|
+
if org_id is not None:
|
|
565
|
+
params["orgId"] = org_id
|
|
566
|
+
if json_body:
|
|
567
|
+
body = json.loads(json_body)
|
|
568
|
+
else:
|
|
569
|
+
body = {}
|
|
570
|
+
if enabled is not None:
|
|
571
|
+
body["enabled"] = enabled
|
|
572
|
+
try:
|
|
573
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
574
|
+
except WebexError as e:
|
|
575
|
+
handle_rest_error(e)
|
|
576
|
+
typer.echo(f"Updated.")
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
@app.command("show-call-forwarding")
|
|
581
|
+
def show_call_forwarding(
|
|
582
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
583
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
584
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
585
|
+
):
|
|
586
|
+
"""Read Call Forwarding Settings for a Virtual Line."""
|
|
587
|
+
api = get_api(debug=debug)
|
|
588
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callForwarding"
|
|
589
|
+
params = {}
|
|
590
|
+
org_id = get_org_id()
|
|
591
|
+
if org_id is not None:
|
|
592
|
+
params["orgId"] = org_id
|
|
593
|
+
try:
|
|
594
|
+
result = api.session.rest_get(url, params=params)
|
|
595
|
+
except WebexError as e:
|
|
596
|
+
handle_rest_error(e)
|
|
597
|
+
if output == "json":
|
|
598
|
+
print_json(result)
|
|
599
|
+
else:
|
|
600
|
+
if isinstance(result, dict):
|
|
601
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
602
|
+
elif isinstance(result, list):
|
|
603
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
604
|
+
else:
|
|
605
|
+
print_json(result)
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
@app.command("update-call-forwarding")
|
|
610
|
+
def update_call_forwarding(
|
|
611
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
612
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
613
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
614
|
+
):
|
|
615
|
+
"""Configure Call Forwarding Settings for a Virtual Line\n\nExample --json-body:\n '{"callForwarding":{"always":{"enabled":"...","destination":"...","ringReminderEnabled":"...","destinationVoicemailEnabled":"..."},"busy":{"enabled":"...","destination":"...","destinationVoicemailEnabled":"..."},"noAnswer":{"enabled":"...","destination":"...","numberOfRings":"...","destinationVoicemailEnabled":"..."}},"businessContinuity":{"enabled":true,"destination":"...","destinationVoicemailEnabled":true}}'."""
|
|
616
|
+
api = get_api(debug=debug)
|
|
617
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callForwarding"
|
|
618
|
+
params = {}
|
|
619
|
+
org_id = get_org_id()
|
|
620
|
+
if org_id is not None:
|
|
621
|
+
params["orgId"] = org_id
|
|
622
|
+
if json_body:
|
|
623
|
+
body = json.loads(json_body)
|
|
624
|
+
else:
|
|
625
|
+
body = {}
|
|
626
|
+
try:
|
|
627
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
628
|
+
except WebexError as e:
|
|
629
|
+
handle_rest_error(e)
|
|
630
|
+
typer.echo(f"Updated.")
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
@app.command("show-incoming-permission")
|
|
635
|
+
def show_incoming_permission(
|
|
636
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
637
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
638
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
639
|
+
):
|
|
640
|
+
"""Read Incoming Permission Settings for a Virtual Line."""
|
|
641
|
+
api = get_api(debug=debug)
|
|
642
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/incomingPermission"
|
|
643
|
+
params = {}
|
|
644
|
+
org_id = get_org_id()
|
|
645
|
+
if org_id is not None:
|
|
646
|
+
params["orgId"] = org_id
|
|
647
|
+
try:
|
|
648
|
+
result = api.session.rest_get(url, params=params)
|
|
649
|
+
except WebexError as e:
|
|
650
|
+
handle_rest_error(e)
|
|
651
|
+
if output == "json":
|
|
652
|
+
print_json(result)
|
|
653
|
+
else:
|
|
654
|
+
if isinstance(result, dict):
|
|
655
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
656
|
+
elif isinstance(result, list):
|
|
657
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
658
|
+
else:
|
|
659
|
+
print_json(result)
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
@app.command("update-incoming-permission")
|
|
664
|
+
def update_incoming_permission(
|
|
665
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
666
|
+
use_custom_enabled: bool = typer.Option(None, "--use-custom-enabled/--no-use-custom-enabled", help="When true, indicates that this virtual line uses the specifi"),
|
|
667
|
+
external_transfer: str = typer.Option(None, "--external-transfer", help="Choices: ALLOW_ALL_EXTERNAL, ALLOW_ONLY_TRANSFERRED_EXTERNAL, BLOCK_ALL_EXTERNAL"),
|
|
668
|
+
internal_calls_enabled: bool = typer.Option(None, "--internal-calls-enabled/--no-internal-calls-enabled", help="Internal calls are allowed to be received."),
|
|
669
|
+
collect_calls_enabled: bool = typer.Option(None, "--collect-calls-enabled/--no-collect-calls-enabled", help="Collect calls are allowed to be received."),
|
|
670
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
671
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
672
|
+
):
|
|
673
|
+
"""Configure Incoming Permission Settings for a Virtual Line."""
|
|
674
|
+
api = get_api(debug=debug)
|
|
675
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/incomingPermission"
|
|
676
|
+
params = {}
|
|
677
|
+
org_id = get_org_id()
|
|
678
|
+
if org_id is not None:
|
|
679
|
+
params["orgId"] = org_id
|
|
680
|
+
if json_body:
|
|
681
|
+
body = json.loads(json_body)
|
|
682
|
+
else:
|
|
683
|
+
body = {}
|
|
684
|
+
if use_custom_enabled is not None:
|
|
685
|
+
body["useCustomEnabled"] = use_custom_enabled
|
|
686
|
+
if external_transfer is not None:
|
|
687
|
+
body["externalTransfer"] = external_transfer
|
|
688
|
+
if internal_calls_enabled is not None:
|
|
689
|
+
body["internalCallsEnabled"] = internal_calls_enabled
|
|
690
|
+
if collect_calls_enabled is not None:
|
|
691
|
+
body["collectCallsEnabled"] = collect_calls_enabled
|
|
692
|
+
try:
|
|
693
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
694
|
+
except WebexError as e:
|
|
695
|
+
handle_rest_error(e)
|
|
696
|
+
typer.echo(f"Updated.")
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
@app.command("list-outgoing-permission")
|
|
701
|
+
def list_outgoing_permission(
|
|
702
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
703
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
704
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
705
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
706
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
707
|
+
):
|
|
708
|
+
"""Retrieve a virtual line's Outgoing Calling Permissions Settings."""
|
|
709
|
+
api = get_api(debug=debug)
|
|
710
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission"
|
|
711
|
+
params = {}
|
|
712
|
+
if limit > 0:
|
|
713
|
+
params["max"] = limit
|
|
714
|
+
if offset > 0:
|
|
715
|
+
params["start"] = offset
|
|
716
|
+
org_id = get_org_id()
|
|
717
|
+
if org_id is not None:
|
|
718
|
+
params["orgId"] = org_id
|
|
719
|
+
result = None
|
|
720
|
+
try:
|
|
721
|
+
result = api.session.rest_get(url, params=params)
|
|
722
|
+
except WebexError as e:
|
|
723
|
+
handle_rest_error(e)
|
|
724
|
+
result = result or []
|
|
725
|
+
items = result.get("callingPermissions", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
726
|
+
if output == "json":
|
|
727
|
+
print_json(items)
|
|
728
|
+
else:
|
|
729
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
@app.command("update-outgoing-permission")
|
|
734
|
+
def update_outgoing_permission(
|
|
735
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
736
|
+
use_custom_enabled: bool = typer.Option(None, "--use-custom-enabled/--no-use-custom-enabled", help="When true, indicates that this user uses the shared control"),
|
|
737
|
+
use_custom_permissions: bool = typer.Option(None, "--use-custom-permissions/--no-use-custom-permissions", help="When true, indicates that this user uses the specified outgo"),
|
|
738
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
739
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
740
|
+
):
|
|
741
|
+
"""Modify a virtual line's Outgoing Calling Permissions Settings\n\nExample --json-body:\n '{"callingPermissions":[{"transferEnabled":"...","callType":"...","action":"..."}],"useCustomEnabled":true,"useCustomPermissions":true}'."""
|
|
742
|
+
api = get_api(debug=debug)
|
|
743
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission"
|
|
744
|
+
params = {}
|
|
745
|
+
org_id = get_org_id()
|
|
746
|
+
if org_id is not None:
|
|
747
|
+
params["orgId"] = org_id
|
|
748
|
+
if json_body:
|
|
749
|
+
body = json.loads(json_body)
|
|
750
|
+
else:
|
|
751
|
+
body = {}
|
|
752
|
+
if use_custom_enabled is not None:
|
|
753
|
+
body["useCustomEnabled"] = use_custom_enabled
|
|
754
|
+
if use_custom_permissions is not None:
|
|
755
|
+
body["useCustomPermissions"] = use_custom_permissions
|
|
756
|
+
try:
|
|
757
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
758
|
+
except WebexError as e:
|
|
759
|
+
handle_rest_error(e)
|
|
760
|
+
typer.echo(f"Updated.")
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
@app.command("list-access-codes")
|
|
765
|
+
def list_access_codes(
|
|
766
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
767
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
768
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
769
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
770
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
771
|
+
):
|
|
772
|
+
"""Retrieve Access Codes for a Virtual Line."""
|
|
773
|
+
api = get_api(debug=debug)
|
|
774
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/accessCodes"
|
|
775
|
+
params = {}
|
|
776
|
+
if limit > 0:
|
|
777
|
+
params["max"] = limit
|
|
778
|
+
if offset > 0:
|
|
779
|
+
params["start"] = offset
|
|
780
|
+
org_id = get_org_id()
|
|
781
|
+
if org_id is not None:
|
|
782
|
+
params["orgId"] = org_id
|
|
783
|
+
result = None
|
|
784
|
+
try:
|
|
785
|
+
result = api.session.rest_get(url, params=params)
|
|
786
|
+
except WebexError as e:
|
|
787
|
+
handle_rest_error(e)
|
|
788
|
+
result = result or []
|
|
789
|
+
items = result.get("accessCodes", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
790
|
+
if output == "json":
|
|
791
|
+
print_json(items)
|
|
792
|
+
else:
|
|
793
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
@app.command("create-access-codes")
|
|
798
|
+
def create_access_codes(
|
|
799
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
800
|
+
code: str = typer.Option(None, "--code", help="(required) An Access code."),
|
|
801
|
+
description: str = typer.Option(None, "--description", help="(required) The description of the access code."),
|
|
802
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
803
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
804
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
805
|
+
):
|
|
806
|
+
"""Create Access Codes for a Virtual Line."""
|
|
807
|
+
api = get_api(debug=debug)
|
|
808
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/accessCodes"
|
|
809
|
+
params = {}
|
|
810
|
+
org_id = get_org_id()
|
|
811
|
+
if org_id is not None:
|
|
812
|
+
params["orgId"] = org_id
|
|
813
|
+
if json_body:
|
|
814
|
+
body = json.loads(json_body)
|
|
815
|
+
else:
|
|
816
|
+
body = {}
|
|
817
|
+
if code is not None:
|
|
818
|
+
body["code"] = code
|
|
819
|
+
if description is not None:
|
|
820
|
+
body["description"] = description
|
|
821
|
+
_missing = [f for f in ['code', 'description'] if f not in body or body[f] is None]
|
|
822
|
+
if _missing:
|
|
823
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
824
|
+
raise typer.Exit(1)
|
|
825
|
+
try:
|
|
826
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
827
|
+
except WebexError as e:
|
|
828
|
+
handle_rest_error(e)
|
|
829
|
+
if output == "json":
|
|
830
|
+
print_json(result)
|
|
831
|
+
elif isinstance(result, dict) and "id" in result:
|
|
832
|
+
typer.echo(f"Created: {result['id']}")
|
|
833
|
+
elif not result or result == {}:
|
|
834
|
+
typer.echo("Created.")
|
|
835
|
+
else:
|
|
836
|
+
print_json(result)
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
@app.command("update-access-codes")
|
|
841
|
+
def update_access_codes(
|
|
842
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
843
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
844
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
845
|
+
):
|
|
846
|
+
"""Modify Access Codes for a Virtual Line\n\nExample --json-body:\n '{"deleteCodes":["..."]}'."""
|
|
847
|
+
api = get_api(debug=debug)
|
|
848
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/accessCodes"
|
|
849
|
+
params = {}
|
|
850
|
+
org_id = get_org_id()
|
|
851
|
+
if org_id is not None:
|
|
852
|
+
params["orgId"] = org_id
|
|
853
|
+
if json_body:
|
|
854
|
+
body = json.loads(json_body)
|
|
855
|
+
else:
|
|
856
|
+
body = {}
|
|
857
|
+
try:
|
|
858
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
859
|
+
except WebexError as e:
|
|
860
|
+
handle_rest_error(e)
|
|
861
|
+
typer.echo(f"Updated.")
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
@app.command("delete-access-codes")
|
|
866
|
+
def delete_access_codes(
|
|
867
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
868
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
869
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
870
|
+
):
|
|
871
|
+
"""Delete Access Codes for a Virtual Line."""
|
|
872
|
+
if not force:
|
|
873
|
+
typer.confirm(f"Delete {virtual_line_id}?", abort=True)
|
|
874
|
+
api = get_api(debug=debug)
|
|
875
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/accessCodes"
|
|
876
|
+
params = {}
|
|
877
|
+
org_id = get_org_id()
|
|
878
|
+
if org_id is not None:
|
|
879
|
+
params["orgId"] = org_id
|
|
880
|
+
try:
|
|
881
|
+
api.session.rest_delete(url, params=params)
|
|
882
|
+
except WebexError as e:
|
|
883
|
+
handle_rest_error(e)
|
|
884
|
+
typer.echo(f"Deleted: {virtual_line_id}")
|
|
885
|
+
|
|
886
|
+
|
|
887
|
+
|
|
888
|
+
@app.command("show-auto-transfer-numbers")
|
|
889
|
+
def show_auto_transfer_numbers(
|
|
890
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
891
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
892
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
893
|
+
):
|
|
894
|
+
"""Retrieve Transfer Numbers for a Virtual Line."""
|
|
895
|
+
api = get_api(debug=debug)
|
|
896
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/autoTransferNumbers"
|
|
897
|
+
params = {}
|
|
898
|
+
org_id = get_org_id()
|
|
899
|
+
if org_id is not None:
|
|
900
|
+
params["orgId"] = org_id
|
|
901
|
+
try:
|
|
902
|
+
result = api.session.rest_get(url, params=params)
|
|
903
|
+
except WebexError as e:
|
|
904
|
+
handle_rest_error(e)
|
|
905
|
+
if output == "json":
|
|
906
|
+
print_json(result)
|
|
907
|
+
else:
|
|
908
|
+
if isinstance(result, dict):
|
|
909
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
910
|
+
elif isinstance(result, list):
|
|
911
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
912
|
+
else:
|
|
913
|
+
print_json(result)
|
|
914
|
+
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
@app.command("update-auto-transfer-numbers")
|
|
918
|
+
def update_auto_transfer_numbers(
|
|
919
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
920
|
+
use_custom_transfer_numbers: bool = typer.Option(None, "--use-custom-transfer-numbers/--no-use-custom-transfer-numbers", help="When `true`, use custom settings for the transfer numbers ca"),
|
|
921
|
+
auto_transfer_number1: str = typer.Option(None, "--auto-transfer-number1", help="When calling a specific call type, this workspace will be au"),
|
|
922
|
+
auto_transfer_number2: str = typer.Option(None, "--auto-transfer-number2", help="When calling a specific call type, this workspace will be au"),
|
|
923
|
+
auto_transfer_number3: str = typer.Option(None, "--auto-transfer-number3", help="When calling a specific call type, this workspace will be au"),
|
|
924
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
925
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
926
|
+
):
|
|
927
|
+
"""Modify Transfer Numbers for a Virtual Line."""
|
|
928
|
+
api = get_api(debug=debug)
|
|
929
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/autoTransferNumbers"
|
|
930
|
+
params = {}
|
|
931
|
+
org_id = get_org_id()
|
|
932
|
+
if org_id is not None:
|
|
933
|
+
params["orgId"] = org_id
|
|
934
|
+
if json_body:
|
|
935
|
+
body = json.loads(json_body)
|
|
936
|
+
else:
|
|
937
|
+
body = {}
|
|
938
|
+
if use_custom_transfer_numbers is not None:
|
|
939
|
+
body["useCustomTransferNumbers"] = use_custom_transfer_numbers
|
|
940
|
+
if auto_transfer_number1 is not None:
|
|
941
|
+
body["autoTransferNumber1"] = auto_transfer_number1
|
|
942
|
+
if auto_transfer_number2 is not None:
|
|
943
|
+
body["autoTransferNumber2"] = auto_transfer_number2
|
|
944
|
+
if auto_transfer_number3 is not None:
|
|
945
|
+
body["autoTransferNumber3"] = auto_transfer_number3
|
|
946
|
+
try:
|
|
947
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
948
|
+
except WebexError as e:
|
|
949
|
+
handle_rest_error(e)
|
|
950
|
+
typer.echo(f"Updated.")
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
@app.command("list-digit-patterns")
|
|
955
|
+
def list_digit_patterns(
|
|
956
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
957
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
958
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
959
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
960
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
961
|
+
):
|
|
962
|
+
"""Retrieve Digit Patterns for a Virtual Profile."""
|
|
963
|
+
api = get_api(debug=debug)
|
|
964
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns"
|
|
965
|
+
params = {}
|
|
966
|
+
if limit > 0:
|
|
967
|
+
params["max"] = limit
|
|
968
|
+
if offset > 0:
|
|
969
|
+
params["start"] = offset
|
|
970
|
+
org_id = get_org_id()
|
|
971
|
+
if org_id is not None:
|
|
972
|
+
params["orgId"] = org_id
|
|
973
|
+
result = None
|
|
974
|
+
try:
|
|
975
|
+
result = api.session.rest_get(url, params=params)
|
|
976
|
+
except WebexError as e:
|
|
977
|
+
handle_rest_error(e)
|
|
978
|
+
result = result or []
|
|
979
|
+
items = result.get("digitPatterns", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
980
|
+
if output == "json":
|
|
981
|
+
print_json(items)
|
|
982
|
+
else:
|
|
983
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
@app.command("create-digit-patterns")
|
|
988
|
+
def create_digit_patterns(
|
|
989
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
990
|
+
name: str = typer.Option(None, "--name", help="(required) A unique name for the digit pattern."),
|
|
991
|
+
pattern: str = typer.Option(None, "--pattern", help="(required) The digit pattern to be matched with the input number."),
|
|
992
|
+
action: str = typer.Option(None, "--action", help="(required) Choices: ALLOW, BLOCK, AUTH_CODE, TRANSFER_NUMBER_1, TRANSFER_NUMBER_2, TRANSFER_NUMBER_3"),
|
|
993
|
+
transfer_enabled: bool = typer.Option(None, "--transfer-enabled/--no-transfer-enabled", help="(required) If `true`, allows transfer and forwarding for the call type."),
|
|
994
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
995
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
996
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
997
|
+
):
|
|
998
|
+
"""Create Digit Pattern for a Virtual Profile."""
|
|
999
|
+
api = get_api(debug=debug)
|
|
1000
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns"
|
|
1001
|
+
params = {}
|
|
1002
|
+
org_id = get_org_id()
|
|
1003
|
+
if org_id is not None:
|
|
1004
|
+
params["orgId"] = org_id
|
|
1005
|
+
if json_body:
|
|
1006
|
+
body = json.loads(json_body)
|
|
1007
|
+
else:
|
|
1008
|
+
body = {}
|
|
1009
|
+
if name is not None:
|
|
1010
|
+
body["name"] = name
|
|
1011
|
+
if pattern is not None:
|
|
1012
|
+
body["pattern"] = pattern
|
|
1013
|
+
if action is not None:
|
|
1014
|
+
body["action"] = action
|
|
1015
|
+
if transfer_enabled is not None:
|
|
1016
|
+
body["transferEnabled"] = transfer_enabled
|
|
1017
|
+
_missing = [f for f in ['name', 'pattern', 'action', 'transferEnabled'] if f not in body or body[f] is None]
|
|
1018
|
+
if _missing:
|
|
1019
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1020
|
+
raise typer.Exit(1)
|
|
1021
|
+
try:
|
|
1022
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1023
|
+
except WebexError as e:
|
|
1024
|
+
handle_rest_error(e)
|
|
1025
|
+
if output == "json":
|
|
1026
|
+
print_json(result)
|
|
1027
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1028
|
+
typer.echo(f"Created: {result['id']}")
|
|
1029
|
+
elif not result or result == {}:
|
|
1030
|
+
typer.echo("Created.")
|
|
1031
|
+
else:
|
|
1032
|
+
print_json(result)
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
@app.command("update-digit-patterns-outgoing-permission")
|
|
1037
|
+
def update_digit_patterns_outgoing_permission(
|
|
1038
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1039
|
+
use_custom_digit_patterns: bool = typer.Option(None, "--use-custom-digit-patterns/--no-use-custom-digit-patterns", help="When `true`, use custom settings for the digit patterns cate"),
|
|
1040
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1041
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1042
|
+
):
|
|
1043
|
+
"""Modify the Digit Pattern Category Control Settings for a Virtual Profile."""
|
|
1044
|
+
api = get_api(debug=debug)
|
|
1045
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns"
|
|
1046
|
+
params = {}
|
|
1047
|
+
org_id = get_org_id()
|
|
1048
|
+
if org_id is not None:
|
|
1049
|
+
params["orgId"] = org_id
|
|
1050
|
+
if json_body:
|
|
1051
|
+
body = json.loads(json_body)
|
|
1052
|
+
else:
|
|
1053
|
+
body = {}
|
|
1054
|
+
if use_custom_digit_patterns is not None:
|
|
1055
|
+
body["useCustomDigitPatterns"] = use_custom_digit_patterns
|
|
1056
|
+
try:
|
|
1057
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1058
|
+
except WebexError as e:
|
|
1059
|
+
handle_rest_error(e)
|
|
1060
|
+
typer.echo(f"Updated.")
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
@app.command("delete-digit-patterns-outgoing-permission")
|
|
1065
|
+
def delete_digit_patterns_outgoing_permission(
|
|
1066
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1067
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1068
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1069
|
+
):
|
|
1070
|
+
"""Delete all Digit Patterns for a Virtual Profile."""
|
|
1071
|
+
if not force:
|
|
1072
|
+
typer.confirm(f"Delete {virtual_line_id}?", abort=True)
|
|
1073
|
+
api = get_api(debug=debug)
|
|
1074
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns"
|
|
1075
|
+
params = {}
|
|
1076
|
+
org_id = get_org_id()
|
|
1077
|
+
if org_id is not None:
|
|
1078
|
+
params["orgId"] = org_id
|
|
1079
|
+
try:
|
|
1080
|
+
api.session.rest_delete(url, params=params)
|
|
1081
|
+
except WebexError as e:
|
|
1082
|
+
handle_rest_error(e)
|
|
1083
|
+
typer.echo(f"Deleted: {virtual_line_id}")
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
@app.command("show-digit-patterns")
|
|
1088
|
+
def show_digit_patterns(
|
|
1089
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1090
|
+
digit_pattern_id: str = typer.Argument(help="digitPatternId"),
|
|
1091
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1092
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1093
|
+
):
|
|
1094
|
+
"""Retrieve Specified Digit Pattern Details for a Virtual Profile."""
|
|
1095
|
+
api = get_api(debug=debug)
|
|
1096
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns/{digit_pattern_id}"
|
|
1097
|
+
params = {}
|
|
1098
|
+
org_id = get_org_id()
|
|
1099
|
+
if org_id is not None:
|
|
1100
|
+
params["orgId"] = org_id
|
|
1101
|
+
try:
|
|
1102
|
+
result = api.session.rest_get(url, params=params)
|
|
1103
|
+
except WebexError as e:
|
|
1104
|
+
handle_rest_error(e)
|
|
1105
|
+
if output == "json":
|
|
1106
|
+
print_json(result)
|
|
1107
|
+
else:
|
|
1108
|
+
if isinstance(result, dict):
|
|
1109
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1110
|
+
elif isinstance(result, list):
|
|
1111
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1112
|
+
else:
|
|
1113
|
+
print_json(result)
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
|
|
1117
|
+
@app.command("update-digit-patterns-outgoing-permission-1")
|
|
1118
|
+
def update_digit_patterns_outgoing_permission_1(
|
|
1119
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1120
|
+
digit_pattern_id: str = typer.Argument(help="digitPatternId"),
|
|
1121
|
+
name: str = typer.Option(None, "--name", help="A unique name for the digit pattern."),
|
|
1122
|
+
pattern: str = typer.Option(None, "--pattern", help="The digit pattern to be matched with the input number."),
|
|
1123
|
+
action: str = typer.Option(None, "--action", help="Choices: ALLOW, BLOCK, AUTH_CODE, TRANSFER_NUMBER_1, TRANSFER_NUMBER_2, TRANSFER_NUMBER_3"),
|
|
1124
|
+
transfer_enabled: bool = typer.Option(None, "--transfer-enabled/--no-transfer-enabled", help="If `true`, allows transfer and forwarding for the call type."),
|
|
1125
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1126
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1127
|
+
):
|
|
1128
|
+
"""Modify a Digit Pattern for a Virtual Profile."""
|
|
1129
|
+
api = get_api(debug=debug)
|
|
1130
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns/{digit_pattern_id}"
|
|
1131
|
+
params = {}
|
|
1132
|
+
org_id = get_org_id()
|
|
1133
|
+
if org_id is not None:
|
|
1134
|
+
params["orgId"] = org_id
|
|
1135
|
+
if json_body:
|
|
1136
|
+
body = json.loads(json_body)
|
|
1137
|
+
else:
|
|
1138
|
+
body = {}
|
|
1139
|
+
if name is not None:
|
|
1140
|
+
body["name"] = name
|
|
1141
|
+
if pattern is not None:
|
|
1142
|
+
body["pattern"] = pattern
|
|
1143
|
+
if action is not None:
|
|
1144
|
+
body["action"] = action
|
|
1145
|
+
if transfer_enabled is not None:
|
|
1146
|
+
body["transferEnabled"] = transfer_enabled
|
|
1147
|
+
try:
|
|
1148
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1149
|
+
except WebexError as e:
|
|
1150
|
+
handle_rest_error(e)
|
|
1151
|
+
typer.echo(f"Updated.")
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
|
|
1155
|
+
@app.command("delete-digit-patterns-outgoing-permission-1")
|
|
1156
|
+
def delete_digit_patterns_outgoing_permission_1(
|
|
1157
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1158
|
+
digit_pattern_id: str = typer.Argument(help="digitPatternId"),
|
|
1159
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1160
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1161
|
+
):
|
|
1162
|
+
"""Delete a Digit Pattern for a Virtual Profile."""
|
|
1163
|
+
if not force:
|
|
1164
|
+
typer.confirm(f"Delete {digit_pattern_id}?", abort=True)
|
|
1165
|
+
api = get_api(debug=debug)
|
|
1166
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/outgoingPermission/digitPatterns/{digit_pattern_id}"
|
|
1167
|
+
params = {}
|
|
1168
|
+
org_id = get_org_id()
|
|
1169
|
+
if org_id is not None:
|
|
1170
|
+
params["orgId"] = org_id
|
|
1171
|
+
try:
|
|
1172
|
+
api.session.rest_delete(url, params=params)
|
|
1173
|
+
except WebexError as e:
|
|
1174
|
+
handle_rest_error(e)
|
|
1175
|
+
typer.echo(f"Deleted: {digit_pattern_id}")
|
|
1176
|
+
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
@app.command("show-intercept")
|
|
1180
|
+
def show_intercept(
|
|
1181
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1182
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1183
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1184
|
+
):
|
|
1185
|
+
"""Read Call Intercept Settings for a Virtual Line."""
|
|
1186
|
+
api = get_api(debug=debug)
|
|
1187
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/intercept"
|
|
1188
|
+
params = {}
|
|
1189
|
+
org_id = get_org_id()
|
|
1190
|
+
if org_id is not None:
|
|
1191
|
+
params["orgId"] = org_id
|
|
1192
|
+
try:
|
|
1193
|
+
result = api.session.rest_get(url, params=params)
|
|
1194
|
+
except WebexError as e:
|
|
1195
|
+
handle_rest_error(e)
|
|
1196
|
+
if output == "json":
|
|
1197
|
+
print_json(result)
|
|
1198
|
+
else:
|
|
1199
|
+
if isinstance(result, dict):
|
|
1200
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1201
|
+
elif isinstance(result, list):
|
|
1202
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1203
|
+
else:
|
|
1204
|
+
print_json(result)
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
|
|
1208
|
+
@app.command("update-intercept")
|
|
1209
|
+
def update_intercept(
|
|
1210
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1211
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the intercept feature is enabled."),
|
|
1212
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1213
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1214
|
+
):
|
|
1215
|
+
"""Configure Call Intercept Settings for a Virtual Line\n\nExample --json-body:\n '{"enabled":true,"incoming":{"type":"INTERCEPT_ALL","voicemailEnabled":true,"announcements":{"greeting":"...","newNumber":"...","zeroTransfer":"..."}},"outgoing":{"type":"INTERCEPT_ALL","transferEnabled":true,"destination":"..."}}'."""
|
|
1216
|
+
api = get_api(debug=debug)
|
|
1217
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/intercept"
|
|
1218
|
+
params = {}
|
|
1219
|
+
org_id = get_org_id()
|
|
1220
|
+
if org_id is not None:
|
|
1221
|
+
params["orgId"] = org_id
|
|
1222
|
+
if json_body:
|
|
1223
|
+
body = json.loads(json_body)
|
|
1224
|
+
else:
|
|
1225
|
+
body = {}
|
|
1226
|
+
if enabled is not None:
|
|
1227
|
+
body["enabled"] = enabled
|
|
1228
|
+
try:
|
|
1229
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1230
|
+
except WebexError as e:
|
|
1231
|
+
handle_rest_error(e)
|
|
1232
|
+
typer.echo(f"Updated.")
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
@app.command("configure-call-intercept")
|
|
1237
|
+
def configure_call_intercept(
|
|
1238
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1239
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1240
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1241
|
+
):
|
|
1242
|
+
"""Configure Call Intercept Greeting for a Virtual Line."""
|
|
1243
|
+
api = get_api(debug=debug)
|
|
1244
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/intercept/actions/announcementUpload/invoke"
|
|
1245
|
+
params = {}
|
|
1246
|
+
org_id = get_org_id()
|
|
1247
|
+
if org_id is not None:
|
|
1248
|
+
params["orgId"] = org_id
|
|
1249
|
+
if json_body:
|
|
1250
|
+
body = json.loads(json_body)
|
|
1251
|
+
else:
|
|
1252
|
+
body = {}
|
|
1253
|
+
try:
|
|
1254
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1255
|
+
except WebexError as e:
|
|
1256
|
+
handle_rest_error(e)
|
|
1257
|
+
print_json(result)
|
|
1258
|
+
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
@app.command("list-available-caller-ids")
|
|
1262
|
+
def list_available_caller_ids(
|
|
1263
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1264
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1265
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1266
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1267
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1268
|
+
):
|
|
1269
|
+
"""Retrieve Agent's List of Available Caller IDs."""
|
|
1270
|
+
api = get_api(debug=debug)
|
|
1271
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/agent/availableCallerIds"
|
|
1272
|
+
params = {}
|
|
1273
|
+
if limit > 0:
|
|
1274
|
+
params["max"] = limit
|
|
1275
|
+
if offset > 0:
|
|
1276
|
+
params["start"] = offset
|
|
1277
|
+
org_id = get_org_id()
|
|
1278
|
+
if org_id is not None:
|
|
1279
|
+
params["orgId"] = org_id
|
|
1280
|
+
result = None
|
|
1281
|
+
try:
|
|
1282
|
+
result = api.session.rest_get(url, params=params)
|
|
1283
|
+
except WebexError as e:
|
|
1284
|
+
handle_rest_error(e)
|
|
1285
|
+
result = result or []
|
|
1286
|
+
items = result.get("availableCallerIds", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1287
|
+
if output == "json":
|
|
1288
|
+
print_json(items)
|
|
1289
|
+
else:
|
|
1290
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
@app.command("show-caller-id")
|
|
1295
|
+
def show_caller_id(
|
|
1296
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1297
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1298
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1299
|
+
):
|
|
1300
|
+
"""Retrieve Agent's Caller ID Information."""
|
|
1301
|
+
api = get_api(debug=debug)
|
|
1302
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/agent/callerId"
|
|
1303
|
+
try:
|
|
1304
|
+
result = api.session.rest_get(url)
|
|
1305
|
+
except WebexError as e:
|
|
1306
|
+
handle_rest_error(e)
|
|
1307
|
+
if output == "json":
|
|
1308
|
+
print_json(result)
|
|
1309
|
+
else:
|
|
1310
|
+
if isinstance(result, dict):
|
|
1311
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1312
|
+
elif isinstance(result, list):
|
|
1313
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1314
|
+
else:
|
|
1315
|
+
print_json(result)
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
|
|
1319
|
+
@app.command("update-caller-id-agent")
|
|
1320
|
+
def update_caller_id_agent(
|
|
1321
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1322
|
+
selected_caller_id: str = typer.Option(None, "--selected-caller-id", help="The unique identifier of the call queue or hunt group to use"),
|
|
1323
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1324
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1325
|
+
):
|
|
1326
|
+
"""Modify Agent's Caller ID Information."""
|
|
1327
|
+
api = get_api(debug=debug)
|
|
1328
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/agent/callerId"
|
|
1329
|
+
if json_body:
|
|
1330
|
+
body = json.loads(json_body)
|
|
1331
|
+
else:
|
|
1332
|
+
body = {}
|
|
1333
|
+
if selected_caller_id is not None:
|
|
1334
|
+
body["selectedCallerId"] = selected_caller_id
|
|
1335
|
+
try:
|
|
1336
|
+
result = api.session.rest_put(url, json=body)
|
|
1337
|
+
except WebexError as e:
|
|
1338
|
+
handle_rest_error(e)
|
|
1339
|
+
typer.echo(f"Updated.")
|
|
1340
|
+
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
@app.command("show-voicemail")
|
|
1344
|
+
def show_voicemail(
|
|
1345
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1346
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1347
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1348
|
+
):
|
|
1349
|
+
"""Read Voicemail Settings for a Virtual Line."""
|
|
1350
|
+
api = get_api(debug=debug)
|
|
1351
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/voicemail"
|
|
1352
|
+
params = {}
|
|
1353
|
+
org_id = get_org_id()
|
|
1354
|
+
if org_id is not None:
|
|
1355
|
+
params["orgId"] = org_id
|
|
1356
|
+
try:
|
|
1357
|
+
result = api.session.rest_get(url, params=params)
|
|
1358
|
+
except WebexError as e:
|
|
1359
|
+
handle_rest_error(e)
|
|
1360
|
+
if output == "json":
|
|
1361
|
+
print_json(result)
|
|
1362
|
+
else:
|
|
1363
|
+
if isinstance(result, dict):
|
|
1364
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1365
|
+
elif isinstance(result, list):
|
|
1366
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1367
|
+
else:
|
|
1368
|
+
print_json(result)
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
|
|
1372
|
+
@app.command("update-voicemail")
|
|
1373
|
+
def update_voicemail(
|
|
1374
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1375
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Voicemail is enabled or disabled."),
|
|
1376
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1377
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1378
|
+
):
|
|
1379
|
+
"""Configure Voicemail Settings for a Virtual Line\n\nExample --json-body:\n '{"notifications":{"enabled":true,"destination":"...","smsDestination":"..."},"transferToNumber":{"enabled":true,"destination":"..."},"enabled":true,"sendAllCalls":{"enabled":true},"sendBusyCalls":{"enabled":true,"greeting":"DEFAULT"},"sendUnansweredCalls":{"enabled":true,"greeting":"DEFAULT","numberOfRings":0},"emailCopyOfMessage":{"enabled":true,"emailId":"..."},"messageStorage":{"mwiEnabled":true,"storageType":"INTERNAL","externalEmail":"..."}}'."""
|
|
1380
|
+
api = get_api(debug=debug)
|
|
1381
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/voicemail"
|
|
1382
|
+
params = {}
|
|
1383
|
+
org_id = get_org_id()
|
|
1384
|
+
if org_id is not None:
|
|
1385
|
+
params["orgId"] = org_id
|
|
1386
|
+
if json_body:
|
|
1387
|
+
body = json.loads(json_body)
|
|
1388
|
+
else:
|
|
1389
|
+
body = {}
|
|
1390
|
+
if enabled is not None:
|
|
1391
|
+
body["enabled"] = enabled
|
|
1392
|
+
try:
|
|
1393
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1394
|
+
except WebexError as e:
|
|
1395
|
+
handle_rest_error(e)
|
|
1396
|
+
typer.echo(f"Updated.")
|
|
1397
|
+
|
|
1398
|
+
|
|
1399
|
+
|
|
1400
|
+
@app.command("configure-busy-voicemail")
|
|
1401
|
+
def configure_busy_voicemail(
|
|
1402
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1403
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1404
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1405
|
+
):
|
|
1406
|
+
"""Configure Busy Voicemail Greeting for a Virtual Line."""
|
|
1407
|
+
api = get_api(debug=debug)
|
|
1408
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/voicemail/actions/uploadBusyGreeting/invoke"
|
|
1409
|
+
params = {}
|
|
1410
|
+
org_id = get_org_id()
|
|
1411
|
+
if org_id is not None:
|
|
1412
|
+
params["orgId"] = org_id
|
|
1413
|
+
if json_body:
|
|
1414
|
+
body = json.loads(json_body)
|
|
1415
|
+
else:
|
|
1416
|
+
body = {}
|
|
1417
|
+
try:
|
|
1418
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1419
|
+
except WebexError as e:
|
|
1420
|
+
handle_rest_error(e)
|
|
1421
|
+
print_json(result)
|
|
1422
|
+
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
@app.command("configure-no-answer")
|
|
1426
|
+
def configure_no_answer(
|
|
1427
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1428
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1429
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1430
|
+
):
|
|
1431
|
+
"""Configure No Answer Voicemail Greeting for a Virtual Line."""
|
|
1432
|
+
api = get_api(debug=debug)
|
|
1433
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/voicemail/actions/uploadNoAnswerGreeting/invoke"
|
|
1434
|
+
params = {}
|
|
1435
|
+
org_id = get_org_id()
|
|
1436
|
+
if org_id is not None:
|
|
1437
|
+
params["orgId"] = org_id
|
|
1438
|
+
if json_body:
|
|
1439
|
+
body = json.loads(json_body)
|
|
1440
|
+
else:
|
|
1441
|
+
body = {}
|
|
1442
|
+
try:
|
|
1443
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1444
|
+
except WebexError as e:
|
|
1445
|
+
handle_rest_error(e)
|
|
1446
|
+
print_json(result)
|
|
1447
|
+
|
|
1448
|
+
|
|
1449
|
+
|
|
1450
|
+
@app.command("reset-voicemail-pin")
|
|
1451
|
+
def reset_voicemail_pin(
|
|
1452
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1453
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1454
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1455
|
+
):
|
|
1456
|
+
"""Reset Voicemail PIN for a Virtual Line."""
|
|
1457
|
+
api = get_api(debug=debug)
|
|
1458
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/voicemail/actions/resetPin/invoke"
|
|
1459
|
+
params = {}
|
|
1460
|
+
org_id = get_org_id()
|
|
1461
|
+
if org_id is not None:
|
|
1462
|
+
params["orgId"] = org_id
|
|
1463
|
+
if json_body:
|
|
1464
|
+
body = json.loads(json_body)
|
|
1465
|
+
else:
|
|
1466
|
+
body = {}
|
|
1467
|
+
try:
|
|
1468
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1469
|
+
except WebexError as e:
|
|
1470
|
+
handle_rest_error(e)
|
|
1471
|
+
print_json(result)
|
|
1472
|
+
|
|
1473
|
+
|
|
1474
|
+
|
|
1475
|
+
@app.command("update-passcode")
|
|
1476
|
+
def update_passcode(
|
|
1477
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1478
|
+
passcode: str = typer.Option(None, "--passcode", help="Voicemail access passcode. The minimum length of the passcod"),
|
|
1479
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1480
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1481
|
+
):
|
|
1482
|
+
"""Modify a virtual line's voicemail passcode."""
|
|
1483
|
+
api = get_api(debug=debug)
|
|
1484
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/voicemail/passcode"
|
|
1485
|
+
params = {}
|
|
1486
|
+
org_id = get_org_id()
|
|
1487
|
+
if org_id is not None:
|
|
1488
|
+
params["orgId"] = org_id
|
|
1489
|
+
if json_body:
|
|
1490
|
+
body = json.loads(json_body)
|
|
1491
|
+
else:
|
|
1492
|
+
body = {}
|
|
1493
|
+
if passcode is not None:
|
|
1494
|
+
body["passcode"] = passcode
|
|
1495
|
+
try:
|
|
1496
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1497
|
+
except WebexError as e:
|
|
1498
|
+
handle_rest_error(e)
|
|
1499
|
+
typer.echo(f"Updated.")
|
|
1500
|
+
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
@app.command("show-music-on-hold")
|
|
1504
|
+
def show_music_on_hold(
|
|
1505
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1506
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1507
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1508
|
+
):
|
|
1509
|
+
"""Retrieve Music On Hold Settings for a Virtual Line."""
|
|
1510
|
+
api = get_api(debug=debug)
|
|
1511
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/musicOnHold"
|
|
1512
|
+
params = {}
|
|
1513
|
+
org_id = get_org_id()
|
|
1514
|
+
if org_id is not None:
|
|
1515
|
+
params["orgId"] = org_id
|
|
1516
|
+
try:
|
|
1517
|
+
result = api.session.rest_get(url, params=params)
|
|
1518
|
+
except WebexError as e:
|
|
1519
|
+
handle_rest_error(e)
|
|
1520
|
+
if output == "json":
|
|
1521
|
+
print_json(result)
|
|
1522
|
+
else:
|
|
1523
|
+
if isinstance(result, dict):
|
|
1524
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1525
|
+
elif isinstance(result, list):
|
|
1526
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1527
|
+
else:
|
|
1528
|
+
print_json(result)
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
@app.command("update-music-on-hold")
|
|
1533
|
+
def update_music_on_hold(
|
|
1534
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1535
|
+
moh_enabled: bool = typer.Option(None, "--moh-enabled/--no-moh-enabled", help="Music on hold is enabled or disabled for the workspace."),
|
|
1536
|
+
greeting: str = typer.Option(None, "--greeting", help="Choices: DEFAULT, CUSTOM"),
|
|
1537
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1538
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1539
|
+
):
|
|
1540
|
+
"""Configure Music On Hold Settings for a Virtual Line\n\nExample --json-body:\n '{"mohEnabled":true,"greeting":"DEFAULT","audioAnnouncementFile":{"id":"...","fileName":"...","mediaFileType":"WAV","level":"ORGANIZATION"}}'."""
|
|
1541
|
+
api = get_api(debug=debug)
|
|
1542
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/musicOnHold"
|
|
1543
|
+
params = {}
|
|
1544
|
+
org_id = get_org_id()
|
|
1545
|
+
if org_id is not None:
|
|
1546
|
+
params["orgId"] = org_id
|
|
1547
|
+
if json_body:
|
|
1548
|
+
body = json.loads(json_body)
|
|
1549
|
+
else:
|
|
1550
|
+
body = {}
|
|
1551
|
+
if moh_enabled is not None:
|
|
1552
|
+
body["mohEnabled"] = moh_enabled
|
|
1553
|
+
if greeting is not None:
|
|
1554
|
+
body["greeting"] = greeting
|
|
1555
|
+
try:
|
|
1556
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1557
|
+
except WebexError as e:
|
|
1558
|
+
handle_rest_error(e)
|
|
1559
|
+
typer.echo(f"Updated.")
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
|
|
1563
|
+
@app.command("list-push-to-talk")
|
|
1564
|
+
def list_push_to_talk(
|
|
1565
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1566
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1567
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1568
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1569
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1570
|
+
):
|
|
1571
|
+
"""Read Push-to-Talk Settings for a Virtual Line."""
|
|
1572
|
+
api = get_api(debug=debug)
|
|
1573
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/pushToTalk"
|
|
1574
|
+
params = {}
|
|
1575
|
+
if limit > 0:
|
|
1576
|
+
params["max"] = limit
|
|
1577
|
+
if offset > 0:
|
|
1578
|
+
params["start"] = offset
|
|
1579
|
+
org_id = get_org_id()
|
|
1580
|
+
if org_id is not None:
|
|
1581
|
+
params["orgId"] = org_id
|
|
1582
|
+
result = None
|
|
1583
|
+
try:
|
|
1584
|
+
result = api.session.rest_get(url, params=params)
|
|
1585
|
+
except WebexError as e:
|
|
1586
|
+
handle_rest_error(e)
|
|
1587
|
+
result = result or []
|
|
1588
|
+
items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1589
|
+
if output == "json":
|
|
1590
|
+
print_json(items)
|
|
1591
|
+
else:
|
|
1592
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1593
|
+
|
|
1594
|
+
|
|
1595
|
+
|
|
1596
|
+
@app.command("update-push-to-talk")
|
|
1597
|
+
def update_push_to_talk(
|
|
1598
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1599
|
+
allow_auto_answer: bool = typer.Option(None, "--allow-auto-answer/--no-allow-auto-answer", help="`true` if Push-to-Talk feature is enabled."),
|
|
1600
|
+
connection_type: str = typer.Option(None, "--connection-type", help="Choices: ONE_WAY, TWO_WAY"),
|
|
1601
|
+
access_type: str = typer.Option(None, "--access-type", help="Choices: ALLOW_MEMBERS, BLOCK_MEMBERS"),
|
|
1602
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1603
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1604
|
+
):
|
|
1605
|
+
"""Configure Push-to-Talk Settings for a Virtual Line\n\nExample --json-body:\n '{"allowAutoAnswer":true,"connectionType":"ONE_WAY","accessType":"ALLOW_MEMBERS","members":["..."]}'."""
|
|
1606
|
+
api = get_api(debug=debug)
|
|
1607
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/pushToTalk"
|
|
1608
|
+
params = {}
|
|
1609
|
+
org_id = get_org_id()
|
|
1610
|
+
if org_id is not None:
|
|
1611
|
+
params["orgId"] = org_id
|
|
1612
|
+
if json_body:
|
|
1613
|
+
body = json.loads(json_body)
|
|
1614
|
+
else:
|
|
1615
|
+
body = {}
|
|
1616
|
+
if allow_auto_answer is not None:
|
|
1617
|
+
body["allowAutoAnswer"] = allow_auto_answer
|
|
1618
|
+
if connection_type is not None:
|
|
1619
|
+
body["connectionType"] = connection_type
|
|
1620
|
+
if access_type is not None:
|
|
1621
|
+
body["accessType"] = access_type
|
|
1622
|
+
try:
|
|
1623
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1624
|
+
except WebexError as e:
|
|
1625
|
+
handle_rest_error(e)
|
|
1626
|
+
typer.echo(f"Updated.")
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
|
|
1630
|
+
@app.command("show-call-bridge")
|
|
1631
|
+
def show_call_bridge(
|
|
1632
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1633
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1634
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1635
|
+
):
|
|
1636
|
+
"""Read Call Bridge Settings for a Virtual Line."""
|
|
1637
|
+
api = get_api(debug=debug)
|
|
1638
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callBridge"
|
|
1639
|
+
params = {}
|
|
1640
|
+
org_id = get_org_id()
|
|
1641
|
+
if org_id is not None:
|
|
1642
|
+
params["orgId"] = org_id
|
|
1643
|
+
try:
|
|
1644
|
+
result = api.session.rest_get(url, params=params)
|
|
1645
|
+
except WebexError as e:
|
|
1646
|
+
handle_rest_error(e)
|
|
1647
|
+
if output == "json":
|
|
1648
|
+
print_json(result)
|
|
1649
|
+
else:
|
|
1650
|
+
if isinstance(result, dict):
|
|
1651
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1652
|
+
elif isinstance(result, list):
|
|
1653
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1654
|
+
else:
|
|
1655
|
+
print_json(result)
|
|
1656
|
+
|
|
1657
|
+
|
|
1658
|
+
|
|
1659
|
+
@app.command("update-call-bridge")
|
|
1660
|
+
def update_call_bridge(
|
|
1661
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1662
|
+
warning_tone_enabled: bool = typer.Option(None, "--warning-tone-enabled/--no-warning-tone-enabled", help="Set to enable or disable a stutter dial tone being played to"),
|
|
1663
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1664
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1665
|
+
):
|
|
1666
|
+
"""Configure Call Bridge Settings for a Virtual Line."""
|
|
1667
|
+
api = get_api(debug=debug)
|
|
1668
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callBridge"
|
|
1669
|
+
params = {}
|
|
1670
|
+
org_id = get_org_id()
|
|
1671
|
+
if org_id is not None:
|
|
1672
|
+
params["orgId"] = org_id
|
|
1673
|
+
if json_body:
|
|
1674
|
+
body = json.loads(json_body)
|
|
1675
|
+
else:
|
|
1676
|
+
body = {}
|
|
1677
|
+
if warning_tone_enabled is not None:
|
|
1678
|
+
body["warningToneEnabled"] = warning_tone_enabled
|
|
1679
|
+
try:
|
|
1680
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1681
|
+
except WebexError as e:
|
|
1682
|
+
handle_rest_error(e)
|
|
1683
|
+
typer.echo(f"Updated.")
|
|
1684
|
+
|
|
1685
|
+
|
|
1686
|
+
|
|
1687
|
+
@app.command("show-barge-in")
|
|
1688
|
+
def show_barge_in(
|
|
1689
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1690
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1691
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1692
|
+
):
|
|
1693
|
+
"""Read Barge In Settings for a Virtual Line."""
|
|
1694
|
+
api = get_api(debug=debug)
|
|
1695
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/bargeIn"
|
|
1696
|
+
params = {}
|
|
1697
|
+
org_id = get_org_id()
|
|
1698
|
+
if org_id is not None:
|
|
1699
|
+
params["orgId"] = org_id
|
|
1700
|
+
try:
|
|
1701
|
+
result = api.session.rest_get(url, params=params)
|
|
1702
|
+
except WebexError as e:
|
|
1703
|
+
handle_rest_error(e)
|
|
1704
|
+
if output == "json":
|
|
1705
|
+
print_json(result)
|
|
1706
|
+
else:
|
|
1707
|
+
if isinstance(result, dict):
|
|
1708
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1709
|
+
elif isinstance(result, list):
|
|
1710
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1711
|
+
else:
|
|
1712
|
+
print_json(result)
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
@app.command("update-barge-in")
|
|
1717
|
+
def update_barge_in(
|
|
1718
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1719
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Set to enable or disable the Barge In feature."),
|
|
1720
|
+
tone_enabled: bool = typer.Option(None, "--tone-enabled/--no-tone-enabled", help="Set to enable or disable a stutter dial tone being played wh"),
|
|
1721
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1722
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1723
|
+
):
|
|
1724
|
+
"""Configure Barge In Settings for a Virtual Line."""
|
|
1725
|
+
api = get_api(debug=debug)
|
|
1726
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/bargeIn"
|
|
1727
|
+
params = {}
|
|
1728
|
+
org_id = get_org_id()
|
|
1729
|
+
if org_id is not None:
|
|
1730
|
+
params["orgId"] = org_id
|
|
1731
|
+
if json_body:
|
|
1732
|
+
body = json.loads(json_body)
|
|
1733
|
+
else:
|
|
1734
|
+
body = {}
|
|
1735
|
+
if enabled is not None:
|
|
1736
|
+
body["enabled"] = enabled
|
|
1737
|
+
if tone_enabled is not None:
|
|
1738
|
+
body["toneEnabled"] = tone_enabled
|
|
1739
|
+
try:
|
|
1740
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1741
|
+
except WebexError as e:
|
|
1742
|
+
handle_rest_error(e)
|
|
1743
|
+
typer.echo(f"Updated.")
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
|
|
1747
|
+
@app.command("list-privacy")
|
|
1748
|
+
def list_privacy(
|
|
1749
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1750
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1751
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1752
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1753
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1754
|
+
):
|
|
1755
|
+
"""Get a Virtual Line's Privacy Settings."""
|
|
1756
|
+
api = get_api(debug=debug)
|
|
1757
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/privacy"
|
|
1758
|
+
params = {}
|
|
1759
|
+
if limit > 0:
|
|
1760
|
+
params["max"] = limit
|
|
1761
|
+
if offset > 0:
|
|
1762
|
+
params["start"] = offset
|
|
1763
|
+
org_id = get_org_id()
|
|
1764
|
+
if org_id is not None:
|
|
1765
|
+
params["orgId"] = org_id
|
|
1766
|
+
result = None
|
|
1767
|
+
try:
|
|
1768
|
+
result = api.session.rest_get(url, params=params)
|
|
1769
|
+
except WebexError as e:
|
|
1770
|
+
handle_rest_error(e)
|
|
1771
|
+
result = result or []
|
|
1772
|
+
items = result.get("monitoringAgents", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1773
|
+
if output == "json":
|
|
1774
|
+
print_json(items)
|
|
1775
|
+
else:
|
|
1776
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
|
|
1780
|
+
@app.command("update-privacy")
|
|
1781
|
+
def update_privacy(
|
|
1782
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1783
|
+
aa_extension_dialing_enabled: bool = typer.Option(None, "--aa-extension-dialing-enabled/--no-aa-extension-dialing-enabled", help="When `true` auto attendant extension dialing is enabled."),
|
|
1784
|
+
aa_naming_dialing_enabled: bool = typer.Option(None, "--aa-naming-dialing-enabled/--no-aa-naming-dialing-enabled", help="When `true` auto attendant dialing by first or last name is"),
|
|
1785
|
+
enable_phone_status_directory_privacy: bool = typer.Option(None, "--enable-phone-status-directory-privacy/--no-enable-phone-status-directory-privacy", help="When `true` phone status directory privacy is enabled."),
|
|
1786
|
+
enable_phone_status_pickup_barge_in_privacy: bool = typer.Option(None, "--enable-phone-status-pickup-barge-in-privacy/--no-enable-phone-status-pickup-barge-in-privacy", help="When `true` privacy is enforced for call pickup and barge-in"),
|
|
1787
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1788
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1789
|
+
):
|
|
1790
|
+
"""Configure a Virtual Line's Privacy Settings\n\nExample --json-body:\n '{"aaExtensionDialingEnabled":true,"aaNamingDialingEnabled":true,"enablePhoneStatusDirectoryPrivacy":true,"enablePhoneStatusPickupBargeInPrivacy":true,"monitoringAgents":["..."]}'."""
|
|
1791
|
+
api = get_api(debug=debug)
|
|
1792
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/privacy"
|
|
1793
|
+
params = {}
|
|
1794
|
+
org_id = get_org_id()
|
|
1795
|
+
if org_id is not None:
|
|
1796
|
+
params["orgId"] = org_id
|
|
1797
|
+
if json_body:
|
|
1798
|
+
body = json.loads(json_body)
|
|
1799
|
+
else:
|
|
1800
|
+
body = {}
|
|
1801
|
+
if aa_extension_dialing_enabled is not None:
|
|
1802
|
+
body["aaExtensionDialingEnabled"] = aa_extension_dialing_enabled
|
|
1803
|
+
if aa_naming_dialing_enabled is not None:
|
|
1804
|
+
body["aaNamingDialingEnabled"] = aa_naming_dialing_enabled
|
|
1805
|
+
if enable_phone_status_directory_privacy is not None:
|
|
1806
|
+
body["enablePhoneStatusDirectoryPrivacy"] = enable_phone_status_directory_privacy
|
|
1807
|
+
if enable_phone_status_pickup_barge_in_privacy is not None:
|
|
1808
|
+
body["enablePhoneStatusPickupBargeInPrivacy"] = enable_phone_status_pickup_barge_in_privacy
|
|
1809
|
+
try:
|
|
1810
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1811
|
+
except WebexError as e:
|
|
1812
|
+
handle_rest_error(e)
|
|
1813
|
+
typer.echo(f"Updated.")
|
|
1814
|
+
|
|
1815
|
+
|
|
1816
|
+
|
|
1817
|
+
@app.command("list-available-numbers-fax-message")
|
|
1818
|
+
def list_available_numbers_fax_message(
|
|
1819
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1820
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1821
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1822
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1823
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1824
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1825
|
+
):
|
|
1826
|
+
"""Get Virtual Line Fax Message Available Phone Numbers."""
|
|
1827
|
+
api = get_api(debug=debug)
|
|
1828
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/faxMessage/availableNumbers"
|
|
1829
|
+
params = {}
|
|
1830
|
+
if phone_number is not None:
|
|
1831
|
+
params["phoneNumber"] = phone_number
|
|
1832
|
+
if limit > 0:
|
|
1833
|
+
params["max"] = limit
|
|
1834
|
+
if offset > 0:
|
|
1835
|
+
params["start"] = offset
|
|
1836
|
+
org_id = get_org_id()
|
|
1837
|
+
if org_id is not None:
|
|
1838
|
+
params["orgId"] = org_id
|
|
1839
|
+
result = None
|
|
1840
|
+
try:
|
|
1841
|
+
result = api.session.rest_get(url, params=params)
|
|
1842
|
+
except WebexError as e:
|
|
1843
|
+
handle_rest_error(e)
|
|
1844
|
+
result = result or []
|
|
1845
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1846
|
+
if output == "json":
|
|
1847
|
+
print_json(items)
|
|
1848
|
+
else:
|
|
1849
|
+
print_table(items, columns=[('Phone Number', 'phoneNumber'), ('State', 'state')], limit=limit)
|
|
1850
|
+
|
|
1851
|
+
|
|
1852
|
+
|
|
1853
|
+
@app.command("list-available-numbers-call-forwarding")
|
|
1854
|
+
def list_available_numbers_call_forwarding(
|
|
1855
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1856
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1857
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
1858
|
+
extension: str = typer.Option(None, "--extension", help="Returns the list of PSTN phone numbers with the given `exten"),
|
|
1859
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1860
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1861
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1862
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1863
|
+
):
|
|
1864
|
+
"""Get Virtual Line Call Forward Available Phone Numbers."""
|
|
1865
|
+
api = get_api(debug=debug)
|
|
1866
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callForwarding/availableNumbers"
|
|
1867
|
+
params = {}
|
|
1868
|
+
if phone_number is not None:
|
|
1869
|
+
params["phoneNumber"] = phone_number
|
|
1870
|
+
if owner_name is not None:
|
|
1871
|
+
params["ownerName"] = owner_name
|
|
1872
|
+
if extension is not None:
|
|
1873
|
+
params["extension"] = extension
|
|
1874
|
+
if limit > 0:
|
|
1875
|
+
params["max"] = limit
|
|
1876
|
+
if offset > 0:
|
|
1877
|
+
params["start"] = offset
|
|
1878
|
+
org_id = get_org_id()
|
|
1879
|
+
if org_id is not None:
|
|
1880
|
+
params["orgId"] = org_id
|
|
1881
|
+
result = None
|
|
1882
|
+
try:
|
|
1883
|
+
result = api.session.rest_get(url, params=params)
|
|
1884
|
+
except WebexError as e:
|
|
1885
|
+
handle_rest_error(e)
|
|
1886
|
+
result = result or []
|
|
1887
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1888
|
+
if output == "json":
|
|
1889
|
+
print_json(items)
|
|
1890
|
+
else:
|
|
1891
|
+
print_table(items, columns=[('Phone Number', 'phoneNumber'), ('State', 'state')], limit=limit)
|
|
1892
|
+
|
|
1893
|
+
|
|
1894
|
+
|
|
1895
|
+
@app.command("list-available-numbers-virtual-lines")
|
|
1896
|
+
def list_available_numbers_virtual_lines(
|
|
1897
|
+
location_id: str = typer.Option(None, "--location-id", help="Return the list of phone numbers for this location within th"),
|
|
1898
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1899
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1900
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1901
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1902
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1903
|
+
):
|
|
1904
|
+
"""Get Virtual Line Available Phone Numbers."""
|
|
1905
|
+
api = get_api(debug=debug)
|
|
1906
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/availableNumbers"
|
|
1907
|
+
params = {}
|
|
1908
|
+
if location_id is not None:
|
|
1909
|
+
params["locationId"] = location_id
|
|
1910
|
+
if phone_number is not None:
|
|
1911
|
+
params["phoneNumber"] = phone_number
|
|
1912
|
+
if limit > 0:
|
|
1913
|
+
params["max"] = limit
|
|
1914
|
+
if offset > 0:
|
|
1915
|
+
params["start"] = offset
|
|
1916
|
+
org_id = get_org_id()
|
|
1917
|
+
if org_id is not None:
|
|
1918
|
+
params["orgId"] = org_id
|
|
1919
|
+
result = None
|
|
1920
|
+
try:
|
|
1921
|
+
result = api.session.rest_get(url, params=params)
|
|
1922
|
+
except WebexError as e:
|
|
1923
|
+
handle_rest_error(e)
|
|
1924
|
+
result = result or []
|
|
1925
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1926
|
+
if output == "json":
|
|
1927
|
+
print_json(items)
|
|
1928
|
+
else:
|
|
1929
|
+
print_table(items, columns=[('Phone Number', 'phoneNumber'), ('State', 'state')], limit=limit)
|
|
1930
|
+
|
|
1931
|
+
|
|
1932
|
+
|
|
1933
|
+
@app.command("list-available-numbers-emergency-callback-number")
|
|
1934
|
+
def list_available_numbers_emergency_callback_number(
|
|
1935
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1936
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1937
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
1938
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1939
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1940
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1941
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1942
|
+
):
|
|
1943
|
+
"""Get Virtual Line ECBN Available Phone Numbers."""
|
|
1944
|
+
api = get_api(debug=debug)
|
|
1945
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/emergencyCallbackNumber/availableNumbers"
|
|
1946
|
+
params = {}
|
|
1947
|
+
if phone_number is not None:
|
|
1948
|
+
params["phoneNumber"] = phone_number
|
|
1949
|
+
if owner_name is not None:
|
|
1950
|
+
params["ownerName"] = owner_name
|
|
1951
|
+
if limit > 0:
|
|
1952
|
+
params["max"] = limit
|
|
1953
|
+
if offset > 0:
|
|
1954
|
+
params["start"] = offset
|
|
1955
|
+
org_id = get_org_id()
|
|
1956
|
+
if org_id is not None:
|
|
1957
|
+
params["orgId"] = org_id
|
|
1958
|
+
result = None
|
|
1959
|
+
try:
|
|
1960
|
+
result = api.session.rest_get(url, params=params)
|
|
1961
|
+
except WebexError as e:
|
|
1962
|
+
handle_rest_error(e)
|
|
1963
|
+
result = result or []
|
|
1964
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1965
|
+
if output == "json":
|
|
1966
|
+
print_json(items)
|
|
1967
|
+
else:
|
|
1968
|
+
print_table(items, columns=[('Phone Number', 'phoneNumber'), ('State', 'state')], limit=limit)
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
|
|
1972
|
+
@app.command("list-available-numbers-call-intercept")
|
|
1973
|
+
def list_available_numbers_call_intercept(
|
|
1974
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
1975
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1976
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
1977
|
+
extension: str = typer.Option(None, "--extension", help="Returns the list of PSTN phone numbers with the given `exten"),
|
|
1978
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1979
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1980
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1981
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1982
|
+
):
|
|
1983
|
+
"""Get Virtual Line Call Intercept Available Phone Numbers."""
|
|
1984
|
+
api = get_api(debug=debug)
|
|
1985
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/callIntercept/availableNumbers"
|
|
1986
|
+
params = {}
|
|
1987
|
+
if phone_number is not None:
|
|
1988
|
+
params["phoneNumber"] = phone_number
|
|
1989
|
+
if owner_name is not None:
|
|
1990
|
+
params["ownerName"] = owner_name
|
|
1991
|
+
if extension is not None:
|
|
1992
|
+
params["extension"] = extension
|
|
1993
|
+
if limit > 0:
|
|
1994
|
+
params["max"] = limit
|
|
1995
|
+
if offset > 0:
|
|
1996
|
+
params["start"] = offset
|
|
1997
|
+
org_id = get_org_id()
|
|
1998
|
+
if org_id is not None:
|
|
1999
|
+
params["orgId"] = org_id
|
|
2000
|
+
result = None
|
|
2001
|
+
try:
|
|
2002
|
+
result = api.session.rest_get(url, params=params)
|
|
2003
|
+
except WebexError as e:
|
|
2004
|
+
handle_rest_error(e)
|
|
2005
|
+
result = result or []
|
|
2006
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2007
|
+
if output == "json":
|
|
2008
|
+
print_json(items)
|
|
2009
|
+
else:
|
|
2010
|
+
print_table(items, columns=[('Phone Number', 'phoneNumber'), ('State', 'state')], limit=limit)
|
|
2011
|
+
|
|
2012
|
+
|
|
2013
|
+
|
|
2014
|
+
@app.command("show-do-not-disturb")
|
|
2015
|
+
def show_do_not_disturb(
|
|
2016
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
2017
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2018
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2019
|
+
):
|
|
2020
|
+
"""Retrieve DoNotDisturb Settings for a Virtual Line."""
|
|
2021
|
+
api = get_api(debug=debug)
|
|
2022
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/doNotDisturb"
|
|
2023
|
+
params = {}
|
|
2024
|
+
org_id = get_org_id()
|
|
2025
|
+
if org_id is not None:
|
|
2026
|
+
params["orgId"] = org_id
|
|
2027
|
+
try:
|
|
2028
|
+
result = api.session.rest_get(url, params=params)
|
|
2029
|
+
except WebexError as e:
|
|
2030
|
+
handle_rest_error(e)
|
|
2031
|
+
if output == "json":
|
|
2032
|
+
print_json(result)
|
|
2033
|
+
else:
|
|
2034
|
+
if isinstance(result, dict):
|
|
2035
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2036
|
+
elif isinstance(result, list):
|
|
2037
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2038
|
+
else:
|
|
2039
|
+
print_json(result)
|
|
2040
|
+
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
@app.command("update-do-not-disturb")
|
|
2044
|
+
def update_do_not_disturb(
|
|
2045
|
+
virtual_line_id: str = typer.Argument(help="virtualLineId"),
|
|
2046
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the DoNotDisturb feature is enabled."),
|
|
2047
|
+
ring_splash_enabled: bool = typer.Option(None, "--ring-splash-enabled/--no-ring-splash-enabled", help="When `true`, enables ring reminder when you receive an incom"),
|
|
2048
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2049
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2050
|
+
):
|
|
2051
|
+
"""Modify DoNotDisturb Settings for a Virtual Line."""
|
|
2052
|
+
api = get_api(debug=debug)
|
|
2053
|
+
url = f"https://webexapis.com/v1/telephony/config/virtualLines/{virtual_line_id}/doNotDisturb"
|
|
2054
|
+
params = {}
|
|
2055
|
+
org_id = get_org_id()
|
|
2056
|
+
if org_id is not None:
|
|
2057
|
+
params["orgId"] = org_id
|
|
2058
|
+
if json_body:
|
|
2059
|
+
body = json.loads(json_body)
|
|
2060
|
+
else:
|
|
2061
|
+
body = {}
|
|
2062
|
+
if enabled is not None:
|
|
2063
|
+
body["enabled"] = enabled
|
|
2064
|
+
if ring_splash_enabled is not None:
|
|
2065
|
+
body["ringSplashEnabled"] = ring_splash_enabled
|
|
2066
|
+
try:
|
|
2067
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2068
|
+
except WebexError as e:
|
|
2069
|
+
handle_rest_error(e)
|
|
2070
|
+
typer.echo(f"Updated.")
|
|
2071
|
+
|
|
2072
|
+
|