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,3347 @@
|
|
|
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 workspace-settings.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("show")
|
|
13
|
+
def show(
|
|
14
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
15
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
16
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
17
|
+
):
|
|
18
|
+
"""Retrieve Call Forwarding Settings for a Workspace."""
|
|
19
|
+
api = get_api(debug=debug)
|
|
20
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/callForwarding"
|
|
21
|
+
params = {}
|
|
22
|
+
org_id = get_org_id()
|
|
23
|
+
if org_id is not None:
|
|
24
|
+
params["orgId"] = org_id
|
|
25
|
+
try:
|
|
26
|
+
result = api.session.rest_get(url, params=params)
|
|
27
|
+
except WebexError as e:
|
|
28
|
+
handle_rest_error(e)
|
|
29
|
+
if output == "json":
|
|
30
|
+
print_json(result)
|
|
31
|
+
else:
|
|
32
|
+
if isinstance(result, dict):
|
|
33
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
34
|
+
elif isinstance(result, list):
|
|
35
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
36
|
+
else:
|
|
37
|
+
print_json(result)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@app.command("update")
|
|
42
|
+
def update(
|
|
43
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
44
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
45
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
46
|
+
):
|
|
47
|
+
"""Modify Call Forwarding Settings for a Workspace\n\nExample --json-body:\n '{"callForwarding":{"always":{"enabled":"...","ringReminderEnabled":"...","destinationVoicemailEnabled":"...","destination":"..."},"busy":{"enabled":"...","destinationVoicemailEnabled":"...","destination":"..."},"noAnswer":{"enabled":"...","destination":"...","numberOfRings":"...","systemMaxNumberOfRings":"...","destinationVoicemailEnabled":"..."}},"businessContinuity":{"enabled":true,"destinationVoicemailEnabled":true,"destination":"..."}}'."""
|
|
48
|
+
api = get_api(debug=debug)
|
|
49
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/callForwarding"
|
|
50
|
+
params = {}
|
|
51
|
+
org_id = get_org_id()
|
|
52
|
+
if org_id is not None:
|
|
53
|
+
params["orgId"] = org_id
|
|
54
|
+
if json_body:
|
|
55
|
+
body = json.loads(json_body)
|
|
56
|
+
else:
|
|
57
|
+
body = {}
|
|
58
|
+
try:
|
|
59
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
60
|
+
except WebexError as e:
|
|
61
|
+
handle_rest_error(e)
|
|
62
|
+
typer.echo(f"Updated.")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@app.command("show-call-waiting")
|
|
67
|
+
def show_call_waiting(
|
|
68
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
69
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
70
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
71
|
+
):
|
|
72
|
+
"""Retrieve Call Waiting Settings for a Workspace."""
|
|
73
|
+
api = get_api(debug=debug)
|
|
74
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/callWaiting"
|
|
75
|
+
params = {}
|
|
76
|
+
org_id = get_org_id()
|
|
77
|
+
if org_id is not None:
|
|
78
|
+
params["orgId"] = org_id
|
|
79
|
+
try:
|
|
80
|
+
result = api.session.rest_get(url, params=params)
|
|
81
|
+
except WebexError as e:
|
|
82
|
+
handle_rest_error(e)
|
|
83
|
+
if output == "json":
|
|
84
|
+
print_json(result)
|
|
85
|
+
else:
|
|
86
|
+
if isinstance(result, dict):
|
|
87
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
88
|
+
elif isinstance(result, list):
|
|
89
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
90
|
+
else:
|
|
91
|
+
print_json(result)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@app.command("update-call-waiting")
|
|
96
|
+
def update_call_waiting(
|
|
97
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
98
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Call Waiting state."),
|
|
99
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
100
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
101
|
+
):
|
|
102
|
+
"""Modify Call Waiting Settings for a Workspace."""
|
|
103
|
+
api = get_api(debug=debug)
|
|
104
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/callWaiting"
|
|
105
|
+
params = {}
|
|
106
|
+
org_id = get_org_id()
|
|
107
|
+
if org_id is not None:
|
|
108
|
+
params["orgId"] = org_id
|
|
109
|
+
if json_body:
|
|
110
|
+
body = json.loads(json_body)
|
|
111
|
+
else:
|
|
112
|
+
body = {}
|
|
113
|
+
if enabled is not None:
|
|
114
|
+
body["enabled"] = enabled
|
|
115
|
+
try:
|
|
116
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
117
|
+
except WebexError as e:
|
|
118
|
+
handle_rest_error(e)
|
|
119
|
+
typer.echo(f"Updated.")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@app.command("list")
|
|
124
|
+
def cmd_list(
|
|
125
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
126
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
127
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
128
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
129
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
130
|
+
):
|
|
131
|
+
"""Read Caller ID Settings for a Workspace."""
|
|
132
|
+
api = get_api(debug=debug)
|
|
133
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/callerId"
|
|
134
|
+
params = {}
|
|
135
|
+
if limit > 0:
|
|
136
|
+
params["max"] = limit
|
|
137
|
+
if offset > 0:
|
|
138
|
+
params["start"] = offset
|
|
139
|
+
org_id = get_org_id()
|
|
140
|
+
if org_id is not None:
|
|
141
|
+
params["orgId"] = org_id
|
|
142
|
+
result = None
|
|
143
|
+
try:
|
|
144
|
+
result = api.session.rest_get(url, params=params)
|
|
145
|
+
except WebexError as e:
|
|
146
|
+
handle_rest_error(e)
|
|
147
|
+
result = result or []
|
|
148
|
+
items = result.get("types", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
149
|
+
if output == "json":
|
|
150
|
+
print_json(items)
|
|
151
|
+
else:
|
|
152
|
+
print_table(items, columns=[('Number', 'directNumber'), ('Extension', 'extension')], limit=limit)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@app.command("update-caller-id")
|
|
157
|
+
def update_caller_id(
|
|
158
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
159
|
+
selected: str = typer.Option(None, "--selected", help="Choices: DIRECT_LINE, LOCATION_NUMBER, CUSTOM"),
|
|
160
|
+
custom_number: str = typer.Option(None, "--custom-number", help="Custom number which is shown if CUSTOM is selected. This val"),
|
|
161
|
+
display_name: str = typer.Option(None, "--display-name", help="Workspace's caller ID display name. This field has been depr"),
|
|
162
|
+
display_detail: str = typer.Option(None, "--display-detail", help="Workspace's caller ID display details. This field has been d"),
|
|
163
|
+
block_in_forward_calls_enabled: bool = typer.Option(None, "--block-in-forward-calls-enabled/--no-block-in-forward-calls-enabled", help="Block this workspace's identity when receiving a call."),
|
|
164
|
+
external_caller_id_name_policy: str = typer.Option(None, "--external-caller-id-name-policy", help="Choices: DIRECT_LINE, LOCATION, OTHER"),
|
|
165
|
+
custom_external_caller_id_name: str = typer.Option(None, "--custom-external-caller-id-name", help="Custom external caller ID name which is shown if external ca"),
|
|
166
|
+
location_external_caller_id_name: str = typer.Option(None, "--location-external-caller-id-name", help="Location's external caller ID name which is shown if externa"),
|
|
167
|
+
dial_by_name: str = typer.Option(None, "--dial-by-name", help="Sets or clears the name to be used for dial by name function"),
|
|
168
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
169
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
170
|
+
):
|
|
171
|
+
"""Configure Caller ID Settings for a Workspace\n\nExample --json-body:\n '{"selected":"DIRECT_LINE","customNumber":"...","displayName":"...","displayDetail":"...","blockInForwardCallsEnabled":true,"externalCallerIdNamePolicy":"DIRECT_LINE","customExternalCallerIdName":"...","locationExternalCallerIdName":"..."}'."""
|
|
172
|
+
api = get_api(debug=debug)
|
|
173
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/callerId"
|
|
174
|
+
params = {}
|
|
175
|
+
org_id = get_org_id()
|
|
176
|
+
if org_id is not None:
|
|
177
|
+
params["orgId"] = org_id
|
|
178
|
+
if json_body:
|
|
179
|
+
body = json.loads(json_body)
|
|
180
|
+
else:
|
|
181
|
+
body = {}
|
|
182
|
+
if selected is not None:
|
|
183
|
+
body["selected"] = selected
|
|
184
|
+
if custom_number is not None:
|
|
185
|
+
body["customNumber"] = custom_number
|
|
186
|
+
if display_name is not None:
|
|
187
|
+
body["displayName"] = display_name
|
|
188
|
+
if display_detail is not None:
|
|
189
|
+
body["displayDetail"] = display_detail
|
|
190
|
+
if block_in_forward_calls_enabled is not None:
|
|
191
|
+
body["blockInForwardCallsEnabled"] = block_in_forward_calls_enabled
|
|
192
|
+
if external_caller_id_name_policy is not None:
|
|
193
|
+
body["externalCallerIdNamePolicy"] = external_caller_id_name_policy
|
|
194
|
+
if custom_external_caller_id_name is not None:
|
|
195
|
+
body["customExternalCallerIdName"] = custom_external_caller_id_name
|
|
196
|
+
if location_external_caller_id_name is not None:
|
|
197
|
+
body["locationExternalCallerIdName"] = location_external_caller_id_name
|
|
198
|
+
if dial_by_name is not None:
|
|
199
|
+
body["dialByName"] = dial_by_name
|
|
200
|
+
try:
|
|
201
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
202
|
+
except WebexError as e:
|
|
203
|
+
handle_rest_error(e)
|
|
204
|
+
typer.echo(f"Updated.")
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@app.command("list-monitoring")
|
|
209
|
+
def list_monitoring(
|
|
210
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
211
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
212
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
213
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
214
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
215
|
+
):
|
|
216
|
+
"""Retrieve Monitoring Settings for a Workspace."""
|
|
217
|
+
api = get_api(debug=debug)
|
|
218
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/monitoring"
|
|
219
|
+
params = {}
|
|
220
|
+
if limit > 0:
|
|
221
|
+
params["max"] = limit
|
|
222
|
+
if offset > 0:
|
|
223
|
+
params["start"] = offset
|
|
224
|
+
org_id = get_org_id()
|
|
225
|
+
if org_id is not None:
|
|
226
|
+
params["orgId"] = org_id
|
|
227
|
+
result = None
|
|
228
|
+
try:
|
|
229
|
+
result = api.session.rest_get(url, params=params)
|
|
230
|
+
except WebexError as e:
|
|
231
|
+
handle_rest_error(e)
|
|
232
|
+
result = result or []
|
|
233
|
+
items = result.get("monitoredElements", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
234
|
+
if output == "json":
|
|
235
|
+
print_json(items)
|
|
236
|
+
else:
|
|
237
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@app.command("update-monitoring")
|
|
242
|
+
def update_monitoring(
|
|
243
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
244
|
+
enable_call_park_notification: bool = typer.Option(None, "--enable-call-park-notification/--no-enable-call-park-notification", help="Call park notification is enabled or disabled."),
|
|
245
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
246
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
247
|
+
):
|
|
248
|
+
"""Modify Monitoring Settings for a Workspace\n\nExample --json-body:\n '{"enableCallParkNotification":true,"monitoredElements":[{"id":"...","type":"...","lineKeyLabel":"...","phoneNumber":"..."}]}'."""
|
|
249
|
+
api = get_api(debug=debug)
|
|
250
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/monitoring"
|
|
251
|
+
params = {}
|
|
252
|
+
org_id = get_org_id()
|
|
253
|
+
if org_id is not None:
|
|
254
|
+
params["orgId"] = org_id
|
|
255
|
+
if json_body:
|
|
256
|
+
body = json.loads(json_body)
|
|
257
|
+
else:
|
|
258
|
+
body = {}
|
|
259
|
+
if enable_call_park_notification is not None:
|
|
260
|
+
body["enableCallParkNotification"] = enable_call_park_notification
|
|
261
|
+
try:
|
|
262
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
263
|
+
except WebexError as e:
|
|
264
|
+
handle_rest_error(e)
|
|
265
|
+
typer.echo(f"Updated.")
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@app.command("list-available-members-speed-dials")
|
|
270
|
+
def list_available_members_speed_dials(
|
|
271
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
272
|
+
location_id: str = typer.Option(None, "--location-id", help="Search for the available speed dials in the location ID."),
|
|
273
|
+
member_name: str = typer.Option(None, "--member-name", help="Search for available members by name."),
|
|
274
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Search for available members by number or extension."),
|
|
275
|
+
order: str = typer.Option(None, "--order", help="Sort response based on `firstName` or `lastName` with sort d"),
|
|
276
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
277
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
278
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
279
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
280
|
+
):
|
|
281
|
+
"""Get Available Speed Dials for Workspace Monitoring."""
|
|
282
|
+
api = get_api(debug=debug)
|
|
283
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/monitoring/speedDials/availableMembers"
|
|
284
|
+
params = {}
|
|
285
|
+
if location_id is not None:
|
|
286
|
+
params["locationId"] = location_id
|
|
287
|
+
if member_name is not None:
|
|
288
|
+
params["memberName"] = member_name
|
|
289
|
+
if phone_number is not None:
|
|
290
|
+
params["phoneNumber"] = phone_number
|
|
291
|
+
if order is not None:
|
|
292
|
+
params["order"] = order
|
|
293
|
+
if limit > 0:
|
|
294
|
+
params["max"] = limit
|
|
295
|
+
if offset > 0:
|
|
296
|
+
params["start"] = offset
|
|
297
|
+
org_id = get_org_id()
|
|
298
|
+
if org_id is not None:
|
|
299
|
+
params["orgId"] = org_id
|
|
300
|
+
result = None
|
|
301
|
+
try:
|
|
302
|
+
result = api.session.rest_get(url, params=params)
|
|
303
|
+
except WebexError as e:
|
|
304
|
+
handle_rest_error(e)
|
|
305
|
+
result = result or []
|
|
306
|
+
items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
307
|
+
if output == "json":
|
|
308
|
+
print_json(items)
|
|
309
|
+
else:
|
|
310
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
@app.command("list-available-members-monitoring")
|
|
315
|
+
def list_available_members_monitoring(
|
|
316
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
317
|
+
location_id: str = typer.Option(None, "--location-id", help="Search for the available members in the location ID."),
|
|
318
|
+
member_name: str = typer.Option(None, "--member-name", help="Search for available members by name."),
|
|
319
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Search for available members by number or extension."),
|
|
320
|
+
order: str = typer.Option(None, "--order", help="Sort response based on `firstName` or `lastName` with sort d"),
|
|
321
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
322
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
323
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
324
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
325
|
+
):
|
|
326
|
+
"""Get Available Members for Workspace Monitoring."""
|
|
327
|
+
api = get_api(debug=debug)
|
|
328
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/monitoring/availableMembers"
|
|
329
|
+
params = {}
|
|
330
|
+
if location_id is not None:
|
|
331
|
+
params["locationId"] = location_id
|
|
332
|
+
if member_name is not None:
|
|
333
|
+
params["memberName"] = member_name
|
|
334
|
+
if phone_number is not None:
|
|
335
|
+
params["phoneNumber"] = phone_number
|
|
336
|
+
if order is not None:
|
|
337
|
+
params["order"] = order
|
|
338
|
+
if limit > 0:
|
|
339
|
+
params["max"] = limit
|
|
340
|
+
if offset > 0:
|
|
341
|
+
params["start"] = offset
|
|
342
|
+
org_id = get_org_id()
|
|
343
|
+
if org_id is not None:
|
|
344
|
+
params["orgId"] = org_id
|
|
345
|
+
result = None
|
|
346
|
+
try:
|
|
347
|
+
result = api.session.rest_get(url, params=params)
|
|
348
|
+
except WebexError as e:
|
|
349
|
+
handle_rest_error(e)
|
|
350
|
+
result = result or []
|
|
351
|
+
items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
352
|
+
if output == "json":
|
|
353
|
+
print_json(items)
|
|
354
|
+
else:
|
|
355
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@app.command("list-numbers")
|
|
360
|
+
def list_numbers(
|
|
361
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
362
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
363
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
364
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
365
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
366
|
+
):
|
|
367
|
+
"""List numbers associated with a specific workspace."""
|
|
368
|
+
api = get_api(debug=debug)
|
|
369
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/numbers"
|
|
370
|
+
params = {}
|
|
371
|
+
if limit > 0:
|
|
372
|
+
params["max"] = limit
|
|
373
|
+
if offset > 0:
|
|
374
|
+
params["start"] = offset
|
|
375
|
+
org_id = get_org_id()
|
|
376
|
+
if org_id is not None:
|
|
377
|
+
params["orgId"] = org_id
|
|
378
|
+
result = None
|
|
379
|
+
try:
|
|
380
|
+
result = api.session.rest_get(url, params=params)
|
|
381
|
+
except WebexError as e:
|
|
382
|
+
handle_rest_error(e)
|
|
383
|
+
result = result or []
|
|
384
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
385
|
+
if output == "json":
|
|
386
|
+
print_json(items)
|
|
387
|
+
else:
|
|
388
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
@app.command("show-incoming-permission")
|
|
393
|
+
def show_incoming_permission(
|
|
394
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
395
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
396
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
397
|
+
):
|
|
398
|
+
"""Retrieve Incoming Permission Settings for a Workspace."""
|
|
399
|
+
api = get_api(debug=debug)
|
|
400
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/incomingPermission"
|
|
401
|
+
params = {}
|
|
402
|
+
org_id = get_org_id()
|
|
403
|
+
if org_id is not None:
|
|
404
|
+
params["orgId"] = org_id
|
|
405
|
+
try:
|
|
406
|
+
result = api.session.rest_get(url, params=params)
|
|
407
|
+
except WebexError as e:
|
|
408
|
+
handle_rest_error(e)
|
|
409
|
+
if output == "json":
|
|
410
|
+
print_json(result)
|
|
411
|
+
else:
|
|
412
|
+
if isinstance(result, dict):
|
|
413
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
414
|
+
elif isinstance(result, list):
|
|
415
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
416
|
+
else:
|
|
417
|
+
print_json(result)
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
@app.command("update-incoming-permission")
|
|
422
|
+
def update_incoming_permission(
|
|
423
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
424
|
+
use_custom_enabled: bool = typer.Option(None, "--use-custom-enabled/--no-use-custom-enabled", help="Incoming Permission state. If disabled, the default settings"),
|
|
425
|
+
external_transfer: str = typer.Option(None, "--external-transfer", help="Choices: ALLOW_ALL_EXTERNAL, ALLOW_ONLY_TRANSFERRED_EXTERNAL, BLOCK_ALL_EXTERNAL"),
|
|
426
|
+
internal_calls_enabled: bool = typer.Option(None, "--internal-calls-enabled/--no-internal-calls-enabled", help="Flag to indicate if the workspace can receive internal calls"),
|
|
427
|
+
collect_calls_enabled: bool = typer.Option(None, "--collect-calls-enabled/--no-collect-calls-enabled", help="Flag to indicate if the workspace can receive collect calls."),
|
|
428
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
429
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
430
|
+
):
|
|
431
|
+
"""Modify Incoming Permission Settings for a Workspace."""
|
|
432
|
+
api = get_api(debug=debug)
|
|
433
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/incomingPermission"
|
|
434
|
+
params = {}
|
|
435
|
+
org_id = get_org_id()
|
|
436
|
+
if org_id is not None:
|
|
437
|
+
params["orgId"] = org_id
|
|
438
|
+
if json_body:
|
|
439
|
+
body = json.loads(json_body)
|
|
440
|
+
else:
|
|
441
|
+
body = {}
|
|
442
|
+
if use_custom_enabled is not None:
|
|
443
|
+
body["useCustomEnabled"] = use_custom_enabled
|
|
444
|
+
if external_transfer is not None:
|
|
445
|
+
body["externalTransfer"] = external_transfer
|
|
446
|
+
if internal_calls_enabled is not None:
|
|
447
|
+
body["internalCallsEnabled"] = internal_calls_enabled
|
|
448
|
+
if collect_calls_enabled is not None:
|
|
449
|
+
body["collectCallsEnabled"] = collect_calls_enabled
|
|
450
|
+
try:
|
|
451
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
452
|
+
except WebexError as e:
|
|
453
|
+
handle_rest_error(e)
|
|
454
|
+
typer.echo(f"Updated.")
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
@app.command("list-outgoing-permission")
|
|
459
|
+
def list_outgoing_permission(
|
|
460
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
461
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
462
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
463
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
464
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
465
|
+
):
|
|
466
|
+
"""Retrieve Outgoing Permission Settings for a Workspace."""
|
|
467
|
+
api = get_api(debug=debug)
|
|
468
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission"
|
|
469
|
+
params = {}
|
|
470
|
+
if limit > 0:
|
|
471
|
+
params["max"] = limit
|
|
472
|
+
if offset > 0:
|
|
473
|
+
params["start"] = offset
|
|
474
|
+
org_id = get_org_id()
|
|
475
|
+
if org_id is not None:
|
|
476
|
+
params["orgId"] = org_id
|
|
477
|
+
result = None
|
|
478
|
+
try:
|
|
479
|
+
result = api.session.rest_get(url, params=params)
|
|
480
|
+
except WebexError as e:
|
|
481
|
+
handle_rest_error(e)
|
|
482
|
+
result = result or []
|
|
483
|
+
items = result.get("callingPermissions", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
484
|
+
if output == "json":
|
|
485
|
+
print_json(items)
|
|
486
|
+
else:
|
|
487
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
@app.command("update-outgoing-permission")
|
|
492
|
+
def update_outgoing_permission(
|
|
493
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
494
|
+
use_custom_enabled: bool = typer.Option(None, "--use-custom-enabled/--no-use-custom-enabled", help="When `true`, indicates that this workspace uses the shared c"),
|
|
495
|
+
use_custom_permissions: bool = typer.Option(None, "--use-custom-permissions/--no-use-custom-permissions", help="When `true`, indicates that this workspace uses the specifie"),
|
|
496
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
497
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
498
|
+
):
|
|
499
|
+
"""Modify Outgoing Permission Settings for a Workspace\n\nExample --json-body:\n '{"useCustomEnabled":true,"useCustomPermissions":true,"callingPermissions":[{"callType":"...","action":"...","transferEnabled":"..."}]}'."""
|
|
500
|
+
api = get_api(debug=debug)
|
|
501
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission"
|
|
502
|
+
params = {}
|
|
503
|
+
org_id = get_org_id()
|
|
504
|
+
if org_id is not None:
|
|
505
|
+
params["orgId"] = org_id
|
|
506
|
+
if json_body:
|
|
507
|
+
body = json.loads(json_body)
|
|
508
|
+
else:
|
|
509
|
+
body = {}
|
|
510
|
+
if use_custom_enabled is not None:
|
|
511
|
+
body["useCustomEnabled"] = use_custom_enabled
|
|
512
|
+
if use_custom_permissions is not None:
|
|
513
|
+
body["useCustomPermissions"] = use_custom_permissions
|
|
514
|
+
try:
|
|
515
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
516
|
+
except WebexError as e:
|
|
517
|
+
handle_rest_error(e)
|
|
518
|
+
typer.echo(f"Updated.")
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
@app.command("list-access-codes")
|
|
523
|
+
def list_access_codes(
|
|
524
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
525
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
526
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
527
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
528
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
529
|
+
):
|
|
530
|
+
"""Retrieve Access Codes for a Workspace."""
|
|
531
|
+
api = get_api(debug=debug)
|
|
532
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission/accessCodes"
|
|
533
|
+
params = {}
|
|
534
|
+
if limit > 0:
|
|
535
|
+
params["max"] = limit
|
|
536
|
+
if offset > 0:
|
|
537
|
+
params["start"] = offset
|
|
538
|
+
org_id = get_org_id()
|
|
539
|
+
if org_id is not None:
|
|
540
|
+
params["orgId"] = org_id
|
|
541
|
+
result = None
|
|
542
|
+
try:
|
|
543
|
+
result = api.session.rest_get(url, params=params)
|
|
544
|
+
except WebexError as e:
|
|
545
|
+
handle_rest_error(e)
|
|
546
|
+
result = result or []
|
|
547
|
+
items = result.get("accessCodes", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
548
|
+
if output == "json":
|
|
549
|
+
print_json(items)
|
|
550
|
+
else:
|
|
551
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
@app.command("create")
|
|
556
|
+
def create(
|
|
557
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
558
|
+
code: str = typer.Option(None, "--code", help="(required) An Access code."),
|
|
559
|
+
description: str = typer.Option(None, "--description", help="(required) The description of the access code."),
|
|
560
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
561
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
562
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
563
|
+
):
|
|
564
|
+
"""Create Access Codes for a Workspace."""
|
|
565
|
+
api = get_api(debug=debug)
|
|
566
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission/accessCodes"
|
|
567
|
+
params = {}
|
|
568
|
+
org_id = get_org_id()
|
|
569
|
+
if org_id is not None:
|
|
570
|
+
params["orgId"] = org_id
|
|
571
|
+
if json_body:
|
|
572
|
+
body = json.loads(json_body)
|
|
573
|
+
else:
|
|
574
|
+
body = {}
|
|
575
|
+
if code is not None:
|
|
576
|
+
body["code"] = code
|
|
577
|
+
if description is not None:
|
|
578
|
+
body["description"] = description
|
|
579
|
+
_missing = [f for f in ['code', 'description'] if f not in body or body[f] is None]
|
|
580
|
+
if _missing:
|
|
581
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
582
|
+
raise typer.Exit(1)
|
|
583
|
+
try:
|
|
584
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
585
|
+
except WebexError as e:
|
|
586
|
+
handle_rest_error(e)
|
|
587
|
+
if output == "json":
|
|
588
|
+
print_json(result)
|
|
589
|
+
elif isinstance(result, dict) and "id" in result:
|
|
590
|
+
typer.echo(f"Created: {result['id']}")
|
|
591
|
+
elif not result or result == {}:
|
|
592
|
+
typer.echo("Created.")
|
|
593
|
+
else:
|
|
594
|
+
print_json(result)
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
@app.command("update-access-codes")
|
|
599
|
+
def update_access_codes(
|
|
600
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
601
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
602
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
603
|
+
):
|
|
604
|
+
"""Modify Access Codes for a Workspace\n\nExample --json-body:\n '{"deleteCodes":["..."]}'."""
|
|
605
|
+
api = get_api(debug=debug)
|
|
606
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission/accessCodes"
|
|
607
|
+
params = {}
|
|
608
|
+
org_id = get_org_id()
|
|
609
|
+
if org_id is not None:
|
|
610
|
+
params["orgId"] = org_id
|
|
611
|
+
if json_body:
|
|
612
|
+
body = json.loads(json_body)
|
|
613
|
+
else:
|
|
614
|
+
body = {}
|
|
615
|
+
try:
|
|
616
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
617
|
+
except WebexError as e:
|
|
618
|
+
handle_rest_error(e)
|
|
619
|
+
typer.echo(f"Updated.")
|
|
620
|
+
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
@app.command("delete")
|
|
624
|
+
def delete(
|
|
625
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
626
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
627
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
628
|
+
):
|
|
629
|
+
"""Delete all Access Codes for a Workspace."""
|
|
630
|
+
if not force:
|
|
631
|
+
typer.confirm(f"Delete {workspace_id}?", abort=True)
|
|
632
|
+
api = get_api(debug=debug)
|
|
633
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission/accessCodes"
|
|
634
|
+
params = {}
|
|
635
|
+
org_id = get_org_id()
|
|
636
|
+
if org_id is not None:
|
|
637
|
+
params["orgId"] = org_id
|
|
638
|
+
try:
|
|
639
|
+
api.session.rest_delete(url, params=params)
|
|
640
|
+
except WebexError as e:
|
|
641
|
+
handle_rest_error(e)
|
|
642
|
+
typer.echo(f"Deleted: {workspace_id}")
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
|
|
646
|
+
@app.command("show-intercept")
|
|
647
|
+
def show_intercept(
|
|
648
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
649
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
650
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
651
|
+
):
|
|
652
|
+
"""Read Call Intercept Settings for a Workspace."""
|
|
653
|
+
api = get_api(debug=debug)
|
|
654
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/intercept"
|
|
655
|
+
params = {}
|
|
656
|
+
org_id = get_org_id()
|
|
657
|
+
if org_id is not None:
|
|
658
|
+
params["orgId"] = org_id
|
|
659
|
+
try:
|
|
660
|
+
result = api.session.rest_get(url, params=params)
|
|
661
|
+
except WebexError as e:
|
|
662
|
+
handle_rest_error(e)
|
|
663
|
+
if output == "json":
|
|
664
|
+
print_json(result)
|
|
665
|
+
else:
|
|
666
|
+
if isinstance(result, dict):
|
|
667
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
668
|
+
elif isinstance(result, list):
|
|
669
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
670
|
+
else:
|
|
671
|
+
print_json(result)
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
@app.command("update-intercept")
|
|
676
|
+
def update_intercept(
|
|
677
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
678
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if call interception is enabled."),
|
|
679
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
680
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
681
|
+
):
|
|
682
|
+
"""Configure Call Intercept Settings for a Workspace\n\nExample --json-body:\n '{"enabled":true,"incoming":{"type":"INTERCEPT_ALL","voicemailEnabled":true,"announcements":{"greeting":"...","newNumber":"...","zeroTransfer":"..."}},"outgoing":{"type":"INTERCEPT_ALL","transferEnabled":true,"destination":"..."}}'."""
|
|
683
|
+
api = get_api(debug=debug)
|
|
684
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/intercept"
|
|
685
|
+
params = {}
|
|
686
|
+
org_id = get_org_id()
|
|
687
|
+
if org_id is not None:
|
|
688
|
+
params["orgId"] = org_id
|
|
689
|
+
if json_body:
|
|
690
|
+
body = json.loads(json_body)
|
|
691
|
+
else:
|
|
692
|
+
body = {}
|
|
693
|
+
if enabled is not None:
|
|
694
|
+
body["enabled"] = enabled
|
|
695
|
+
try:
|
|
696
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
697
|
+
except WebexError as e:
|
|
698
|
+
handle_rest_error(e)
|
|
699
|
+
typer.echo(f"Updated.")
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
@app.command("show-auto-transfer-numbers")
|
|
704
|
+
def show_auto_transfer_numbers(
|
|
705
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
706
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
707
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
708
|
+
):
|
|
709
|
+
"""Retrieve Transfer Numbers Settings for a Workspace."""
|
|
710
|
+
api = get_api(debug=debug)
|
|
711
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission/autoTransferNumbers"
|
|
712
|
+
params = {}
|
|
713
|
+
org_id = get_org_id()
|
|
714
|
+
if org_id is not None:
|
|
715
|
+
params["orgId"] = org_id
|
|
716
|
+
try:
|
|
717
|
+
result = api.session.rest_get(url, params=params)
|
|
718
|
+
except WebexError as e:
|
|
719
|
+
handle_rest_error(e)
|
|
720
|
+
if output == "json":
|
|
721
|
+
print_json(result)
|
|
722
|
+
else:
|
|
723
|
+
if isinstance(result, dict):
|
|
724
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
725
|
+
elif isinstance(result, list):
|
|
726
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
727
|
+
else:
|
|
728
|
+
print_json(result)
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
@app.command("update-auto-transfer-numbers")
|
|
733
|
+
def update_auto_transfer_numbers(
|
|
734
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
735
|
+
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"),
|
|
736
|
+
auto_transfer_number1: str = typer.Option(None, "--auto-transfer-number1", help="When calling a specific call type, this workspace will be au"),
|
|
737
|
+
auto_transfer_number2: str = typer.Option(None, "--auto-transfer-number2", help="When calling a specific call type, this workspace will be au"),
|
|
738
|
+
auto_transfer_number3: str = typer.Option(None, "--auto-transfer-number3", help="When calling a specific call type, this workspace will be au"),
|
|
739
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
740
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
741
|
+
):
|
|
742
|
+
"""Modify Transfer Numbers Settings for a Workspace."""
|
|
743
|
+
api = get_api(debug=debug)
|
|
744
|
+
url = f"https://webexapis.com/v1/workspaces/{workspace_id}/features/outgoingPermission/autoTransferNumbers"
|
|
745
|
+
params = {}
|
|
746
|
+
org_id = get_org_id()
|
|
747
|
+
if org_id is not None:
|
|
748
|
+
params["orgId"] = org_id
|
|
749
|
+
if json_body:
|
|
750
|
+
body = json.loads(json_body)
|
|
751
|
+
else:
|
|
752
|
+
body = {}
|
|
753
|
+
if use_custom_transfer_numbers is not None:
|
|
754
|
+
body["useCustomTransferNumbers"] = use_custom_transfer_numbers
|
|
755
|
+
if auto_transfer_number1 is not None:
|
|
756
|
+
body["autoTransferNumber1"] = auto_transfer_number1
|
|
757
|
+
if auto_transfer_number2 is not None:
|
|
758
|
+
body["autoTransferNumber2"] = auto_transfer_number2
|
|
759
|
+
if auto_transfer_number3 is not None:
|
|
760
|
+
body["autoTransferNumber3"] = auto_transfer_number3
|
|
761
|
+
try:
|
|
762
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
763
|
+
except WebexError as e:
|
|
764
|
+
handle_rest_error(e)
|
|
765
|
+
typer.echo(f"Updated.")
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
@app.command("show-music-on-hold")
|
|
770
|
+
def show_music_on_hold(
|
|
771
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
772
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
773
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
774
|
+
):
|
|
775
|
+
"""Retrieve Music On Hold Settings for a Workspace."""
|
|
776
|
+
api = get_api(debug=debug)
|
|
777
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/musicOnHold"
|
|
778
|
+
params = {}
|
|
779
|
+
org_id = get_org_id()
|
|
780
|
+
if org_id is not None:
|
|
781
|
+
params["orgId"] = org_id
|
|
782
|
+
try:
|
|
783
|
+
result = api.session.rest_get(url, params=params)
|
|
784
|
+
except WebexError as e:
|
|
785
|
+
handle_rest_error(e)
|
|
786
|
+
if output == "json":
|
|
787
|
+
print_json(result)
|
|
788
|
+
else:
|
|
789
|
+
if isinstance(result, dict):
|
|
790
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
791
|
+
elif isinstance(result, list):
|
|
792
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
793
|
+
else:
|
|
794
|
+
print_json(result)
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
@app.command("update-music-on-hold")
|
|
799
|
+
def update_music_on_hold(
|
|
800
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
801
|
+
moh_enabled: bool = typer.Option(None, "--moh-enabled/--no-moh-enabled", help="Music on hold is enabled or disabled for the workspace."),
|
|
802
|
+
greeting: str = typer.Option(None, "--greeting", help="Choices: DEFAULT, CUSTOM"),
|
|
803
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
804
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
805
|
+
):
|
|
806
|
+
"""Modify Music On Hold Settings for a Workspace\n\nExample --json-body:\n '{"mohEnabled":true,"greeting":"DEFAULT","audioAnnouncementFile":{"id":"...","fileName":"...","mediaFileType":"WAV","level":"ORGANIZATION"}}'."""
|
|
807
|
+
api = get_api(debug=debug)
|
|
808
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/musicOnHold"
|
|
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 moh_enabled is not None:
|
|
818
|
+
body["mohEnabled"] = moh_enabled
|
|
819
|
+
if greeting is not None:
|
|
820
|
+
body["greeting"] = greeting
|
|
821
|
+
try:
|
|
822
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
823
|
+
except WebexError as e:
|
|
824
|
+
handle_rest_error(e)
|
|
825
|
+
typer.echo(f"Updated.")
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
@app.command("delete-access-codes")
|
|
830
|
+
def delete_access_codes(
|
|
831
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
832
|
+
access_code: str = typer.Argument(help="accessCode"),
|
|
833
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
834
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
835
|
+
):
|
|
836
|
+
"""Delete a Specific Access Code for a Workspace."""
|
|
837
|
+
if not force:
|
|
838
|
+
typer.confirm(f"Delete {access_code}?", abort=True)
|
|
839
|
+
api = get_api(debug=debug)
|
|
840
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/features/accessCodes/{access_code}"
|
|
841
|
+
params = {}
|
|
842
|
+
org_id = get_org_id()
|
|
843
|
+
if org_id is not None:
|
|
844
|
+
params["orgId"] = org_id
|
|
845
|
+
try:
|
|
846
|
+
api.session.rest_delete(url, params=params)
|
|
847
|
+
except WebexError as e:
|
|
848
|
+
handle_rest_error(e)
|
|
849
|
+
typer.echo(f"Deleted: {access_code}")
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
@app.command("list-digit-patterns")
|
|
854
|
+
def list_digit_patterns(
|
|
855
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
856
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
857
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
858
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
859
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
860
|
+
):
|
|
861
|
+
"""Retrieve all Digit Patterns for a Workspace."""
|
|
862
|
+
api = get_api(debug=debug)
|
|
863
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns"
|
|
864
|
+
params = {}
|
|
865
|
+
if limit > 0:
|
|
866
|
+
params["max"] = limit
|
|
867
|
+
if offset > 0:
|
|
868
|
+
params["start"] = offset
|
|
869
|
+
org_id = get_org_id()
|
|
870
|
+
if org_id is not None:
|
|
871
|
+
params["orgId"] = org_id
|
|
872
|
+
result = None
|
|
873
|
+
try:
|
|
874
|
+
result = api.session.rest_get(url, params=params)
|
|
875
|
+
except WebexError as e:
|
|
876
|
+
handle_rest_error(e)
|
|
877
|
+
result = result or []
|
|
878
|
+
items = result.get("digitPatterns", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
879
|
+
if output == "json":
|
|
880
|
+
print_json(items)
|
|
881
|
+
else:
|
|
882
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
@app.command("create-digit-patterns")
|
|
887
|
+
def create_digit_patterns(
|
|
888
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
889
|
+
name: str = typer.Option(None, "--name", help="(required) A unique name for the digit pattern."),
|
|
890
|
+
pattern: str = typer.Option(None, "--pattern", help="(required) The digit pattern to be matched with the input number."),
|
|
891
|
+
action: str = typer.Option(None, "--action", help="(required) Choices: ALLOW, BLOCK, AUTH_CODE, TRANSFER_NUMBER_1, TRANSFER_NUMBER_2, TRANSFER_NUMBER_3"),
|
|
892
|
+
transfer_enabled: bool = typer.Option(None, "--transfer-enabled/--no-transfer-enabled", help="(required) If `true`, allows transfer and forwarding for the call type."),
|
|
893
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
894
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
895
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
896
|
+
):
|
|
897
|
+
"""Create Digit Pattern for a Workspace."""
|
|
898
|
+
api = get_api(debug=debug)
|
|
899
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns"
|
|
900
|
+
params = {}
|
|
901
|
+
org_id = get_org_id()
|
|
902
|
+
if org_id is not None:
|
|
903
|
+
params["orgId"] = org_id
|
|
904
|
+
if json_body:
|
|
905
|
+
body = json.loads(json_body)
|
|
906
|
+
else:
|
|
907
|
+
body = {}
|
|
908
|
+
if name is not None:
|
|
909
|
+
body["name"] = name
|
|
910
|
+
if pattern is not None:
|
|
911
|
+
body["pattern"] = pattern
|
|
912
|
+
if action is not None:
|
|
913
|
+
body["action"] = action
|
|
914
|
+
if transfer_enabled is not None:
|
|
915
|
+
body["transferEnabled"] = transfer_enabled
|
|
916
|
+
_missing = [f for f in ['name', 'pattern', 'action', 'transferEnabled'] if f not in body or body[f] is None]
|
|
917
|
+
if _missing:
|
|
918
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
919
|
+
raise typer.Exit(1)
|
|
920
|
+
try:
|
|
921
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
922
|
+
except WebexError as e:
|
|
923
|
+
handle_rest_error(e)
|
|
924
|
+
if output == "json":
|
|
925
|
+
print_json(result)
|
|
926
|
+
elif isinstance(result, dict) and "id" in result:
|
|
927
|
+
typer.echo(f"Created: {result['id']}")
|
|
928
|
+
elif not result or result == {}:
|
|
929
|
+
typer.echo("Created.")
|
|
930
|
+
else:
|
|
931
|
+
print_json(result)
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
@app.command("update-digit-patterns-outgoing-permission")
|
|
936
|
+
def update_digit_patterns_outgoing_permission(
|
|
937
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
938
|
+
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"),
|
|
939
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
940
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
941
|
+
):
|
|
942
|
+
"""Modify the Digit Pattern Category Control Settings for the Workspace."""
|
|
943
|
+
api = get_api(debug=debug)
|
|
944
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns"
|
|
945
|
+
params = {}
|
|
946
|
+
org_id = get_org_id()
|
|
947
|
+
if org_id is not None:
|
|
948
|
+
params["orgId"] = org_id
|
|
949
|
+
if json_body:
|
|
950
|
+
body = json.loads(json_body)
|
|
951
|
+
else:
|
|
952
|
+
body = {}
|
|
953
|
+
if use_custom_digit_patterns is not None:
|
|
954
|
+
body["useCustomDigitPatterns"] = use_custom_digit_patterns
|
|
955
|
+
try:
|
|
956
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
957
|
+
except WebexError as e:
|
|
958
|
+
handle_rest_error(e)
|
|
959
|
+
typer.echo(f"Updated.")
|
|
960
|
+
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
@app.command("delete-digit-patterns-outgoing-permission")
|
|
964
|
+
def delete_digit_patterns_outgoing_permission(
|
|
965
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
966
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
967
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
968
|
+
):
|
|
969
|
+
"""Delete all Digit Patterns for a Workspace."""
|
|
970
|
+
if not force:
|
|
971
|
+
typer.confirm(f"Delete {workspace_id}?", abort=True)
|
|
972
|
+
api = get_api(debug=debug)
|
|
973
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns"
|
|
974
|
+
params = {}
|
|
975
|
+
org_id = get_org_id()
|
|
976
|
+
if org_id is not None:
|
|
977
|
+
params["orgId"] = org_id
|
|
978
|
+
try:
|
|
979
|
+
api.session.rest_delete(url, params=params)
|
|
980
|
+
except WebexError as e:
|
|
981
|
+
handle_rest_error(e)
|
|
982
|
+
typer.echo(f"Deleted: {workspace_id}")
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
@app.command("show-digit-patterns")
|
|
987
|
+
def show_digit_patterns(
|
|
988
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
989
|
+
digit_pattern_id: str = typer.Argument(help="digitPatternId"),
|
|
990
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
991
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
992
|
+
):
|
|
993
|
+
"""Retrieve a Digit Pattern details for the Workspace."""
|
|
994
|
+
api = get_api(debug=debug)
|
|
995
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns/{digit_pattern_id}"
|
|
996
|
+
params = {}
|
|
997
|
+
org_id = get_org_id()
|
|
998
|
+
if org_id is not None:
|
|
999
|
+
params["orgId"] = org_id
|
|
1000
|
+
try:
|
|
1001
|
+
result = api.session.rest_get(url, params=params)
|
|
1002
|
+
except WebexError as e:
|
|
1003
|
+
handle_rest_error(e)
|
|
1004
|
+
if output == "json":
|
|
1005
|
+
print_json(result)
|
|
1006
|
+
else:
|
|
1007
|
+
if isinstance(result, dict):
|
|
1008
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1009
|
+
elif isinstance(result, list):
|
|
1010
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1011
|
+
else:
|
|
1012
|
+
print_json(result)
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
@app.command("update-digit-patterns-outgoing-permission-1")
|
|
1017
|
+
def update_digit_patterns_outgoing_permission_1(
|
|
1018
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1019
|
+
digit_pattern_id: str = typer.Argument(help="digitPatternId"),
|
|
1020
|
+
name: str = typer.Option(None, "--name", help="A unique name for the digit pattern."),
|
|
1021
|
+
pattern: str = typer.Option(None, "--pattern", help="The digit pattern to be matched with the input number."),
|
|
1022
|
+
action: str = typer.Option(None, "--action", help="Choices: ALLOW, BLOCK, AUTH_CODE, TRANSFER_NUMBER_1, TRANSFER_NUMBER_2, TRANSFER_NUMBER_3"),
|
|
1023
|
+
transfer_enabled: bool = typer.Option(None, "--transfer-enabled/--no-transfer-enabled", help="If `true`, allows transfer and forwarding for the call type."),
|
|
1024
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1025
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1026
|
+
):
|
|
1027
|
+
"""Modify a Digit Pattern for the Workspace."""
|
|
1028
|
+
api = get_api(debug=debug)
|
|
1029
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns/{digit_pattern_id}"
|
|
1030
|
+
params = {}
|
|
1031
|
+
org_id = get_org_id()
|
|
1032
|
+
if org_id is not None:
|
|
1033
|
+
params["orgId"] = org_id
|
|
1034
|
+
if json_body:
|
|
1035
|
+
body = json.loads(json_body)
|
|
1036
|
+
else:
|
|
1037
|
+
body = {}
|
|
1038
|
+
if name is not None:
|
|
1039
|
+
body["name"] = name
|
|
1040
|
+
if pattern is not None:
|
|
1041
|
+
body["pattern"] = pattern
|
|
1042
|
+
if action is not None:
|
|
1043
|
+
body["action"] = action
|
|
1044
|
+
if transfer_enabled is not None:
|
|
1045
|
+
body["transferEnabled"] = transfer_enabled
|
|
1046
|
+
try:
|
|
1047
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1048
|
+
except WebexError as e:
|
|
1049
|
+
handle_rest_error(e)
|
|
1050
|
+
typer.echo(f"Updated.")
|
|
1051
|
+
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
@app.command("delete-digit-patterns-outgoing-permission-1")
|
|
1055
|
+
def delete_digit_patterns_outgoing_permission_1(
|
|
1056
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1057
|
+
digit_pattern_id: str = typer.Argument(help="digitPatternId"),
|
|
1058
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1059
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1060
|
+
):
|
|
1061
|
+
"""Delete a Digit Pattern for the Workspace."""
|
|
1062
|
+
if not force:
|
|
1063
|
+
typer.confirm(f"Delete {digit_pattern_id}?", abort=True)
|
|
1064
|
+
api = get_api(debug=debug)
|
|
1065
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/outgoingPermission/digitPatterns/{digit_pattern_id}"
|
|
1066
|
+
params = {}
|
|
1067
|
+
org_id = get_org_id()
|
|
1068
|
+
if org_id is not None:
|
|
1069
|
+
params["orgId"] = org_id
|
|
1070
|
+
try:
|
|
1071
|
+
api.session.rest_delete(url, params=params)
|
|
1072
|
+
except WebexError as e:
|
|
1073
|
+
handle_rest_error(e)
|
|
1074
|
+
typer.echo(f"Deleted: {digit_pattern_id}")
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
@app.command("upload-call-intercept")
|
|
1079
|
+
def upload_call_intercept(
|
|
1080
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1081
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1082
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1083
|
+
):
|
|
1084
|
+
"""Upload Call Intercept Announcement file for a Workspace."""
|
|
1085
|
+
api = get_api(debug=debug)
|
|
1086
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/features/intercept/actions/announcementUpload/invoke"
|
|
1087
|
+
params = {}
|
|
1088
|
+
org_id = get_org_id()
|
|
1089
|
+
if org_id is not None:
|
|
1090
|
+
params["orgId"] = org_id
|
|
1091
|
+
if json_body:
|
|
1092
|
+
body = json.loads(json_body)
|
|
1093
|
+
else:
|
|
1094
|
+
body = {}
|
|
1095
|
+
try:
|
|
1096
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1097
|
+
except WebexError as e:
|
|
1098
|
+
handle_rest_error(e)
|
|
1099
|
+
print_json(result)
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
@app.command("show-call-recordings")
|
|
1104
|
+
def show_call_recordings(
|
|
1105
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1106
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1107
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1108
|
+
):
|
|
1109
|
+
"""Retrieve Call Recording Settings for a Workspace."""
|
|
1110
|
+
api = get_api(debug=debug)
|
|
1111
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/features/callRecordings"
|
|
1112
|
+
params = {}
|
|
1113
|
+
org_id = get_org_id()
|
|
1114
|
+
if org_id is not None:
|
|
1115
|
+
params["orgId"] = org_id
|
|
1116
|
+
try:
|
|
1117
|
+
result = api.session.rest_get(url, params=params)
|
|
1118
|
+
except WebexError as e:
|
|
1119
|
+
handle_rest_error(e)
|
|
1120
|
+
if output == "json":
|
|
1121
|
+
print_json(result)
|
|
1122
|
+
else:
|
|
1123
|
+
if isinstance(result, dict):
|
|
1124
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1125
|
+
elif isinstance(result, list):
|
|
1126
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1127
|
+
else:
|
|
1128
|
+
print_json(result)
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@app.command("update-call-recordings")
|
|
1133
|
+
def update_call_recordings(
|
|
1134
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1135
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if call recording is enabled."),
|
|
1136
|
+
record: str = typer.Option(None, "--record", help="Choices: Always, Never, Always with Pause/Resume, On Demand with User Initiated Start"),
|
|
1137
|
+
record_voicemail_enabled: bool = typer.Option(None, "--record-voicemail-enabled/--no-record-voicemail-enabled", help="When `true`, voicemail messages are also recorded."),
|
|
1138
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1139
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1140
|
+
):
|
|
1141
|
+
"""Modify Call Recording Settings for a Workspace\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}}'."""
|
|
1142
|
+
api = get_api(debug=debug)
|
|
1143
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/features/callRecordings"
|
|
1144
|
+
params = {}
|
|
1145
|
+
org_id = get_org_id()
|
|
1146
|
+
if org_id is not None:
|
|
1147
|
+
params["orgId"] = org_id
|
|
1148
|
+
if json_body:
|
|
1149
|
+
body = json.loads(json_body)
|
|
1150
|
+
else:
|
|
1151
|
+
body = {}
|
|
1152
|
+
if enabled is not None:
|
|
1153
|
+
body["enabled"] = enabled
|
|
1154
|
+
if record is not None:
|
|
1155
|
+
body["record"] = record
|
|
1156
|
+
if record_voicemail_enabled is not None:
|
|
1157
|
+
body["recordVoicemailEnabled"] = record_voicemail_enabled
|
|
1158
|
+
try:
|
|
1159
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1160
|
+
except WebexError as e:
|
|
1161
|
+
handle_rest_error(e)
|
|
1162
|
+
typer.echo(f"Updated.")
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
@app.command("list-available-numbers-workspaces")
|
|
1167
|
+
def list_available_numbers_workspaces(
|
|
1168
|
+
location_id: str = typer.Option(None, "--location-id", help="Return the list of phone numbers for this location within th"),
|
|
1169
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1170
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1171
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1172
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1173
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1174
|
+
):
|
|
1175
|
+
"""Get Workspace Available Phone Numbers."""
|
|
1176
|
+
api = get_api(debug=debug)
|
|
1177
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/availableNumbers"
|
|
1178
|
+
params = {}
|
|
1179
|
+
if location_id is not None:
|
|
1180
|
+
params["locationId"] = location_id
|
|
1181
|
+
if phone_number is not None:
|
|
1182
|
+
params["phoneNumber"] = phone_number
|
|
1183
|
+
if limit > 0:
|
|
1184
|
+
params["max"] = limit
|
|
1185
|
+
if offset > 0:
|
|
1186
|
+
params["start"] = offset
|
|
1187
|
+
org_id = get_org_id()
|
|
1188
|
+
if org_id is not None:
|
|
1189
|
+
params["orgId"] = org_id
|
|
1190
|
+
result = None
|
|
1191
|
+
try:
|
|
1192
|
+
result = api.session.rest_get(url, params=params)
|
|
1193
|
+
except WebexError as e:
|
|
1194
|
+
handle_rest_error(e)
|
|
1195
|
+
result = result or []
|
|
1196
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1197
|
+
if output == "json":
|
|
1198
|
+
print_json(items)
|
|
1199
|
+
else:
|
|
1200
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
|
|
1204
|
+
@app.command("list-available-numbers-emergency-callback-number")
|
|
1205
|
+
def list_available_numbers_emergency_callback_number(
|
|
1206
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1207
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1208
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
1209
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1210
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1211
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1212
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1213
|
+
):
|
|
1214
|
+
"""Get Workspace ECBN Available Phone Numbers."""
|
|
1215
|
+
api = get_api(debug=debug)
|
|
1216
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/emergencyCallbackNumber/availableNumbers"
|
|
1217
|
+
params = {}
|
|
1218
|
+
if phone_number is not None:
|
|
1219
|
+
params["phoneNumber"] = phone_number
|
|
1220
|
+
if owner_name is not None:
|
|
1221
|
+
params["ownerName"] = owner_name
|
|
1222
|
+
if limit > 0:
|
|
1223
|
+
params["max"] = limit
|
|
1224
|
+
if offset > 0:
|
|
1225
|
+
params["start"] = offset
|
|
1226
|
+
org_id = get_org_id()
|
|
1227
|
+
if org_id is not None:
|
|
1228
|
+
params["orgId"] = org_id
|
|
1229
|
+
result = None
|
|
1230
|
+
try:
|
|
1231
|
+
result = api.session.rest_get(url, params=params)
|
|
1232
|
+
except WebexError as e:
|
|
1233
|
+
handle_rest_error(e)
|
|
1234
|
+
result = result or []
|
|
1235
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1236
|
+
if output == "json":
|
|
1237
|
+
print_json(items)
|
|
1238
|
+
else:
|
|
1239
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1240
|
+
|
|
1241
|
+
|
|
1242
|
+
|
|
1243
|
+
@app.command("list-available-numbers-call-forwarding")
|
|
1244
|
+
def list_available_numbers_call_forwarding(
|
|
1245
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1246
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1247
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
1248
|
+
extension: str = typer.Option(None, "--extension", help="Returns the list of PSTN phone numbers with the given `exten"),
|
|
1249
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1250
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1251
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1252
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1253
|
+
):
|
|
1254
|
+
"""Get Workspace Call Forward Available Phone Numbers."""
|
|
1255
|
+
api = get_api(debug=debug)
|
|
1256
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/callForwarding/availableNumbers"
|
|
1257
|
+
params = {}
|
|
1258
|
+
if phone_number is not None:
|
|
1259
|
+
params["phoneNumber"] = phone_number
|
|
1260
|
+
if owner_name is not None:
|
|
1261
|
+
params["ownerName"] = owner_name
|
|
1262
|
+
if extension is not None:
|
|
1263
|
+
params["extension"] = extension
|
|
1264
|
+
if limit > 0:
|
|
1265
|
+
params["max"] = limit
|
|
1266
|
+
if offset > 0:
|
|
1267
|
+
params["start"] = offset
|
|
1268
|
+
org_id = get_org_id()
|
|
1269
|
+
if org_id is not None:
|
|
1270
|
+
params["orgId"] = org_id
|
|
1271
|
+
result = None
|
|
1272
|
+
try:
|
|
1273
|
+
result = api.session.rest_get(url, params=params)
|
|
1274
|
+
except WebexError as e:
|
|
1275
|
+
handle_rest_error(e)
|
|
1276
|
+
result = result or []
|
|
1277
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1278
|
+
if output == "json":
|
|
1279
|
+
print_json(items)
|
|
1280
|
+
else:
|
|
1281
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
@app.command("list-available-numbers-call-intercept")
|
|
1286
|
+
def list_available_numbers_call_intercept(
|
|
1287
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1288
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
1289
|
+
owner_name: str = typer.Option(None, "--owner-name", help="Return the list of phone numbers that are owned by the given"),
|
|
1290
|
+
extension: str = typer.Option(None, "--extension", help="Returns the list of PSTN phone numbers with the given `exten"),
|
|
1291
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1292
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1293
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1294
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1295
|
+
):
|
|
1296
|
+
"""Get Workspace Call Intercept Available Phone Numbers."""
|
|
1297
|
+
api = get_api(debug=debug)
|
|
1298
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/callIntercept/availableNumbers"
|
|
1299
|
+
params = {}
|
|
1300
|
+
if phone_number is not None:
|
|
1301
|
+
params["phoneNumber"] = phone_number
|
|
1302
|
+
if owner_name is not None:
|
|
1303
|
+
params["ownerName"] = owner_name
|
|
1304
|
+
if extension is not None:
|
|
1305
|
+
params["extension"] = extension
|
|
1306
|
+
if limit > 0:
|
|
1307
|
+
params["max"] = limit
|
|
1308
|
+
if offset > 0:
|
|
1309
|
+
params["start"] = offset
|
|
1310
|
+
org_id = get_org_id()
|
|
1311
|
+
if org_id is not None:
|
|
1312
|
+
params["orgId"] = org_id
|
|
1313
|
+
result = None
|
|
1314
|
+
try:
|
|
1315
|
+
result = api.session.rest_get(url, params=params)
|
|
1316
|
+
except WebexError as e:
|
|
1317
|
+
handle_rest_error(e)
|
|
1318
|
+
result = result or []
|
|
1319
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1320
|
+
if output == "json":
|
|
1321
|
+
print_json(items)
|
|
1322
|
+
else:
|
|
1323
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
@app.command("show-anonymous-call-reject")
|
|
1328
|
+
def show_anonymous_call_reject(
|
|
1329
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1330
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1331
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1332
|
+
):
|
|
1333
|
+
"""Retrieve Anonymous Call Settings for a Workspace."""
|
|
1334
|
+
api = get_api(debug=debug)
|
|
1335
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/anonymousCallReject"
|
|
1336
|
+
params = {}
|
|
1337
|
+
org_id = get_org_id()
|
|
1338
|
+
if org_id is not None:
|
|
1339
|
+
params["orgId"] = org_id
|
|
1340
|
+
try:
|
|
1341
|
+
result = api.session.rest_get(url, params=params)
|
|
1342
|
+
except WebexError as e:
|
|
1343
|
+
handle_rest_error(e)
|
|
1344
|
+
if output == "json":
|
|
1345
|
+
print_json(result)
|
|
1346
|
+
else:
|
|
1347
|
+
if isinstance(result, dict):
|
|
1348
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1349
|
+
elif isinstance(result, list):
|
|
1350
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1351
|
+
else:
|
|
1352
|
+
print_json(result)
|
|
1353
|
+
|
|
1354
|
+
|
|
1355
|
+
|
|
1356
|
+
@app.command("update-anonymous-call-reject")
|
|
1357
|
+
def update_anonymous_call_reject(
|
|
1358
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1359
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Anonymous Call Rejection feature is enabled."),
|
|
1360
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1361
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1362
|
+
):
|
|
1363
|
+
"""Modify Anonymous Call Settings for a Workspace."""
|
|
1364
|
+
api = get_api(debug=debug)
|
|
1365
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/anonymousCallReject"
|
|
1366
|
+
params = {}
|
|
1367
|
+
org_id = get_org_id()
|
|
1368
|
+
if org_id is not None:
|
|
1369
|
+
params["orgId"] = org_id
|
|
1370
|
+
if json_body:
|
|
1371
|
+
body = json.loads(json_body)
|
|
1372
|
+
else:
|
|
1373
|
+
body = {}
|
|
1374
|
+
if enabled is not None:
|
|
1375
|
+
body["enabled"] = enabled
|
|
1376
|
+
try:
|
|
1377
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1378
|
+
except WebexError as e:
|
|
1379
|
+
handle_rest_error(e)
|
|
1380
|
+
typer.echo(f"Updated.")
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
|
|
1384
|
+
@app.command("show-barge-in")
|
|
1385
|
+
def show_barge_in(
|
|
1386
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1387
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1388
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1389
|
+
):
|
|
1390
|
+
"""Retrieve Barge In Call Settings for a Workspace."""
|
|
1391
|
+
api = get_api(debug=debug)
|
|
1392
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/bargeIn"
|
|
1393
|
+
params = {}
|
|
1394
|
+
org_id = get_org_id()
|
|
1395
|
+
if org_id is not None:
|
|
1396
|
+
params["orgId"] = org_id
|
|
1397
|
+
try:
|
|
1398
|
+
result = api.session.rest_get(url, params=params)
|
|
1399
|
+
except WebexError as e:
|
|
1400
|
+
handle_rest_error(e)
|
|
1401
|
+
if output == "json":
|
|
1402
|
+
print_json(result)
|
|
1403
|
+
else:
|
|
1404
|
+
if isinstance(result, dict):
|
|
1405
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1406
|
+
elif isinstance(result, list):
|
|
1407
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1408
|
+
else:
|
|
1409
|
+
print_json(result)
|
|
1410
|
+
|
|
1411
|
+
|
|
1412
|
+
|
|
1413
|
+
@app.command("update-barge-in")
|
|
1414
|
+
def update_barge_in(
|
|
1415
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1416
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Barge In feature is enabled."),
|
|
1417
|
+
tone_enabled: bool = typer.Option(None, "--tone-enabled/--no-tone-enabled", help="When `true`, a tone is played when someone barges into a cal"),
|
|
1418
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1419
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1420
|
+
):
|
|
1421
|
+
"""Modify Barge In Call Settings for a Workspace."""
|
|
1422
|
+
api = get_api(debug=debug)
|
|
1423
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/bargeIn"
|
|
1424
|
+
params = {}
|
|
1425
|
+
org_id = get_org_id()
|
|
1426
|
+
if org_id is not None:
|
|
1427
|
+
params["orgId"] = org_id
|
|
1428
|
+
if json_body:
|
|
1429
|
+
body = json.loads(json_body)
|
|
1430
|
+
else:
|
|
1431
|
+
body = {}
|
|
1432
|
+
if enabled is not None:
|
|
1433
|
+
body["enabled"] = enabled
|
|
1434
|
+
if tone_enabled is not None:
|
|
1435
|
+
body["toneEnabled"] = tone_enabled
|
|
1436
|
+
try:
|
|
1437
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1438
|
+
except WebexError as e:
|
|
1439
|
+
handle_rest_error(e)
|
|
1440
|
+
typer.echo(f"Updated.")
|
|
1441
|
+
|
|
1442
|
+
|
|
1443
|
+
|
|
1444
|
+
@app.command("show-do-not-disturb")
|
|
1445
|
+
def show_do_not_disturb(
|
|
1446
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1447
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1448
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1449
|
+
):
|
|
1450
|
+
"""Retrieve DoNotDisturb Settings for a Workspace."""
|
|
1451
|
+
api = get_api(debug=debug)
|
|
1452
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/doNotDisturb"
|
|
1453
|
+
params = {}
|
|
1454
|
+
org_id = get_org_id()
|
|
1455
|
+
if org_id is not None:
|
|
1456
|
+
params["orgId"] = org_id
|
|
1457
|
+
try:
|
|
1458
|
+
result = api.session.rest_get(url, params=params)
|
|
1459
|
+
except WebexError as e:
|
|
1460
|
+
handle_rest_error(e)
|
|
1461
|
+
if output == "json":
|
|
1462
|
+
print_json(result)
|
|
1463
|
+
else:
|
|
1464
|
+
if isinstance(result, dict):
|
|
1465
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1466
|
+
elif isinstance(result, list):
|
|
1467
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1468
|
+
else:
|
|
1469
|
+
print_json(result)
|
|
1470
|
+
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
@app.command("update-do-not-disturb")
|
|
1474
|
+
def update_do_not_disturb(
|
|
1475
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1476
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the DoNotDisturb feature is enabled."),
|
|
1477
|
+
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"),
|
|
1478
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1479
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1480
|
+
):
|
|
1481
|
+
"""Modify DoNotDisturb Settings for a Workspace."""
|
|
1482
|
+
api = get_api(debug=debug)
|
|
1483
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/doNotDisturb"
|
|
1484
|
+
params = {}
|
|
1485
|
+
org_id = get_org_id()
|
|
1486
|
+
if org_id is not None:
|
|
1487
|
+
params["orgId"] = org_id
|
|
1488
|
+
if json_body:
|
|
1489
|
+
body = json.loads(json_body)
|
|
1490
|
+
else:
|
|
1491
|
+
body = {}
|
|
1492
|
+
if enabled is not None:
|
|
1493
|
+
body["enabled"] = enabled
|
|
1494
|
+
if ring_splash_enabled is not None:
|
|
1495
|
+
body["ringSplashEnabled"] = ring_splash_enabled
|
|
1496
|
+
try:
|
|
1497
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1498
|
+
except WebexError as e:
|
|
1499
|
+
handle_rest_error(e)
|
|
1500
|
+
typer.echo(f"Updated.")
|
|
1501
|
+
|
|
1502
|
+
|
|
1503
|
+
|
|
1504
|
+
@app.command("show-call-bridge")
|
|
1505
|
+
def show_call_bridge(
|
|
1506
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1507
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1508
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1509
|
+
):
|
|
1510
|
+
"""Retrieve Call Bridge Warning Tone Settings for a Workspace."""
|
|
1511
|
+
api = get_api(debug=debug)
|
|
1512
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/callBridge"
|
|
1513
|
+
params = {}
|
|
1514
|
+
org_id = get_org_id()
|
|
1515
|
+
if org_id is not None:
|
|
1516
|
+
params["orgId"] = org_id
|
|
1517
|
+
try:
|
|
1518
|
+
result = api.session.rest_get(url, params=params)
|
|
1519
|
+
except WebexError as e:
|
|
1520
|
+
handle_rest_error(e)
|
|
1521
|
+
if output == "json":
|
|
1522
|
+
print_json(result)
|
|
1523
|
+
else:
|
|
1524
|
+
if isinstance(result, dict):
|
|
1525
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1526
|
+
elif isinstance(result, list):
|
|
1527
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1528
|
+
else:
|
|
1529
|
+
print_json(result)
|
|
1530
|
+
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
@app.command("update-call-bridge")
|
|
1534
|
+
def update_call_bridge(
|
|
1535
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1536
|
+
warning_tone_enabled: bool = typer.Option(None, "--warning-tone-enabled/--no-warning-tone-enabled", help="`true` if the Call Bridge Warning Tone feature is enabled."),
|
|
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
|
+
"""Modify Call Bridge Warning Tone Settings for a Workspace."""
|
|
1541
|
+
api = get_api(debug=debug)
|
|
1542
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/callBridge"
|
|
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 warning_tone_enabled is not None:
|
|
1552
|
+
body["warningToneEnabled"] = warning_tone_enabled
|
|
1553
|
+
try:
|
|
1554
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1555
|
+
except WebexError as e:
|
|
1556
|
+
handle_rest_error(e)
|
|
1557
|
+
typer.echo(f"Updated.")
|
|
1558
|
+
|
|
1559
|
+
|
|
1560
|
+
|
|
1561
|
+
@app.command("list-push-to-talk")
|
|
1562
|
+
def list_push_to_talk(
|
|
1563
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1564
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1565
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1566
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1567
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1568
|
+
):
|
|
1569
|
+
"""Read Push-to-Talk Settings for a Workspace."""
|
|
1570
|
+
api = get_api(debug=debug)
|
|
1571
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/pushToTalk"
|
|
1572
|
+
params = {}
|
|
1573
|
+
if limit > 0:
|
|
1574
|
+
params["max"] = limit
|
|
1575
|
+
if offset > 0:
|
|
1576
|
+
params["start"] = offset
|
|
1577
|
+
org_id = get_org_id()
|
|
1578
|
+
if org_id is not None:
|
|
1579
|
+
params["orgId"] = org_id
|
|
1580
|
+
result = None
|
|
1581
|
+
try:
|
|
1582
|
+
result = api.session.rest_get(url, params=params)
|
|
1583
|
+
except WebexError as e:
|
|
1584
|
+
handle_rest_error(e)
|
|
1585
|
+
result = result or []
|
|
1586
|
+
items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1587
|
+
if output == "json":
|
|
1588
|
+
print_json(items)
|
|
1589
|
+
else:
|
|
1590
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
@app.command("update-push-to-talk")
|
|
1595
|
+
def update_push_to_talk(
|
|
1596
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1597
|
+
allow_auto_answer: bool = typer.Option(None, "--allow-auto-answer/--no-allow-auto-answer", help="`true` if Push-to-Talk feature is enabled."),
|
|
1598
|
+
connection_type: str = typer.Option(None, "--connection-type", help="Choices: ONE_WAY, TWO_WAY"),
|
|
1599
|
+
access_type: str = typer.Option(None, "--access-type", help="Choices: ALLOW_MEMBERS, BLOCK_MEMBERS"),
|
|
1600
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1601
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1602
|
+
):
|
|
1603
|
+
"""Configure Push-to-Talk Settings for a Workspace\n\nExample --json-body:\n '{"allowAutoAnswer":true,"connectionType":"ONE_WAY","accessType":"ALLOW_MEMBERS","members":["..."]}'."""
|
|
1604
|
+
api = get_api(debug=debug)
|
|
1605
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/pushToTalk"
|
|
1606
|
+
params = {}
|
|
1607
|
+
org_id = get_org_id()
|
|
1608
|
+
if org_id is not None:
|
|
1609
|
+
params["orgId"] = org_id
|
|
1610
|
+
if json_body:
|
|
1611
|
+
body = json.loads(json_body)
|
|
1612
|
+
else:
|
|
1613
|
+
body = {}
|
|
1614
|
+
if allow_auto_answer is not None:
|
|
1615
|
+
body["allowAutoAnswer"] = allow_auto_answer
|
|
1616
|
+
if connection_type is not None:
|
|
1617
|
+
body["connectionType"] = connection_type
|
|
1618
|
+
if access_type is not None:
|
|
1619
|
+
body["accessType"] = access_type
|
|
1620
|
+
try:
|
|
1621
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1622
|
+
except WebexError as e:
|
|
1623
|
+
handle_rest_error(e)
|
|
1624
|
+
typer.echo(f"Updated.")
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
@app.command("list-privacy")
|
|
1629
|
+
def list_privacy(
|
|
1630
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1631
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1632
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1633
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1634
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1635
|
+
):
|
|
1636
|
+
"""Retrieve Privacy Settings for a Workspace."""
|
|
1637
|
+
api = get_api(debug=debug)
|
|
1638
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/privacy"
|
|
1639
|
+
params = {}
|
|
1640
|
+
if limit > 0:
|
|
1641
|
+
params["max"] = limit
|
|
1642
|
+
if offset > 0:
|
|
1643
|
+
params["start"] = offset
|
|
1644
|
+
org_id = get_org_id()
|
|
1645
|
+
if org_id is not None:
|
|
1646
|
+
params["orgId"] = org_id
|
|
1647
|
+
result = None
|
|
1648
|
+
try:
|
|
1649
|
+
result = api.session.rest_get(url, params=params)
|
|
1650
|
+
except WebexError as e:
|
|
1651
|
+
handle_rest_error(e)
|
|
1652
|
+
result = result or []
|
|
1653
|
+
items = result.get("monitoringAgents", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1654
|
+
if output == "json":
|
|
1655
|
+
print_json(items)
|
|
1656
|
+
else:
|
|
1657
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1658
|
+
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
@app.command("update-privacy")
|
|
1662
|
+
def update_privacy(
|
|
1663
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1664
|
+
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."),
|
|
1665
|
+
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"),
|
|
1666
|
+
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."),
|
|
1667
|
+
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"),
|
|
1668
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1669
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1670
|
+
):
|
|
1671
|
+
"""Modify Privacy Settings for a Workspace\n\nExample --json-body:\n '{"aaExtensionDialingEnabled":true,"aaNamingDialingEnabled":true,"enablePhoneStatusDirectoryPrivacy":true,"enablePhoneStatusPickupBargeInPrivacy":true,"monitoringAgents":["..."]}'."""
|
|
1672
|
+
api = get_api(debug=debug)
|
|
1673
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/privacy"
|
|
1674
|
+
params = {}
|
|
1675
|
+
org_id = get_org_id()
|
|
1676
|
+
if org_id is not None:
|
|
1677
|
+
params["orgId"] = org_id
|
|
1678
|
+
if json_body:
|
|
1679
|
+
body = json.loads(json_body)
|
|
1680
|
+
else:
|
|
1681
|
+
body = {}
|
|
1682
|
+
if aa_extension_dialing_enabled is not None:
|
|
1683
|
+
body["aaExtensionDialingEnabled"] = aa_extension_dialing_enabled
|
|
1684
|
+
if aa_naming_dialing_enabled is not None:
|
|
1685
|
+
body["aaNamingDialingEnabled"] = aa_naming_dialing_enabled
|
|
1686
|
+
if enable_phone_status_directory_privacy is not None:
|
|
1687
|
+
body["enablePhoneStatusDirectoryPrivacy"] = enable_phone_status_directory_privacy
|
|
1688
|
+
if enable_phone_status_pickup_barge_in_privacy is not None:
|
|
1689
|
+
body["enablePhoneStatusPickupBargeInPrivacy"] = enable_phone_status_pickup_barge_in_privacy
|
|
1690
|
+
try:
|
|
1691
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1692
|
+
except WebexError as e:
|
|
1693
|
+
handle_rest_error(e)
|
|
1694
|
+
typer.echo(f"Updated.")
|
|
1695
|
+
|
|
1696
|
+
|
|
1697
|
+
|
|
1698
|
+
@app.command("show-voicemail")
|
|
1699
|
+
def show_voicemail(
|
|
1700
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1701
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1702
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1703
|
+
):
|
|
1704
|
+
"""Read Voicemail Settings for a Workspace."""
|
|
1705
|
+
api = get_api(debug=debug)
|
|
1706
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/voicemail"
|
|
1707
|
+
params = {}
|
|
1708
|
+
org_id = get_org_id()
|
|
1709
|
+
if org_id is not None:
|
|
1710
|
+
params["orgId"] = org_id
|
|
1711
|
+
try:
|
|
1712
|
+
result = api.session.rest_get(url, params=params)
|
|
1713
|
+
except WebexError as e:
|
|
1714
|
+
handle_rest_error(e)
|
|
1715
|
+
if output == "json":
|
|
1716
|
+
print_json(result)
|
|
1717
|
+
else:
|
|
1718
|
+
if isinstance(result, dict):
|
|
1719
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1720
|
+
elif isinstance(result, list):
|
|
1721
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1722
|
+
else:
|
|
1723
|
+
print_json(result)
|
|
1724
|
+
|
|
1725
|
+
|
|
1726
|
+
|
|
1727
|
+
@app.command("update-voicemail")
|
|
1728
|
+
def update_voicemail(
|
|
1729
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1730
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Voicemail is enabled or disabled."),
|
|
1731
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1732
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1733
|
+
):
|
|
1734
|
+
"""Configure Voicemail Settings for a Workspace\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":"..."}}'."""
|
|
1735
|
+
api = get_api(debug=debug)
|
|
1736
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/voicemail"
|
|
1737
|
+
params = {}
|
|
1738
|
+
org_id = get_org_id()
|
|
1739
|
+
if org_id is not None:
|
|
1740
|
+
params["orgId"] = org_id
|
|
1741
|
+
if json_body:
|
|
1742
|
+
body = json.loads(json_body)
|
|
1743
|
+
else:
|
|
1744
|
+
body = {}
|
|
1745
|
+
if enabled is not None:
|
|
1746
|
+
body["enabled"] = enabled
|
|
1747
|
+
try:
|
|
1748
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1749
|
+
except WebexError as e:
|
|
1750
|
+
handle_rest_error(e)
|
|
1751
|
+
typer.echo(f"Updated.")
|
|
1752
|
+
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
@app.command("update-passcode")
|
|
1756
|
+
def update_passcode(
|
|
1757
|
+
place_id: str = typer.Argument(help="placeId"),
|
|
1758
|
+
passcode: str = typer.Option(None, "--passcode", help="Voicemail access passcode. The minimum length of the passcod"),
|
|
1759
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1760
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1761
|
+
):
|
|
1762
|
+
"""Modify Voicemail Passcode for a Workspace."""
|
|
1763
|
+
api = get_api(debug=debug)
|
|
1764
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{place_id}/voicemail/passcode"
|
|
1765
|
+
params = {}
|
|
1766
|
+
org_id = get_org_id()
|
|
1767
|
+
if org_id is not None:
|
|
1768
|
+
params["orgId"] = org_id
|
|
1769
|
+
if json_body:
|
|
1770
|
+
body = json.loads(json_body)
|
|
1771
|
+
else:
|
|
1772
|
+
body = {}
|
|
1773
|
+
if passcode is not None:
|
|
1774
|
+
body["passcode"] = passcode
|
|
1775
|
+
try:
|
|
1776
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1777
|
+
except WebexError as e:
|
|
1778
|
+
handle_rest_error(e)
|
|
1779
|
+
typer.echo(f"Updated.")
|
|
1780
|
+
|
|
1781
|
+
|
|
1782
|
+
|
|
1783
|
+
@app.command("show-criteria-sequential-ring")
|
|
1784
|
+
def show_criteria_sequential_ring(
|
|
1785
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1786
|
+
id: str = typer.Argument(help="id"),
|
|
1787
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1788
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1789
|
+
):
|
|
1790
|
+
"""Retrieve Sequential Ring Criteria for a Workspace."""
|
|
1791
|
+
api = get_api(debug=debug)
|
|
1792
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/sequentialRing/criteria/{id}"
|
|
1793
|
+
params = {}
|
|
1794
|
+
org_id = get_org_id()
|
|
1795
|
+
if org_id is not None:
|
|
1796
|
+
params["orgId"] = org_id
|
|
1797
|
+
try:
|
|
1798
|
+
result = api.session.rest_get(url, params=params)
|
|
1799
|
+
except WebexError as e:
|
|
1800
|
+
handle_rest_error(e)
|
|
1801
|
+
if output == "json":
|
|
1802
|
+
print_json(result)
|
|
1803
|
+
else:
|
|
1804
|
+
if isinstance(result, dict):
|
|
1805
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1806
|
+
elif isinstance(result, list):
|
|
1807
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1808
|
+
else:
|
|
1809
|
+
print_json(result)
|
|
1810
|
+
|
|
1811
|
+
|
|
1812
|
+
|
|
1813
|
+
@app.command("update-criteria-sequential-ring")
|
|
1814
|
+
def update_criteria_sequential_ring(
|
|
1815
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1816
|
+
id: str = typer.Argument(help="id"),
|
|
1817
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
1818
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: holidays, businessHours"),
|
|
1819
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
1820
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: SELECT_PHONE_NUMBERS, ANY_PHONE_NUMBER"),
|
|
1821
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true` incoming calls from private numbers are allowed."),
|
|
1822
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true` incoming calls from unavailable numbers are allo"),
|
|
1823
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="When set to `true` sequential ringing is enabled for calls t"),
|
|
1824
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1825
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1826
|
+
):
|
|
1827
|
+
"""Modify Sequential Ring Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"holidays","scheduleLevel":"GROUP","callsFrom":"SELECT_PHONE_NUMBERS","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"ringEnabled":true}'."""
|
|
1828
|
+
api = get_api(debug=debug)
|
|
1829
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/sequentialRing/criteria/{id}"
|
|
1830
|
+
params = {}
|
|
1831
|
+
org_id = get_org_id()
|
|
1832
|
+
if org_id is not None:
|
|
1833
|
+
params["orgId"] = org_id
|
|
1834
|
+
if json_body:
|
|
1835
|
+
body = json.loads(json_body)
|
|
1836
|
+
else:
|
|
1837
|
+
body = {}
|
|
1838
|
+
if schedule_name is not None:
|
|
1839
|
+
body["scheduleName"] = schedule_name
|
|
1840
|
+
if schedule_type is not None:
|
|
1841
|
+
body["scheduleType"] = schedule_type
|
|
1842
|
+
if schedule_level is not None:
|
|
1843
|
+
body["scheduleLevel"] = schedule_level
|
|
1844
|
+
if calls_from is not None:
|
|
1845
|
+
body["callsFrom"] = calls_from
|
|
1846
|
+
if anonymous_callers_enabled is not None:
|
|
1847
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
1848
|
+
if unavailable_callers_enabled is not None:
|
|
1849
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
1850
|
+
if ring_enabled is not None:
|
|
1851
|
+
body["ringEnabled"] = ring_enabled
|
|
1852
|
+
try:
|
|
1853
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1854
|
+
except WebexError as e:
|
|
1855
|
+
handle_rest_error(e)
|
|
1856
|
+
typer.echo(f"Updated.")
|
|
1857
|
+
|
|
1858
|
+
|
|
1859
|
+
|
|
1860
|
+
@app.command("delete-criteria-sequential-ring")
|
|
1861
|
+
def delete_criteria_sequential_ring(
|
|
1862
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1863
|
+
id: str = typer.Argument(help="id"),
|
|
1864
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1865
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1866
|
+
):
|
|
1867
|
+
"""Delete Sequential Ring Criteria for a Workspace."""
|
|
1868
|
+
if not force:
|
|
1869
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
1870
|
+
api = get_api(debug=debug)
|
|
1871
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/sequentialRing/criteria/{id}"
|
|
1872
|
+
params = {}
|
|
1873
|
+
org_id = get_org_id()
|
|
1874
|
+
if org_id is not None:
|
|
1875
|
+
params["orgId"] = org_id
|
|
1876
|
+
try:
|
|
1877
|
+
api.session.rest_delete(url, params=params)
|
|
1878
|
+
except WebexError as e:
|
|
1879
|
+
handle_rest_error(e)
|
|
1880
|
+
typer.echo(f"Deleted: {id}")
|
|
1881
|
+
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
@app.command("show-call-policies")
|
|
1885
|
+
def show_call_policies(
|
|
1886
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1887
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1888
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1889
|
+
):
|
|
1890
|
+
"""Read Call Policy Settings for a Workspace."""
|
|
1891
|
+
api = get_api(debug=debug)
|
|
1892
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/callPolicies"
|
|
1893
|
+
params = {}
|
|
1894
|
+
org_id = get_org_id()
|
|
1895
|
+
if org_id is not None:
|
|
1896
|
+
params["orgId"] = org_id
|
|
1897
|
+
try:
|
|
1898
|
+
result = api.session.rest_get(url, params=params)
|
|
1899
|
+
except WebexError as e:
|
|
1900
|
+
handle_rest_error(e)
|
|
1901
|
+
if output == "json":
|
|
1902
|
+
print_json(result)
|
|
1903
|
+
else:
|
|
1904
|
+
if isinstance(result, dict):
|
|
1905
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1906
|
+
elif isinstance(result, list):
|
|
1907
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1908
|
+
else:
|
|
1909
|
+
print_json(result)
|
|
1910
|
+
|
|
1911
|
+
|
|
1912
|
+
|
|
1913
|
+
@app.command("update-call-policies")
|
|
1914
|
+
def update_call_policies(
|
|
1915
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1916
|
+
connected_line_id_privacy_on_redirected_calls: str = typer.Option(None, "--connected-line-id-privacy-on-redirected-calls", help="Choices: NO_PRIVACY, PRIVACY_FOR_EXTERNAL_CALLS, PRIVACY_FOR_ALL_CALLS"),
|
|
1917
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1918
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1919
|
+
):
|
|
1920
|
+
"""Configure Call Policy Settings for a Workspace."""
|
|
1921
|
+
api = get_api(debug=debug)
|
|
1922
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/callPolicies"
|
|
1923
|
+
params = {}
|
|
1924
|
+
org_id = get_org_id()
|
|
1925
|
+
if org_id is not None:
|
|
1926
|
+
params["orgId"] = org_id
|
|
1927
|
+
if json_body:
|
|
1928
|
+
body = json.loads(json_body)
|
|
1929
|
+
else:
|
|
1930
|
+
body = {}
|
|
1931
|
+
if connected_line_id_privacy_on_redirected_calls is not None:
|
|
1932
|
+
body["connectedLineIdPrivacyOnRedirectedCalls"] = connected_line_id_privacy_on_redirected_calls
|
|
1933
|
+
try:
|
|
1934
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
1935
|
+
except WebexError as e:
|
|
1936
|
+
handle_rest_error(e)
|
|
1937
|
+
typer.echo(f"Updated.")
|
|
1938
|
+
|
|
1939
|
+
|
|
1940
|
+
|
|
1941
|
+
@app.command("configure-busy-voicemail")
|
|
1942
|
+
def configure_busy_voicemail(
|
|
1943
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1944
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1945
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1946
|
+
):
|
|
1947
|
+
"""Configure Busy Voicemail Greeting for a Place."""
|
|
1948
|
+
api = get_api(debug=debug)
|
|
1949
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/voicemail/actions/uploadBusyGreeting/invoke"
|
|
1950
|
+
params = {}
|
|
1951
|
+
org_id = get_org_id()
|
|
1952
|
+
if org_id is not None:
|
|
1953
|
+
params["orgId"] = org_id
|
|
1954
|
+
if json_body:
|
|
1955
|
+
body = json.loads(json_body)
|
|
1956
|
+
else:
|
|
1957
|
+
body = {}
|
|
1958
|
+
try:
|
|
1959
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1960
|
+
except WebexError as e:
|
|
1961
|
+
handle_rest_error(e)
|
|
1962
|
+
print_json(result)
|
|
1963
|
+
|
|
1964
|
+
|
|
1965
|
+
|
|
1966
|
+
@app.command("configure-no-answer")
|
|
1967
|
+
def configure_no_answer(
|
|
1968
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1969
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
1970
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1971
|
+
):
|
|
1972
|
+
"""Configure No Answer Voicemail Greeting for a Place."""
|
|
1973
|
+
api = get_api(debug=debug)
|
|
1974
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/voicemail/actions/uploadNoAnswerGreeting/invoke"
|
|
1975
|
+
params = {}
|
|
1976
|
+
org_id = get_org_id()
|
|
1977
|
+
if org_id is not None:
|
|
1978
|
+
params["orgId"] = org_id
|
|
1979
|
+
if json_body:
|
|
1980
|
+
body = json.loads(json_body)
|
|
1981
|
+
else:
|
|
1982
|
+
body = {}
|
|
1983
|
+
try:
|
|
1984
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1985
|
+
except WebexError as e:
|
|
1986
|
+
handle_rest_error(e)
|
|
1987
|
+
print_json(result)
|
|
1988
|
+
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
@app.command("create-criteria-sequential-ring")
|
|
1992
|
+
def create_criteria_sequential_ring(
|
|
1993
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
1994
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
1995
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: holidays, businessHours"),
|
|
1996
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
1997
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: SELECT_PHONE_NUMBERS, ANY_PHONE_NUMBER"),
|
|
1998
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true` incoming calls from private numbers are allowed."),
|
|
1999
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true` incoming calls from unavailable numbers are allo"),
|
|
2000
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="(required) When set to `true` sequential ringing is enabled for calls t"),
|
|
2001
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2002
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2003
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2004
|
+
):
|
|
2005
|
+
"""Create Sequential Ring Criteria for a Workspace\n\nExample --json-body:\n '{"callsFrom":"SELECT_PHONE_NUMBERS","ringEnabled":true,"scheduleName":"...","scheduleType":"holidays","scheduleLevel":"GROUP","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2006
|
+
api = get_api(debug=debug)
|
|
2007
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/sequentialRing/criteria"
|
|
2008
|
+
params = {}
|
|
2009
|
+
org_id = get_org_id()
|
|
2010
|
+
if org_id is not None:
|
|
2011
|
+
params["orgId"] = org_id
|
|
2012
|
+
if json_body:
|
|
2013
|
+
body = json.loads(json_body)
|
|
2014
|
+
else:
|
|
2015
|
+
body = {}
|
|
2016
|
+
if schedule_name is not None:
|
|
2017
|
+
body["scheduleName"] = schedule_name
|
|
2018
|
+
if schedule_type is not None:
|
|
2019
|
+
body["scheduleType"] = schedule_type
|
|
2020
|
+
if schedule_level is not None:
|
|
2021
|
+
body["scheduleLevel"] = schedule_level
|
|
2022
|
+
if calls_from is not None:
|
|
2023
|
+
body["callsFrom"] = calls_from
|
|
2024
|
+
if anonymous_callers_enabled is not None:
|
|
2025
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2026
|
+
if unavailable_callers_enabled is not None:
|
|
2027
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2028
|
+
if ring_enabled is not None:
|
|
2029
|
+
body["ringEnabled"] = ring_enabled
|
|
2030
|
+
_missing = [f for f in ['callsFrom', 'ringEnabled'] if f not in body or body[f] is None]
|
|
2031
|
+
if _missing:
|
|
2032
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
2033
|
+
raise typer.Exit(1)
|
|
2034
|
+
try:
|
|
2035
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
2036
|
+
except WebexError as e:
|
|
2037
|
+
handle_rest_error(e)
|
|
2038
|
+
if output == "json":
|
|
2039
|
+
print_json(result)
|
|
2040
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2041
|
+
typer.echo(f"Created: {result['id']}")
|
|
2042
|
+
elif not result or result == {}:
|
|
2043
|
+
typer.echo("Created.")
|
|
2044
|
+
else:
|
|
2045
|
+
print_json(result)
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
|
|
2049
|
+
@app.command("list-sequential-ring")
|
|
2050
|
+
def list_sequential_ring(
|
|
2051
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2052
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2053
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2054
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2055
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2056
|
+
):
|
|
2057
|
+
"""Retrieve Sequential Ring Settings for a Workspace."""
|
|
2058
|
+
api = get_api(debug=debug)
|
|
2059
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/sequentialRing"
|
|
2060
|
+
params = {}
|
|
2061
|
+
if limit > 0:
|
|
2062
|
+
params["max"] = limit
|
|
2063
|
+
if offset > 0:
|
|
2064
|
+
params["start"] = offset
|
|
2065
|
+
org_id = get_org_id()
|
|
2066
|
+
if org_id is not None:
|
|
2067
|
+
params["orgId"] = org_id
|
|
2068
|
+
result = None
|
|
2069
|
+
try:
|
|
2070
|
+
result = api.session.rest_get(url, params=params)
|
|
2071
|
+
except WebexError as e:
|
|
2072
|
+
handle_rest_error(e)
|
|
2073
|
+
result = result or []
|
|
2074
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2075
|
+
if output == "json":
|
|
2076
|
+
print_json(items)
|
|
2077
|
+
else:
|
|
2078
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2079
|
+
|
|
2080
|
+
|
|
2081
|
+
|
|
2082
|
+
@app.command("update-sequential-ring")
|
|
2083
|
+
def update_sequential_ring(
|
|
2084
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2085
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="When set to `true` sequential ring is enabled."),
|
|
2086
|
+
ring_base_location_first_enabled: bool = typer.Option(None, "--ring-base-location-first-enabled/--no-ring-base-location-first-enabled", help="When set to `true`, the webex calling primary line will ring"),
|
|
2087
|
+
base_location_number_of_rings: str = typer.Option(None, "--base-location-number-of-rings", help="The number of times the primary line will ring. `baseLocatio"),
|
|
2088
|
+
continue_if_base_location_is_busy_enabled: bool = typer.Option(None, "--continue-if-base-location-is-busy-enabled/--no-continue-if-base-location-is-busy-enabled", help="When set to `true` and the primary line is busy, the system"),
|
|
2089
|
+
calls_to_voicemail_enabled: bool = typer.Option(None, "--calls-to-voicemail-enabled/--no-calls-to-voicemail-enabled", help="When set to `true` calls are directed to voicemail."),
|
|
2090
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2091
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2092
|
+
):
|
|
2093
|
+
"""Modify Sequential Ring Settings for a Workspace\n\nExample --json-body:\n '{"enabled":true,"ringBaseLocationFirstEnabled":true,"baseLocationNumberOfRings":0,"continueIfBaseLocationIsBusyEnabled":true,"callsToVoicemailEnabled":true,"phoneNumbers":[{"phoneNumber":"...","answerConfirmationRequiredEnabled":"...","numberOfRings":"..."}]}'."""
|
|
2094
|
+
api = get_api(debug=debug)
|
|
2095
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/sequentialRing"
|
|
2096
|
+
params = {}
|
|
2097
|
+
org_id = get_org_id()
|
|
2098
|
+
if org_id is not None:
|
|
2099
|
+
params["orgId"] = org_id
|
|
2100
|
+
if json_body:
|
|
2101
|
+
body = json.loads(json_body)
|
|
2102
|
+
else:
|
|
2103
|
+
body = {}
|
|
2104
|
+
if enabled is not None:
|
|
2105
|
+
body["enabled"] = enabled
|
|
2106
|
+
if ring_base_location_first_enabled is not None:
|
|
2107
|
+
body["ringBaseLocationFirstEnabled"] = ring_base_location_first_enabled
|
|
2108
|
+
if base_location_number_of_rings is not None:
|
|
2109
|
+
body["baseLocationNumberOfRings"] = base_location_number_of_rings
|
|
2110
|
+
if continue_if_base_location_is_busy_enabled is not None:
|
|
2111
|
+
body["continueIfBaseLocationIsBusyEnabled"] = continue_if_base_location_is_busy_enabled
|
|
2112
|
+
if calls_to_voicemail_enabled is not None:
|
|
2113
|
+
body["callsToVoicemailEnabled"] = calls_to_voicemail_enabled
|
|
2114
|
+
try:
|
|
2115
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2116
|
+
except WebexError as e:
|
|
2117
|
+
handle_rest_error(e)
|
|
2118
|
+
typer.echo(f"Updated.")
|
|
2119
|
+
|
|
2120
|
+
|
|
2121
|
+
|
|
2122
|
+
@app.command("list-simultaneous-ring")
|
|
2123
|
+
def list_simultaneous_ring(
|
|
2124
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2125
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2126
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2127
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2128
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2129
|
+
):
|
|
2130
|
+
"""Retrieve Simultaneous Ring Settings for a Workspace."""
|
|
2131
|
+
api = get_api(debug=debug)
|
|
2132
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/simultaneousRing"
|
|
2133
|
+
params = {}
|
|
2134
|
+
if limit > 0:
|
|
2135
|
+
params["max"] = limit
|
|
2136
|
+
if offset > 0:
|
|
2137
|
+
params["start"] = offset
|
|
2138
|
+
org_id = get_org_id()
|
|
2139
|
+
if org_id is not None:
|
|
2140
|
+
params["orgId"] = org_id
|
|
2141
|
+
result = None
|
|
2142
|
+
try:
|
|
2143
|
+
result = api.session.rest_get(url, params=params)
|
|
2144
|
+
except WebexError as e:
|
|
2145
|
+
handle_rest_error(e)
|
|
2146
|
+
result = result or []
|
|
2147
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2148
|
+
if output == "json":
|
|
2149
|
+
print_json(items)
|
|
2150
|
+
else:
|
|
2151
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2152
|
+
|
|
2153
|
+
|
|
2154
|
+
|
|
2155
|
+
@app.command("update-simultaneous-ring")
|
|
2156
|
+
def update_simultaneous_ring(
|
|
2157
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2158
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Simultaneous Ring is enabled or not."),
|
|
2159
|
+
do_not_ring_if_on_call_enabled: bool = typer.Option(None, "--do-not-ring-if-on-call-enabled/--no-do-not-ring-if-on-call-enabled", help="When set to `true`, the configured phone numbers won't ring"),
|
|
2160
|
+
criterias_enabled: bool = typer.Option(None, "--criterias-enabled/--no-criterias-enabled", help="When `true`, enables the selected schedule for simultaneous"),
|
|
2161
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2162
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2163
|
+
):
|
|
2164
|
+
"""Modify Simultaneous Ring Settings for a Workspace\n\nExample --json-body:\n '{"criteriasEnabled":true,"enabled":true,"doNotRingIfOnCallEnabled":true,"phoneNumbers":[{"phoneNumber":"...","answerConfirmationRequiredEnabled":"..."}]}'."""
|
|
2165
|
+
api = get_api(debug=debug)
|
|
2166
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/simultaneousRing"
|
|
2167
|
+
params = {}
|
|
2168
|
+
org_id = get_org_id()
|
|
2169
|
+
if org_id is not None:
|
|
2170
|
+
params["orgId"] = org_id
|
|
2171
|
+
if json_body:
|
|
2172
|
+
body = json.loads(json_body)
|
|
2173
|
+
else:
|
|
2174
|
+
body = {}
|
|
2175
|
+
if enabled is not None:
|
|
2176
|
+
body["enabled"] = enabled
|
|
2177
|
+
if do_not_ring_if_on_call_enabled is not None:
|
|
2178
|
+
body["doNotRingIfOnCallEnabled"] = do_not_ring_if_on_call_enabled
|
|
2179
|
+
if criterias_enabled is not None:
|
|
2180
|
+
body["criteriasEnabled"] = criterias_enabled
|
|
2181
|
+
try:
|
|
2182
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2183
|
+
except WebexError as e:
|
|
2184
|
+
handle_rest_error(e)
|
|
2185
|
+
typer.echo(f"Updated.")
|
|
2186
|
+
|
|
2187
|
+
|
|
2188
|
+
|
|
2189
|
+
@app.command("show-criteria-simultaneous-ring")
|
|
2190
|
+
def show_criteria_simultaneous_ring(
|
|
2191
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2192
|
+
id: str = typer.Argument(help="id"),
|
|
2193
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2194
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2195
|
+
):
|
|
2196
|
+
"""Retrieve Simultaneous Ring Criteria for a Workspace."""
|
|
2197
|
+
api = get_api(debug=debug)
|
|
2198
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/simultaneousRing/criteria/{id}"
|
|
2199
|
+
params = {}
|
|
2200
|
+
org_id = get_org_id()
|
|
2201
|
+
if org_id is not None:
|
|
2202
|
+
params["orgId"] = org_id
|
|
2203
|
+
try:
|
|
2204
|
+
result = api.session.rest_get(url, params=params)
|
|
2205
|
+
except WebexError as e:
|
|
2206
|
+
handle_rest_error(e)
|
|
2207
|
+
if output == "json":
|
|
2208
|
+
print_json(result)
|
|
2209
|
+
else:
|
|
2210
|
+
if isinstance(result, dict):
|
|
2211
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2212
|
+
elif isinstance(result, list):
|
|
2213
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2214
|
+
else:
|
|
2215
|
+
print_json(result)
|
|
2216
|
+
|
|
2217
|
+
|
|
2218
|
+
|
|
2219
|
+
@app.command("update-criteria-simultaneous-ring")
|
|
2220
|
+
def update_criteria_simultaneous_ring(
|
|
2221
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2222
|
+
id: str = typer.Argument(help="id"),
|
|
2223
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the si"),
|
|
2224
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2225
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
2226
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2227
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers."),
|
|
2228
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2229
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="When set to `true` simultaneous ringing criteria is enabled"),
|
|
2230
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2231
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2232
|
+
):
|
|
2233
|
+
"""Modify Simultaneous Ring Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"ringEnabled":true}'."""
|
|
2234
|
+
api = get_api(debug=debug)
|
|
2235
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/simultaneousRing/criteria/{id}"
|
|
2236
|
+
params = {}
|
|
2237
|
+
org_id = get_org_id()
|
|
2238
|
+
if org_id is not None:
|
|
2239
|
+
params["orgId"] = org_id
|
|
2240
|
+
if json_body:
|
|
2241
|
+
body = json.loads(json_body)
|
|
2242
|
+
else:
|
|
2243
|
+
body = {}
|
|
2244
|
+
if schedule_name is not None:
|
|
2245
|
+
body["scheduleName"] = schedule_name
|
|
2246
|
+
if schedule_type is not None:
|
|
2247
|
+
body["scheduleType"] = schedule_type
|
|
2248
|
+
if schedule_level is not None:
|
|
2249
|
+
body["scheduleLevel"] = schedule_level
|
|
2250
|
+
if calls_from is not None:
|
|
2251
|
+
body["callsFrom"] = calls_from
|
|
2252
|
+
if anonymous_callers_enabled is not None:
|
|
2253
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2254
|
+
if unavailable_callers_enabled is not None:
|
|
2255
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2256
|
+
if ring_enabled is not None:
|
|
2257
|
+
body["ringEnabled"] = ring_enabled
|
|
2258
|
+
try:
|
|
2259
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2260
|
+
except WebexError as e:
|
|
2261
|
+
handle_rest_error(e)
|
|
2262
|
+
typer.echo(f"Updated.")
|
|
2263
|
+
|
|
2264
|
+
|
|
2265
|
+
|
|
2266
|
+
@app.command("delete-criteria-simultaneous-ring")
|
|
2267
|
+
def delete_criteria_simultaneous_ring(
|
|
2268
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2269
|
+
id: str = typer.Argument(help="id"),
|
|
2270
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2271
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2272
|
+
):
|
|
2273
|
+
"""Delete Simultaneous Ring Criteria for a Workspace."""
|
|
2274
|
+
if not force:
|
|
2275
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2276
|
+
api = get_api(debug=debug)
|
|
2277
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/simultaneousRing/criteria/{id}"
|
|
2278
|
+
params = {}
|
|
2279
|
+
org_id = get_org_id()
|
|
2280
|
+
if org_id is not None:
|
|
2281
|
+
params["orgId"] = org_id
|
|
2282
|
+
try:
|
|
2283
|
+
api.session.rest_delete(url, params=params)
|
|
2284
|
+
except WebexError as e:
|
|
2285
|
+
handle_rest_error(e)
|
|
2286
|
+
typer.echo(f"Deleted: {id}")
|
|
2287
|
+
|
|
2288
|
+
|
|
2289
|
+
|
|
2290
|
+
@app.command("create-criteria-simultaneous-ring")
|
|
2291
|
+
def create_criteria_simultaneous_ring(
|
|
2292
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2293
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="(required) Name of the location's schedule which determines when the si"),
|
|
2294
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="(required) Choices: businessHours, holidays"),
|
|
2295
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="(required) Choices: GROUP"),
|
|
2296
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2297
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers. Value for"),
|
|
2298
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2299
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="(required) When set to `true` simultaneous ringing criteria is enabled"),
|
|
2300
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2301
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2302
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2303
|
+
):
|
|
2304
|
+
"""Create Simultaneous Ring Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","ringEnabled":true,"anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2305
|
+
api = get_api(debug=debug)
|
|
2306
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/simultaneousRing/criteria"
|
|
2307
|
+
params = {}
|
|
2308
|
+
org_id = get_org_id()
|
|
2309
|
+
if org_id is not None:
|
|
2310
|
+
params["orgId"] = org_id
|
|
2311
|
+
if json_body:
|
|
2312
|
+
body = json.loads(json_body)
|
|
2313
|
+
else:
|
|
2314
|
+
body = {}
|
|
2315
|
+
if schedule_name is not None:
|
|
2316
|
+
body["scheduleName"] = schedule_name
|
|
2317
|
+
if schedule_type is not None:
|
|
2318
|
+
body["scheduleType"] = schedule_type
|
|
2319
|
+
if schedule_level is not None:
|
|
2320
|
+
body["scheduleLevel"] = schedule_level
|
|
2321
|
+
if calls_from is not None:
|
|
2322
|
+
body["callsFrom"] = calls_from
|
|
2323
|
+
if anonymous_callers_enabled is not None:
|
|
2324
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2325
|
+
if unavailable_callers_enabled is not None:
|
|
2326
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2327
|
+
if ring_enabled is not None:
|
|
2328
|
+
body["ringEnabled"] = ring_enabled
|
|
2329
|
+
_missing = [f for f in ['scheduleName', 'scheduleType', 'scheduleLevel', 'callsFrom', 'ringEnabled'] if f not in body or body[f] is None]
|
|
2330
|
+
if _missing:
|
|
2331
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
2332
|
+
raise typer.Exit(1)
|
|
2333
|
+
try:
|
|
2334
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
2335
|
+
except WebexError as e:
|
|
2336
|
+
handle_rest_error(e)
|
|
2337
|
+
if output == "json":
|
|
2338
|
+
print_json(result)
|
|
2339
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2340
|
+
typer.echo(f"Created: {result['id']}")
|
|
2341
|
+
elif not result or result == {}:
|
|
2342
|
+
typer.echo("Created.")
|
|
2343
|
+
else:
|
|
2344
|
+
print_json(result)
|
|
2345
|
+
|
|
2346
|
+
|
|
2347
|
+
|
|
2348
|
+
@app.command("list-selective-reject")
|
|
2349
|
+
def list_selective_reject(
|
|
2350
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2351
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2352
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2353
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2354
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2355
|
+
):
|
|
2356
|
+
"""Retrieve Selective Reject Settings for a Workspace."""
|
|
2357
|
+
api = get_api(debug=debug)
|
|
2358
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveReject"
|
|
2359
|
+
params = {}
|
|
2360
|
+
if limit > 0:
|
|
2361
|
+
params["max"] = limit
|
|
2362
|
+
if offset > 0:
|
|
2363
|
+
params["start"] = offset
|
|
2364
|
+
org_id = get_org_id()
|
|
2365
|
+
if org_id is not None:
|
|
2366
|
+
params["orgId"] = org_id
|
|
2367
|
+
result = None
|
|
2368
|
+
try:
|
|
2369
|
+
result = api.session.rest_get(url, params=params)
|
|
2370
|
+
except WebexError as e:
|
|
2371
|
+
handle_rest_error(e)
|
|
2372
|
+
result = result or []
|
|
2373
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2374
|
+
if output == "json":
|
|
2375
|
+
print_json(items)
|
|
2376
|
+
else:
|
|
2377
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
|
|
2381
|
+
@app.command("update-selective-reject")
|
|
2382
|
+
def update_selective_reject(
|
|
2383
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2384
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="if `true`, selective reject is enabled."),
|
|
2385
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2386
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2387
|
+
):
|
|
2388
|
+
"""Modify Selective Reject Settings for a Workspace."""
|
|
2389
|
+
api = get_api(debug=debug)
|
|
2390
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveReject"
|
|
2391
|
+
params = {}
|
|
2392
|
+
org_id = get_org_id()
|
|
2393
|
+
if org_id is not None:
|
|
2394
|
+
params["orgId"] = org_id
|
|
2395
|
+
if json_body:
|
|
2396
|
+
body = json.loads(json_body)
|
|
2397
|
+
else:
|
|
2398
|
+
body = {}
|
|
2399
|
+
if enabled is not None:
|
|
2400
|
+
body["enabled"] = enabled
|
|
2401
|
+
try:
|
|
2402
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2403
|
+
except WebexError as e:
|
|
2404
|
+
handle_rest_error(e)
|
|
2405
|
+
typer.echo(f"Updated.")
|
|
2406
|
+
|
|
2407
|
+
|
|
2408
|
+
|
|
2409
|
+
@app.command("show-criteria-selective-reject")
|
|
2410
|
+
def show_criteria_selective_reject(
|
|
2411
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2412
|
+
id: str = typer.Argument(help="id"),
|
|
2413
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2414
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2415
|
+
):
|
|
2416
|
+
"""Retrieve Selective Reject Criteria for a Workspace."""
|
|
2417
|
+
api = get_api(debug=debug)
|
|
2418
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveReject/criteria/{id}"
|
|
2419
|
+
params = {}
|
|
2420
|
+
org_id = get_org_id()
|
|
2421
|
+
if org_id is not None:
|
|
2422
|
+
params["orgId"] = org_id
|
|
2423
|
+
try:
|
|
2424
|
+
result = api.session.rest_get(url, params=params)
|
|
2425
|
+
except WebexError as e:
|
|
2426
|
+
handle_rest_error(e)
|
|
2427
|
+
if output == "json":
|
|
2428
|
+
print_json(result)
|
|
2429
|
+
else:
|
|
2430
|
+
if isinstance(result, dict):
|
|
2431
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2432
|
+
elif isinstance(result, list):
|
|
2433
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2434
|
+
else:
|
|
2435
|
+
print_json(result)
|
|
2436
|
+
|
|
2437
|
+
|
|
2438
|
+
|
|
2439
|
+
@app.command("update-criteria-selective-reject")
|
|
2440
|
+
def update_criteria_selective_reject(
|
|
2441
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2442
|
+
id: str = typer.Argument(help="id"),
|
|
2443
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
2444
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2445
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
2446
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, FORWARDED"),
|
|
2447
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers."),
|
|
2448
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2449
|
+
reject_enabled: bool = typer.Option(None, "--reject-enabled/--no-reject-enabled", help="Choose to reject (if `rejectEnabled` = `true`) or not to rej"),
|
|
2450
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2451
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2452
|
+
):
|
|
2453
|
+
"""Modify Selective Reject Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"rejectEnabled":true}'."""
|
|
2454
|
+
api = get_api(debug=debug)
|
|
2455
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveReject/criteria/{id}"
|
|
2456
|
+
params = {}
|
|
2457
|
+
org_id = get_org_id()
|
|
2458
|
+
if org_id is not None:
|
|
2459
|
+
params["orgId"] = org_id
|
|
2460
|
+
if json_body:
|
|
2461
|
+
body = json.loads(json_body)
|
|
2462
|
+
else:
|
|
2463
|
+
body = {}
|
|
2464
|
+
if schedule_name is not None:
|
|
2465
|
+
body["scheduleName"] = schedule_name
|
|
2466
|
+
if schedule_type is not None:
|
|
2467
|
+
body["scheduleType"] = schedule_type
|
|
2468
|
+
if schedule_level is not None:
|
|
2469
|
+
body["scheduleLevel"] = schedule_level
|
|
2470
|
+
if calls_from is not None:
|
|
2471
|
+
body["callsFrom"] = calls_from
|
|
2472
|
+
if anonymous_callers_enabled is not None:
|
|
2473
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2474
|
+
if unavailable_callers_enabled is not None:
|
|
2475
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2476
|
+
if reject_enabled is not None:
|
|
2477
|
+
body["rejectEnabled"] = reject_enabled
|
|
2478
|
+
try:
|
|
2479
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2480
|
+
except WebexError as e:
|
|
2481
|
+
handle_rest_error(e)
|
|
2482
|
+
typer.echo(f"Updated.")
|
|
2483
|
+
|
|
2484
|
+
|
|
2485
|
+
|
|
2486
|
+
@app.command("delete-criteria-selective-reject")
|
|
2487
|
+
def delete_criteria_selective_reject(
|
|
2488
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2489
|
+
id: str = typer.Argument(help="id"),
|
|
2490
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2491
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2492
|
+
):
|
|
2493
|
+
"""Delete Selective Reject Criteria for a Workspace."""
|
|
2494
|
+
if not force:
|
|
2495
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2496
|
+
api = get_api(debug=debug)
|
|
2497
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveReject/criteria/{id}"
|
|
2498
|
+
params = {}
|
|
2499
|
+
org_id = get_org_id()
|
|
2500
|
+
if org_id is not None:
|
|
2501
|
+
params["orgId"] = org_id
|
|
2502
|
+
try:
|
|
2503
|
+
api.session.rest_delete(url, params=params)
|
|
2504
|
+
except WebexError as e:
|
|
2505
|
+
handle_rest_error(e)
|
|
2506
|
+
typer.echo(f"Deleted: {id}")
|
|
2507
|
+
|
|
2508
|
+
|
|
2509
|
+
|
|
2510
|
+
@app.command("create-criteria-selective-reject")
|
|
2511
|
+
def create_criteria_selective_reject(
|
|
2512
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2513
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="(required) Name of the location's schedule which determines when the se"),
|
|
2514
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="(required) Choices: businessHours, holidays"),
|
|
2515
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="(required) Choices: GROUP"),
|
|
2516
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, FORWARDED"),
|
|
2517
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers. Value for"),
|
|
2518
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2519
|
+
reject_enabled: bool = typer.Option(None, "--reject-enabled/--no-reject-enabled", help="(required) Choose to reject (if `rejectEnabled` = `true`) or not to rej"),
|
|
2520
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2521
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2522
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2523
|
+
):
|
|
2524
|
+
"""Create Selective Reject Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","rejectEnabled":true,"anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2525
|
+
api = get_api(debug=debug)
|
|
2526
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveReject/criteria"
|
|
2527
|
+
params = {}
|
|
2528
|
+
org_id = get_org_id()
|
|
2529
|
+
if org_id is not None:
|
|
2530
|
+
params["orgId"] = org_id
|
|
2531
|
+
if json_body:
|
|
2532
|
+
body = json.loads(json_body)
|
|
2533
|
+
else:
|
|
2534
|
+
body = {}
|
|
2535
|
+
if schedule_name is not None:
|
|
2536
|
+
body["scheduleName"] = schedule_name
|
|
2537
|
+
if schedule_type is not None:
|
|
2538
|
+
body["scheduleType"] = schedule_type
|
|
2539
|
+
if schedule_level is not None:
|
|
2540
|
+
body["scheduleLevel"] = schedule_level
|
|
2541
|
+
if calls_from is not None:
|
|
2542
|
+
body["callsFrom"] = calls_from
|
|
2543
|
+
if anonymous_callers_enabled is not None:
|
|
2544
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2545
|
+
if unavailable_callers_enabled is not None:
|
|
2546
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2547
|
+
if reject_enabled is not None:
|
|
2548
|
+
body["rejectEnabled"] = reject_enabled
|
|
2549
|
+
_missing = [f for f in ['scheduleName', 'scheduleType', 'scheduleLevel', 'callsFrom', 'rejectEnabled'] if f not in body or body[f] is None]
|
|
2550
|
+
if _missing:
|
|
2551
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
2552
|
+
raise typer.Exit(1)
|
|
2553
|
+
try:
|
|
2554
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
2555
|
+
except WebexError as e:
|
|
2556
|
+
handle_rest_error(e)
|
|
2557
|
+
if output == "json":
|
|
2558
|
+
print_json(result)
|
|
2559
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2560
|
+
typer.echo(f"Created: {result['id']}")
|
|
2561
|
+
elif not result or result == {}:
|
|
2562
|
+
typer.echo("Created.")
|
|
2563
|
+
else:
|
|
2564
|
+
print_json(result)
|
|
2565
|
+
|
|
2566
|
+
|
|
2567
|
+
|
|
2568
|
+
@app.command("update-numbers")
|
|
2569
|
+
def update_numbers(
|
|
2570
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2571
|
+
distinctive_ring_enabled: bool = typer.Option(None, "--distinctive-ring-enabled/--no-distinctive-ring-enabled", help="Enables a distinctive ring pattern for the person."),
|
|
2572
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2573
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2574
|
+
):
|
|
2575
|
+
"""Assign or Unassign numbers associated with a specific workspace\n\nExample --json-body:\n '{"phoneNumbers":[{"primary":"...","action":"...","directNumber":"...","extension":"...","ringPattern":"..."}],"distinctiveRingEnabled":true}'."""
|
|
2576
|
+
api = get_api(debug=debug)
|
|
2577
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/numbers"
|
|
2578
|
+
params = {}
|
|
2579
|
+
org_id = get_org_id()
|
|
2580
|
+
if org_id is not None:
|
|
2581
|
+
params["orgId"] = org_id
|
|
2582
|
+
if json_body:
|
|
2583
|
+
body = json.loads(json_body)
|
|
2584
|
+
else:
|
|
2585
|
+
body = {}
|
|
2586
|
+
if distinctive_ring_enabled is not None:
|
|
2587
|
+
body["distinctiveRingEnabled"] = distinctive_ring_enabled
|
|
2588
|
+
try:
|
|
2589
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2590
|
+
except WebexError as e:
|
|
2591
|
+
handle_rest_error(e)
|
|
2592
|
+
typer.echo(f"Updated.")
|
|
2593
|
+
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
@app.command("list-selective-accept")
|
|
2597
|
+
def list_selective_accept(
|
|
2598
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2599
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2600
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2601
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2602
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2603
|
+
):
|
|
2604
|
+
"""Retrieve Selective Accept Settings for a Workspace."""
|
|
2605
|
+
api = get_api(debug=debug)
|
|
2606
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveAccept"
|
|
2607
|
+
params = {}
|
|
2608
|
+
if limit > 0:
|
|
2609
|
+
params["max"] = limit
|
|
2610
|
+
if offset > 0:
|
|
2611
|
+
params["start"] = offset
|
|
2612
|
+
org_id = get_org_id()
|
|
2613
|
+
if org_id is not None:
|
|
2614
|
+
params["orgId"] = org_id
|
|
2615
|
+
result = None
|
|
2616
|
+
try:
|
|
2617
|
+
result = api.session.rest_get(url, params=params)
|
|
2618
|
+
except WebexError as e:
|
|
2619
|
+
handle_rest_error(e)
|
|
2620
|
+
result = result or []
|
|
2621
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2622
|
+
if output == "json":
|
|
2623
|
+
print_json(items)
|
|
2624
|
+
else:
|
|
2625
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2626
|
+
|
|
2627
|
+
|
|
2628
|
+
|
|
2629
|
+
@app.command("update-selective-accept")
|
|
2630
|
+
def update_selective_accept(
|
|
2631
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2632
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="indicates whether selective accept is enabled or not."),
|
|
2633
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2634
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2635
|
+
):
|
|
2636
|
+
"""Modify Selective Accept Settings for a Workspace."""
|
|
2637
|
+
api = get_api(debug=debug)
|
|
2638
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveAccept"
|
|
2639
|
+
params = {}
|
|
2640
|
+
org_id = get_org_id()
|
|
2641
|
+
if org_id is not None:
|
|
2642
|
+
params["orgId"] = org_id
|
|
2643
|
+
if json_body:
|
|
2644
|
+
body = json.loads(json_body)
|
|
2645
|
+
else:
|
|
2646
|
+
body = {}
|
|
2647
|
+
if enabled is not None:
|
|
2648
|
+
body["enabled"] = enabled
|
|
2649
|
+
try:
|
|
2650
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2651
|
+
except WebexError as e:
|
|
2652
|
+
handle_rest_error(e)
|
|
2653
|
+
typer.echo(f"Updated.")
|
|
2654
|
+
|
|
2655
|
+
|
|
2656
|
+
|
|
2657
|
+
@app.command("show-criteria-selective-accept")
|
|
2658
|
+
def show_criteria_selective_accept(
|
|
2659
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2660
|
+
id: str = typer.Argument(help="id"),
|
|
2661
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2662
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2663
|
+
):
|
|
2664
|
+
"""Retrieve Selective Accept Criteria for a Workspace."""
|
|
2665
|
+
api = get_api(debug=debug)
|
|
2666
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveAccept/criteria/{id}"
|
|
2667
|
+
params = {}
|
|
2668
|
+
org_id = get_org_id()
|
|
2669
|
+
if org_id is not None:
|
|
2670
|
+
params["orgId"] = org_id
|
|
2671
|
+
try:
|
|
2672
|
+
result = api.session.rest_get(url, params=params)
|
|
2673
|
+
except WebexError as e:
|
|
2674
|
+
handle_rest_error(e)
|
|
2675
|
+
if output == "json":
|
|
2676
|
+
print_json(result)
|
|
2677
|
+
else:
|
|
2678
|
+
if isinstance(result, dict):
|
|
2679
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2680
|
+
elif isinstance(result, list):
|
|
2681
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2682
|
+
else:
|
|
2683
|
+
print_json(result)
|
|
2684
|
+
|
|
2685
|
+
|
|
2686
|
+
|
|
2687
|
+
@app.command("update-criteria-selective-accept")
|
|
2688
|
+
def update_criteria_selective_accept(
|
|
2689
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2690
|
+
id: str = typer.Argument(help="id"),
|
|
2691
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
2692
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2693
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
2694
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, FORWARDED"),
|
|
2695
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers."),
|
|
2696
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2697
|
+
accept_enabled: bool = typer.Option(None, "--accept-enabled/--no-accept-enabled", help="Choose to accept (if `acceptEnabled` = `true`) or not to acc"),
|
|
2698
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2699
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2700
|
+
):
|
|
2701
|
+
"""Modify Selective Accept Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"acceptEnabled":true}'."""
|
|
2702
|
+
api = get_api(debug=debug)
|
|
2703
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveAccept/criteria/{id}"
|
|
2704
|
+
params = {}
|
|
2705
|
+
org_id = get_org_id()
|
|
2706
|
+
if org_id is not None:
|
|
2707
|
+
params["orgId"] = org_id
|
|
2708
|
+
if json_body:
|
|
2709
|
+
body = json.loads(json_body)
|
|
2710
|
+
else:
|
|
2711
|
+
body = {}
|
|
2712
|
+
if schedule_name is not None:
|
|
2713
|
+
body["scheduleName"] = schedule_name
|
|
2714
|
+
if schedule_type is not None:
|
|
2715
|
+
body["scheduleType"] = schedule_type
|
|
2716
|
+
if schedule_level is not None:
|
|
2717
|
+
body["scheduleLevel"] = schedule_level
|
|
2718
|
+
if calls_from is not None:
|
|
2719
|
+
body["callsFrom"] = calls_from
|
|
2720
|
+
if anonymous_callers_enabled is not None:
|
|
2721
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2722
|
+
if unavailable_callers_enabled is not None:
|
|
2723
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2724
|
+
if accept_enabled is not None:
|
|
2725
|
+
body["acceptEnabled"] = accept_enabled
|
|
2726
|
+
try:
|
|
2727
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2728
|
+
except WebexError as e:
|
|
2729
|
+
handle_rest_error(e)
|
|
2730
|
+
typer.echo(f"Updated.")
|
|
2731
|
+
|
|
2732
|
+
|
|
2733
|
+
|
|
2734
|
+
@app.command("delete-criteria-selective-accept")
|
|
2735
|
+
def delete_criteria_selective_accept(
|
|
2736
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2737
|
+
id: str = typer.Argument(help="id"),
|
|
2738
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2739
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2740
|
+
):
|
|
2741
|
+
"""Delete Selective Accept Criteria for a Workspace."""
|
|
2742
|
+
if not force:
|
|
2743
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2744
|
+
api = get_api(debug=debug)
|
|
2745
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveAccept/criteria/{id}"
|
|
2746
|
+
params = {}
|
|
2747
|
+
org_id = get_org_id()
|
|
2748
|
+
if org_id is not None:
|
|
2749
|
+
params["orgId"] = org_id
|
|
2750
|
+
try:
|
|
2751
|
+
api.session.rest_delete(url, params=params)
|
|
2752
|
+
except WebexError as e:
|
|
2753
|
+
handle_rest_error(e)
|
|
2754
|
+
typer.echo(f"Deleted: {id}")
|
|
2755
|
+
|
|
2756
|
+
|
|
2757
|
+
|
|
2758
|
+
@app.command("create-criteria-selective-accept")
|
|
2759
|
+
def create_criteria_selective_accept(
|
|
2760
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2761
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="(required) Name of the location's schedule which determines when the se"),
|
|
2762
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="(required) Choices: businessHours, holidays"),
|
|
2763
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="(required) Choices: GROUP"),
|
|
2764
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, FORWARDED"),
|
|
2765
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers. Value for"),
|
|
2766
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2767
|
+
accept_enabled: bool = typer.Option(None, "--accept-enabled/--no-accept-enabled", help="(required) Choose to accept (if `acceptEnabled` = `true`) or not to acc"),
|
|
2768
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2769
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2770
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2771
|
+
):
|
|
2772
|
+
"""Create Selective Accept Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","acceptEnabled":true,"anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2773
|
+
api = get_api(debug=debug)
|
|
2774
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveAccept/criteria"
|
|
2775
|
+
params = {}
|
|
2776
|
+
org_id = get_org_id()
|
|
2777
|
+
if org_id is not None:
|
|
2778
|
+
params["orgId"] = org_id
|
|
2779
|
+
if json_body:
|
|
2780
|
+
body = json.loads(json_body)
|
|
2781
|
+
else:
|
|
2782
|
+
body = {}
|
|
2783
|
+
if schedule_name is not None:
|
|
2784
|
+
body["scheduleName"] = schedule_name
|
|
2785
|
+
if schedule_type is not None:
|
|
2786
|
+
body["scheduleType"] = schedule_type
|
|
2787
|
+
if schedule_level is not None:
|
|
2788
|
+
body["scheduleLevel"] = schedule_level
|
|
2789
|
+
if calls_from is not None:
|
|
2790
|
+
body["callsFrom"] = calls_from
|
|
2791
|
+
if anonymous_callers_enabled is not None:
|
|
2792
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2793
|
+
if unavailable_callers_enabled is not None:
|
|
2794
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2795
|
+
if accept_enabled is not None:
|
|
2796
|
+
body["acceptEnabled"] = accept_enabled
|
|
2797
|
+
_missing = [f for f in ['scheduleName', 'scheduleType', 'scheduleLevel', 'callsFrom', 'acceptEnabled'] if f not in body or body[f] is None]
|
|
2798
|
+
if _missing:
|
|
2799
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
2800
|
+
raise typer.Exit(1)
|
|
2801
|
+
try:
|
|
2802
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
2803
|
+
except WebexError as e:
|
|
2804
|
+
handle_rest_error(e)
|
|
2805
|
+
if output == "json":
|
|
2806
|
+
print_json(result)
|
|
2807
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2808
|
+
typer.echo(f"Created: {result['id']}")
|
|
2809
|
+
elif not result or result == {}:
|
|
2810
|
+
typer.echo("Created.")
|
|
2811
|
+
else:
|
|
2812
|
+
print_json(result)
|
|
2813
|
+
|
|
2814
|
+
|
|
2815
|
+
|
|
2816
|
+
@app.command("list-priority-alert")
|
|
2817
|
+
def list_priority_alert(
|
|
2818
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2819
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2820
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2821
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2822
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2823
|
+
):
|
|
2824
|
+
"""Retrieve Priority Alert Settings for a Workspace."""
|
|
2825
|
+
api = get_api(debug=debug)
|
|
2826
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/priorityAlert"
|
|
2827
|
+
params = {}
|
|
2828
|
+
if limit > 0:
|
|
2829
|
+
params["max"] = limit
|
|
2830
|
+
if offset > 0:
|
|
2831
|
+
params["start"] = offset
|
|
2832
|
+
org_id = get_org_id()
|
|
2833
|
+
if org_id is not None:
|
|
2834
|
+
params["orgId"] = org_id
|
|
2835
|
+
result = None
|
|
2836
|
+
try:
|
|
2837
|
+
result = api.session.rest_get(url, params=params)
|
|
2838
|
+
except WebexError as e:
|
|
2839
|
+
handle_rest_error(e)
|
|
2840
|
+
result = result or []
|
|
2841
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2842
|
+
if output == "json":
|
|
2843
|
+
print_json(items)
|
|
2844
|
+
else:
|
|
2845
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2846
|
+
|
|
2847
|
+
|
|
2848
|
+
|
|
2849
|
+
@app.command("update-priority-alert")
|
|
2850
|
+
def update_priority_alert(
|
|
2851
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2852
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Priority Alert feature is enabled."),
|
|
2853
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2854
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2855
|
+
):
|
|
2856
|
+
"""Configure Priority Alert Settings for a Workspace."""
|
|
2857
|
+
api = get_api(debug=debug)
|
|
2858
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/priorityAlert"
|
|
2859
|
+
params = {}
|
|
2860
|
+
org_id = get_org_id()
|
|
2861
|
+
if org_id is not None:
|
|
2862
|
+
params["orgId"] = org_id
|
|
2863
|
+
if json_body:
|
|
2864
|
+
body = json.loads(json_body)
|
|
2865
|
+
else:
|
|
2866
|
+
body = {}
|
|
2867
|
+
if enabled is not None:
|
|
2868
|
+
body["enabled"] = enabled
|
|
2869
|
+
try:
|
|
2870
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2871
|
+
except WebexError as e:
|
|
2872
|
+
handle_rest_error(e)
|
|
2873
|
+
typer.echo(f"Updated.")
|
|
2874
|
+
|
|
2875
|
+
|
|
2876
|
+
|
|
2877
|
+
@app.command("show-criteria-priority-alert")
|
|
2878
|
+
def show_criteria_priority_alert(
|
|
2879
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2880
|
+
id: str = typer.Argument(help="id"),
|
|
2881
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2882
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2883
|
+
):
|
|
2884
|
+
"""Retrieve Priority Alert Criteria for a Workspace."""
|
|
2885
|
+
api = get_api(debug=debug)
|
|
2886
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/priorityAlert/criteria/{id}"
|
|
2887
|
+
params = {}
|
|
2888
|
+
org_id = get_org_id()
|
|
2889
|
+
if org_id is not None:
|
|
2890
|
+
params["orgId"] = org_id
|
|
2891
|
+
try:
|
|
2892
|
+
result = api.session.rest_get(url, params=params)
|
|
2893
|
+
except WebexError as e:
|
|
2894
|
+
handle_rest_error(e)
|
|
2895
|
+
if output == "json":
|
|
2896
|
+
print_json(result)
|
|
2897
|
+
else:
|
|
2898
|
+
if isinstance(result, dict):
|
|
2899
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2900
|
+
elif isinstance(result, list):
|
|
2901
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2902
|
+
else:
|
|
2903
|
+
print_json(result)
|
|
2904
|
+
|
|
2905
|
+
|
|
2906
|
+
|
|
2907
|
+
@app.command("update-criteria-priority-alert")
|
|
2908
|
+
def update_criteria_priority_alert(
|
|
2909
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2910
|
+
id: str = typer.Argument(help="id"),
|
|
2911
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the pr"),
|
|
2912
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2913
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
2914
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2915
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers."),
|
|
2916
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2917
|
+
notification_enabled: bool = typer.Option(None, "--notification-enabled/--no-notification-enabled", help="When set to `true` priority alerting criteria is enabled for"),
|
|
2918
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2919
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2920
|
+
):
|
|
2921
|
+
"""Modify Priority Alert Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"notificationEnabled":true}'."""
|
|
2922
|
+
api = get_api(debug=debug)
|
|
2923
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/priorityAlert/criteria/{id}"
|
|
2924
|
+
params = {}
|
|
2925
|
+
org_id = get_org_id()
|
|
2926
|
+
if org_id is not None:
|
|
2927
|
+
params["orgId"] = org_id
|
|
2928
|
+
if json_body:
|
|
2929
|
+
body = json.loads(json_body)
|
|
2930
|
+
else:
|
|
2931
|
+
body = {}
|
|
2932
|
+
if schedule_name is not None:
|
|
2933
|
+
body["scheduleName"] = schedule_name
|
|
2934
|
+
if schedule_type is not None:
|
|
2935
|
+
body["scheduleType"] = schedule_type
|
|
2936
|
+
if schedule_level is not None:
|
|
2937
|
+
body["scheduleLevel"] = schedule_level
|
|
2938
|
+
if calls_from is not None:
|
|
2939
|
+
body["callsFrom"] = calls_from
|
|
2940
|
+
if anonymous_callers_enabled is not None:
|
|
2941
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2942
|
+
if unavailable_callers_enabled is not None:
|
|
2943
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2944
|
+
if notification_enabled is not None:
|
|
2945
|
+
body["notificationEnabled"] = notification_enabled
|
|
2946
|
+
try:
|
|
2947
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
2948
|
+
except WebexError as e:
|
|
2949
|
+
handle_rest_error(e)
|
|
2950
|
+
typer.echo(f"Updated.")
|
|
2951
|
+
|
|
2952
|
+
|
|
2953
|
+
|
|
2954
|
+
@app.command("delete-criteria-priority-alert")
|
|
2955
|
+
def delete_criteria_priority_alert(
|
|
2956
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2957
|
+
id: str = typer.Argument(help="id"),
|
|
2958
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2959
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2960
|
+
):
|
|
2961
|
+
"""Delete Priority Alert Criteria for a Workspace."""
|
|
2962
|
+
if not force:
|
|
2963
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2964
|
+
api = get_api(debug=debug)
|
|
2965
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/priorityAlert/criteria/{id}"
|
|
2966
|
+
params = {}
|
|
2967
|
+
org_id = get_org_id()
|
|
2968
|
+
if org_id is not None:
|
|
2969
|
+
params["orgId"] = org_id
|
|
2970
|
+
try:
|
|
2971
|
+
api.session.rest_delete(url, params=params)
|
|
2972
|
+
except WebexError as e:
|
|
2973
|
+
handle_rest_error(e)
|
|
2974
|
+
typer.echo(f"Deleted: {id}")
|
|
2975
|
+
|
|
2976
|
+
|
|
2977
|
+
|
|
2978
|
+
@app.command("create-criteria-priority-alert")
|
|
2979
|
+
def create_criteria_priority_alert(
|
|
2980
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
2981
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="(required) Name of the location's schedule which determines when the pr"),
|
|
2982
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="(required) Choices: businessHours, holidays"),
|
|
2983
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="(required) Choices: GROUP"),
|
|
2984
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2985
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables calls from anonymous callers. Value for"),
|
|
2986
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables calls even if callers are unavailable."),
|
|
2987
|
+
notification_enabled: bool = typer.Option(None, "--notification-enabled/--no-notification-enabled", help="(required) When set to `true` priority alerting criteria is enabled for"),
|
|
2988
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2989
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2990
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2991
|
+
):
|
|
2992
|
+
"""Create Priority Alert Criteria for a Workspace\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","callsFrom":"ANY_PHONE_NUMBER","notificationEnabled":true,"anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2993
|
+
api = get_api(debug=debug)
|
|
2994
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/priorityAlert/criteria"
|
|
2995
|
+
params = {}
|
|
2996
|
+
org_id = get_org_id()
|
|
2997
|
+
if org_id is not None:
|
|
2998
|
+
params["orgId"] = org_id
|
|
2999
|
+
if json_body:
|
|
3000
|
+
body = json.loads(json_body)
|
|
3001
|
+
else:
|
|
3002
|
+
body = {}
|
|
3003
|
+
if schedule_name is not None:
|
|
3004
|
+
body["scheduleName"] = schedule_name
|
|
3005
|
+
if schedule_type is not None:
|
|
3006
|
+
body["scheduleType"] = schedule_type
|
|
3007
|
+
if schedule_level is not None:
|
|
3008
|
+
body["scheduleLevel"] = schedule_level
|
|
3009
|
+
if calls_from is not None:
|
|
3010
|
+
body["callsFrom"] = calls_from
|
|
3011
|
+
if anonymous_callers_enabled is not None:
|
|
3012
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3013
|
+
if unavailable_callers_enabled is not None:
|
|
3014
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3015
|
+
if notification_enabled is not None:
|
|
3016
|
+
body["notificationEnabled"] = notification_enabled
|
|
3017
|
+
_missing = [f for f in ['scheduleName', 'scheduleType', 'scheduleLevel', 'callsFrom', 'notificationEnabled'] if f not in body or body[f] is None]
|
|
3018
|
+
if _missing:
|
|
3019
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
3020
|
+
raise typer.Exit(1)
|
|
3021
|
+
try:
|
|
3022
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
3023
|
+
except WebexError as e:
|
|
3024
|
+
handle_rest_error(e)
|
|
3025
|
+
if output == "json":
|
|
3026
|
+
print_json(result)
|
|
3027
|
+
elif isinstance(result, dict) and "id" in result:
|
|
3028
|
+
typer.echo(f"Created: {result['id']}")
|
|
3029
|
+
elif not result or result == {}:
|
|
3030
|
+
typer.echo("Created.")
|
|
3031
|
+
else:
|
|
3032
|
+
print_json(result)
|
|
3033
|
+
|
|
3034
|
+
|
|
3035
|
+
|
|
3036
|
+
@app.command("list-selective-forward")
|
|
3037
|
+
def list_selective_forward(
|
|
3038
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3039
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3040
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3041
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3042
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3043
|
+
):
|
|
3044
|
+
"""Retrieve Selective Forward Settings for a Workspace."""
|
|
3045
|
+
api = get_api(debug=debug)
|
|
3046
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveForward"
|
|
3047
|
+
params = {}
|
|
3048
|
+
if limit > 0:
|
|
3049
|
+
params["max"] = limit
|
|
3050
|
+
if offset > 0:
|
|
3051
|
+
params["start"] = offset
|
|
3052
|
+
org_id = get_org_id()
|
|
3053
|
+
if org_id is not None:
|
|
3054
|
+
params["orgId"] = org_id
|
|
3055
|
+
result = None
|
|
3056
|
+
try:
|
|
3057
|
+
result = api.session.rest_get(url, params=params)
|
|
3058
|
+
except WebexError as e:
|
|
3059
|
+
handle_rest_error(e)
|
|
3060
|
+
result = result or []
|
|
3061
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3062
|
+
if output == "json":
|
|
3063
|
+
print_json(items)
|
|
3064
|
+
else:
|
|
3065
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3066
|
+
|
|
3067
|
+
|
|
3068
|
+
|
|
3069
|
+
@app.command("update-selective-forward")
|
|
3070
|
+
def update_selective_forward(
|
|
3071
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3072
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Selective Forward feature is enabled."),
|
|
3073
|
+
default_phone_number_to_forward: str = typer.Option(None, "--default-phone-number-to-forward", help="Enter the phone number to forward calls to during this sched"),
|
|
3074
|
+
ring_reminder_enabled: bool = typer.Option(None, "--ring-reminder-enabled/--no-ring-reminder-enabled", help="When `true`, enables a ring reminder for such calls."),
|
|
3075
|
+
destination_voicemail_enabled: bool = typer.Option(None, "--destination-voicemail-enabled/--no-destination-voicemail-enabled", help="Enables forwarding for all calls to voicemail. This option i"),
|
|
3076
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3077
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3078
|
+
):
|
|
3079
|
+
"""Modify Selective Forward Settings for a Workspace."""
|
|
3080
|
+
api = get_api(debug=debug)
|
|
3081
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveForward"
|
|
3082
|
+
params = {}
|
|
3083
|
+
org_id = get_org_id()
|
|
3084
|
+
if org_id is not None:
|
|
3085
|
+
params["orgId"] = org_id
|
|
3086
|
+
if json_body:
|
|
3087
|
+
body = json.loads(json_body)
|
|
3088
|
+
else:
|
|
3089
|
+
body = {}
|
|
3090
|
+
if enabled is not None:
|
|
3091
|
+
body["enabled"] = enabled
|
|
3092
|
+
if default_phone_number_to_forward is not None:
|
|
3093
|
+
body["defaultPhoneNumberToForward"] = default_phone_number_to_forward
|
|
3094
|
+
if ring_reminder_enabled is not None:
|
|
3095
|
+
body["ringReminderEnabled"] = ring_reminder_enabled
|
|
3096
|
+
if destination_voicemail_enabled is not None:
|
|
3097
|
+
body["destinationVoicemailEnabled"] = destination_voicemail_enabled
|
|
3098
|
+
try:
|
|
3099
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
3100
|
+
except WebexError as e:
|
|
3101
|
+
handle_rest_error(e)
|
|
3102
|
+
typer.echo(f"Updated.")
|
|
3103
|
+
|
|
3104
|
+
|
|
3105
|
+
|
|
3106
|
+
@app.command("show-criteria-selective-forward")
|
|
3107
|
+
def show_criteria_selective_forward(
|
|
3108
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3109
|
+
id: str = typer.Argument(help="id"),
|
|
3110
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
3111
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3112
|
+
):
|
|
3113
|
+
"""Retrieve Selective Forward Criteria for a Workspace."""
|
|
3114
|
+
api = get_api(debug=debug)
|
|
3115
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveForward/criteria/{id}"
|
|
3116
|
+
params = {}
|
|
3117
|
+
org_id = get_org_id()
|
|
3118
|
+
if org_id is not None:
|
|
3119
|
+
params["orgId"] = org_id
|
|
3120
|
+
try:
|
|
3121
|
+
result = api.session.rest_get(url, params=params)
|
|
3122
|
+
except WebexError as e:
|
|
3123
|
+
handle_rest_error(e)
|
|
3124
|
+
if output == "json":
|
|
3125
|
+
print_json(result)
|
|
3126
|
+
else:
|
|
3127
|
+
if isinstance(result, dict):
|
|
3128
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
3129
|
+
elif isinstance(result, list):
|
|
3130
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
3131
|
+
else:
|
|
3132
|
+
print_json(result)
|
|
3133
|
+
|
|
3134
|
+
|
|
3135
|
+
|
|
3136
|
+
@app.command("update-criteria-selective-forward")
|
|
3137
|
+
def update_criteria_selective_forward(
|
|
3138
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3139
|
+
id: str = typer.Argument(help="id"),
|
|
3140
|
+
forward_to_phone_number: str = typer.Option(None, "--forward-to-phone-number", help="Phone number to forward calls to during this schedule."),
|
|
3141
|
+
destination_voicemail_enabled: bool = typer.Option(None, "--destination-voicemail-enabled/--no-destination-voicemail-enabled", help="Enables forwarding for all calls to voicemail. This option i"),
|
|
3142
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
3143
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
3144
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
3145
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, ANY_INTERNAL, ANY_EXTERNAL"),
|
|
3146
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables selective forward to calls from anonymo"),
|
|
3147
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables selective forward to calls if the calle"),
|
|
3148
|
+
forward_enabled: bool = typer.Option(None, "--forward-enabled/--no-forward-enabled", help="Indicates whether the calls, that fit within these parameter"),
|
|
3149
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3150
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3151
|
+
):
|
|
3152
|
+
"""Modify Selective Forward Criteria for a Workspace\n\nExample --json-body:\n '{"callsFrom":"ANY_PHONE_NUMBER","forwardToPhoneNumber":"...","destinationVoicemailEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","anonymousCallersEnabled":true,"unavailableCallersEnabled":true}'."""
|
|
3153
|
+
api = get_api(debug=debug)
|
|
3154
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveForward/criteria/{id}"
|
|
3155
|
+
params = {}
|
|
3156
|
+
org_id = get_org_id()
|
|
3157
|
+
if org_id is not None:
|
|
3158
|
+
params["orgId"] = org_id
|
|
3159
|
+
if json_body:
|
|
3160
|
+
body = json.loads(json_body)
|
|
3161
|
+
else:
|
|
3162
|
+
body = {}
|
|
3163
|
+
if forward_to_phone_number is not None:
|
|
3164
|
+
body["forwardToPhoneNumber"] = forward_to_phone_number
|
|
3165
|
+
if destination_voicemail_enabled is not None:
|
|
3166
|
+
body["destinationVoicemailEnabled"] = destination_voicemail_enabled
|
|
3167
|
+
if schedule_name is not None:
|
|
3168
|
+
body["scheduleName"] = schedule_name
|
|
3169
|
+
if schedule_type is not None:
|
|
3170
|
+
body["scheduleType"] = schedule_type
|
|
3171
|
+
if schedule_level is not None:
|
|
3172
|
+
body["scheduleLevel"] = schedule_level
|
|
3173
|
+
if calls_from is not None:
|
|
3174
|
+
body["callsFrom"] = calls_from
|
|
3175
|
+
if anonymous_callers_enabled is not None:
|
|
3176
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3177
|
+
if unavailable_callers_enabled is not None:
|
|
3178
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3179
|
+
if forward_enabled is not None:
|
|
3180
|
+
body["forwardEnabled"] = forward_enabled
|
|
3181
|
+
try:
|
|
3182
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
3183
|
+
except WebexError as e:
|
|
3184
|
+
handle_rest_error(e)
|
|
3185
|
+
typer.echo(f"Updated.")
|
|
3186
|
+
|
|
3187
|
+
|
|
3188
|
+
|
|
3189
|
+
@app.command("delete-criteria-selective-forward")
|
|
3190
|
+
def delete_criteria_selective_forward(
|
|
3191
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3192
|
+
id: str = typer.Argument(help="id"),
|
|
3193
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
3194
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3195
|
+
):
|
|
3196
|
+
"""Delete Selective Forward Criteria for a Workspace."""
|
|
3197
|
+
if not force:
|
|
3198
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
3199
|
+
api = get_api(debug=debug)
|
|
3200
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveForward/criteria/{id}"
|
|
3201
|
+
params = {}
|
|
3202
|
+
org_id = get_org_id()
|
|
3203
|
+
if org_id is not None:
|
|
3204
|
+
params["orgId"] = org_id
|
|
3205
|
+
try:
|
|
3206
|
+
api.session.rest_delete(url, params=params)
|
|
3207
|
+
except WebexError as e:
|
|
3208
|
+
handle_rest_error(e)
|
|
3209
|
+
typer.echo(f"Deleted: {id}")
|
|
3210
|
+
|
|
3211
|
+
|
|
3212
|
+
|
|
3213
|
+
@app.command("create-criteria-selective-forward")
|
|
3214
|
+
def create_criteria_selective_forward(
|
|
3215
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3216
|
+
forward_to_phone_number: str = typer.Option(None, "--forward-to-phone-number", help="Phone number to forward calls to during this schedule."),
|
|
3217
|
+
destination_voicemail_enabled: bool = typer.Option(None, "--destination-voicemail-enabled/--no-destination-voicemail-enabled", help="Enables forwarding for all calls to voicemail. This option i"),
|
|
3218
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
3219
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
3220
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
3221
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, ANY_INTERNAL, ANY_EXTERNAL"),
|
|
3222
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, enables selective forward to calls from anonymo"),
|
|
3223
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, enables selective forward to calls if the calle"),
|
|
3224
|
+
forward_enabled: bool = typer.Option(None, "--forward-enabled/--no-forward-enabled", help="Indicates whether the calls, that fit within these parameter"),
|
|
3225
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3226
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
3227
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3228
|
+
):
|
|
3229
|
+
"""Create Selective Forward Criteria for a Workspace\n\nExample --json-body:\n '{"callsFrom":"ANY_PHONE_NUMBER","forwardToPhoneNumber":"...","destinationVoicemailEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"GROUP","anonymousCallersEnabled":true,"unavailableCallersEnabled":true}'."""
|
|
3230
|
+
api = get_api(debug=debug)
|
|
3231
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/selectiveForward/criteria"
|
|
3232
|
+
params = {}
|
|
3233
|
+
org_id = get_org_id()
|
|
3234
|
+
if org_id is not None:
|
|
3235
|
+
params["orgId"] = org_id
|
|
3236
|
+
if json_body:
|
|
3237
|
+
body = json.loads(json_body)
|
|
3238
|
+
else:
|
|
3239
|
+
body = {}
|
|
3240
|
+
if forward_to_phone_number is not None:
|
|
3241
|
+
body["forwardToPhoneNumber"] = forward_to_phone_number
|
|
3242
|
+
if destination_voicemail_enabled is not None:
|
|
3243
|
+
body["destinationVoicemailEnabled"] = destination_voicemail_enabled
|
|
3244
|
+
if schedule_name is not None:
|
|
3245
|
+
body["scheduleName"] = schedule_name
|
|
3246
|
+
if schedule_type is not None:
|
|
3247
|
+
body["scheduleType"] = schedule_type
|
|
3248
|
+
if schedule_level is not None:
|
|
3249
|
+
body["scheduleLevel"] = schedule_level
|
|
3250
|
+
if calls_from is not None:
|
|
3251
|
+
body["callsFrom"] = calls_from
|
|
3252
|
+
if anonymous_callers_enabled is not None:
|
|
3253
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3254
|
+
if unavailable_callers_enabled is not None:
|
|
3255
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3256
|
+
if forward_enabled is not None:
|
|
3257
|
+
body["forwardEnabled"] = forward_enabled
|
|
3258
|
+
_missing = [f for f in ['callsFrom'] if f not in body or body[f] is None]
|
|
3259
|
+
if _missing:
|
|
3260
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
3261
|
+
raise typer.Exit(1)
|
|
3262
|
+
try:
|
|
3263
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
3264
|
+
except WebexError as e:
|
|
3265
|
+
handle_rest_error(e)
|
|
3266
|
+
if output == "json":
|
|
3267
|
+
print_json(result)
|
|
3268
|
+
elif isinstance(result, dict) and "id" in result:
|
|
3269
|
+
typer.echo(f"Created: {result['id']}")
|
|
3270
|
+
elif not result or result == {}:
|
|
3271
|
+
typer.echo("Created.")
|
|
3272
|
+
else:
|
|
3273
|
+
print_json(result)
|
|
3274
|
+
|
|
3275
|
+
|
|
3276
|
+
|
|
3277
|
+
@app.command("list-available-numbers-fax-message")
|
|
3278
|
+
def list_available_numbers_fax_message(
|
|
3279
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3280
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
3281
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3282
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3283
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3284
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3285
|
+
):
|
|
3286
|
+
"""Get Workspace Fax Message Available Phone Numbers."""
|
|
3287
|
+
api = get_api(debug=debug)
|
|
3288
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/faxMessage/availableNumbers"
|
|
3289
|
+
params = {}
|
|
3290
|
+
if phone_number is not None:
|
|
3291
|
+
params["phoneNumber"] = phone_number
|
|
3292
|
+
if limit > 0:
|
|
3293
|
+
params["max"] = limit
|
|
3294
|
+
if offset > 0:
|
|
3295
|
+
params["start"] = offset
|
|
3296
|
+
org_id = get_org_id()
|
|
3297
|
+
if org_id is not None:
|
|
3298
|
+
params["orgId"] = org_id
|
|
3299
|
+
result = None
|
|
3300
|
+
try:
|
|
3301
|
+
result = api.session.rest_get(url, params=params)
|
|
3302
|
+
except WebexError as e:
|
|
3303
|
+
handle_rest_error(e)
|
|
3304
|
+
result = result or []
|
|
3305
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3306
|
+
if output == "json":
|
|
3307
|
+
print_json(items)
|
|
3308
|
+
else:
|
|
3309
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3310
|
+
|
|
3311
|
+
|
|
3312
|
+
|
|
3313
|
+
@app.command("list-available-numbers-secondary")
|
|
3314
|
+
def list_available_numbers_secondary(
|
|
3315
|
+
workspace_id: str = typer.Argument(help="workspaceId"),
|
|
3316
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Filter phone numbers based on the comma-separated list provi"),
|
|
3317
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3318
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3319
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3320
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3321
|
+
):
|
|
3322
|
+
"""Get Workspace Secondary Available Phone Numbers."""
|
|
3323
|
+
api = get_api(debug=debug)
|
|
3324
|
+
url = f"https://webexapis.com/v1/telephony/config/workspaces/{workspace_id}/secondary/availableNumbers"
|
|
3325
|
+
params = {}
|
|
3326
|
+
if phone_number is not None:
|
|
3327
|
+
params["phoneNumber"] = phone_number
|
|
3328
|
+
if limit > 0:
|
|
3329
|
+
params["max"] = limit
|
|
3330
|
+
if offset > 0:
|
|
3331
|
+
params["start"] = offset
|
|
3332
|
+
org_id = get_org_id()
|
|
3333
|
+
if org_id is not None:
|
|
3334
|
+
params["orgId"] = org_id
|
|
3335
|
+
result = None
|
|
3336
|
+
try:
|
|
3337
|
+
result = api.session.rest_get(url, params=params)
|
|
3338
|
+
except WebexError as e:
|
|
3339
|
+
handle_rest_error(e)
|
|
3340
|
+
result = result or []
|
|
3341
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3342
|
+
if output == "json":
|
|
3343
|
+
print_json(items)
|
|
3344
|
+
else:
|
|
3345
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3346
|
+
|
|
3347
|
+
|