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,3577 @@
|
|
|
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
|
+
|
|
7
|
+
|
|
8
|
+
app = typer.Typer(help="Manage Webex Calling my-call-settings.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
14
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
15
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
16
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
17
|
+
):
|
|
18
|
+
"""Get List Available Preferred Answer Endpoints."""
|
|
19
|
+
api = get_api(debug=debug)
|
|
20
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/availablePreferredAnswerEndpoints"
|
|
21
|
+
params = {}
|
|
22
|
+
if limit > 0:
|
|
23
|
+
params["max"] = limit
|
|
24
|
+
if offset > 0:
|
|
25
|
+
params["start"] = offset
|
|
26
|
+
result = None
|
|
27
|
+
try:
|
|
28
|
+
result = api.session.rest_get(url, params=params)
|
|
29
|
+
except WebexError as e:
|
|
30
|
+
handle_rest_error(e)
|
|
31
|
+
result = result or []
|
|
32
|
+
items = result.get("endpoints", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
33
|
+
if output == "json":
|
|
34
|
+
print_json(items)
|
|
35
|
+
else:
|
|
36
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@app.command("list-available-preferred-answer-endpoints")
|
|
41
|
+
def list_available_preferred_answer_endpoints(
|
|
42
|
+
line_owner_id: str = typer.Argument(help="lineOwnerId"),
|
|
43
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
44
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
45
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
46
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
47
|
+
):
|
|
48
|
+
"""Get My Secondary Line Owner's Available Preferred Answer Endpoint List."""
|
|
49
|
+
api = get_api(debug=debug)
|
|
50
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{line_owner_id}/availablePreferredAnswerEndpoints"
|
|
51
|
+
params = {}
|
|
52
|
+
if limit > 0:
|
|
53
|
+
params["max"] = limit
|
|
54
|
+
if offset > 0:
|
|
55
|
+
params["start"] = offset
|
|
56
|
+
result = None
|
|
57
|
+
try:
|
|
58
|
+
result = api.session.rest_get(url, params=params)
|
|
59
|
+
except WebexError as e:
|
|
60
|
+
handle_rest_error(e)
|
|
61
|
+
result = result or []
|
|
62
|
+
items = result.get("endpoints", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
63
|
+
if output == "json":
|
|
64
|
+
print_json(items)
|
|
65
|
+
else:
|
|
66
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@app.command("show")
|
|
71
|
+
def show(
|
|
72
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
73
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
74
|
+
):
|
|
75
|
+
"""Get Preferred Answer Endpoint."""
|
|
76
|
+
api = get_api(debug=debug)
|
|
77
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/preferredAnswerEndpoint"
|
|
78
|
+
try:
|
|
79
|
+
result = api.session.rest_get(url)
|
|
80
|
+
except WebexError as e:
|
|
81
|
+
handle_rest_error(e)
|
|
82
|
+
if output == "json":
|
|
83
|
+
print_json(result)
|
|
84
|
+
else:
|
|
85
|
+
if isinstance(result, dict):
|
|
86
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
87
|
+
elif isinstance(result, list):
|
|
88
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
89
|
+
else:
|
|
90
|
+
print_json(result)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@app.command("update")
|
|
95
|
+
def update(
|
|
96
|
+
preferred_answer_endpoint_id: str = typer.Option(None, "--preferred-answer-endpoint-id", help="Person’s preferred answer endpoint."),
|
|
97
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
98
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
99
|
+
):
|
|
100
|
+
"""Modify Preferred Answer Endpoint."""
|
|
101
|
+
api = get_api(debug=debug)
|
|
102
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/preferredAnswerEndpoint"
|
|
103
|
+
if json_body:
|
|
104
|
+
body = json.loads(json_body)
|
|
105
|
+
else:
|
|
106
|
+
body = {}
|
|
107
|
+
if preferred_answer_endpoint_id is not None:
|
|
108
|
+
body["preferredAnswerEndpointId"] = preferred_answer_endpoint_id
|
|
109
|
+
try:
|
|
110
|
+
result = api.session.rest_put(url, json=body)
|
|
111
|
+
except WebexError as e:
|
|
112
|
+
handle_rest_error(e)
|
|
113
|
+
typer.echo(f"Updated.")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@app.command("show-preferred-answer-endpoint")
|
|
118
|
+
def show_preferred_answer_endpoint(
|
|
119
|
+
line_owner_id: str = typer.Argument(help="lineOwnerId"),
|
|
120
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
121
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
122
|
+
):
|
|
123
|
+
"""Get My Secondary Line Owner's Preferred Answer Endpoint."""
|
|
124
|
+
api = get_api(debug=debug)
|
|
125
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{line_owner_id}/preferredAnswerEndpoint"
|
|
126
|
+
try:
|
|
127
|
+
result = api.session.rest_get(url)
|
|
128
|
+
except WebexError as e:
|
|
129
|
+
handle_rest_error(e)
|
|
130
|
+
if output == "json":
|
|
131
|
+
print_json(result)
|
|
132
|
+
else:
|
|
133
|
+
if isinstance(result, dict):
|
|
134
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
135
|
+
elif isinstance(result, list):
|
|
136
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
137
|
+
else:
|
|
138
|
+
print_json(result)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@app.command("update-preferred-answer-endpoint")
|
|
143
|
+
def update_preferred_answer_endpoint(
|
|
144
|
+
line_owner_id: str = typer.Argument(help="lineOwnerId"),
|
|
145
|
+
preferred_answer_endpoint_id: str = typer.Option(None, "--preferred-answer-endpoint-id", help="Person’s preferred answer endpoint."),
|
|
146
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
147
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
148
|
+
):
|
|
149
|
+
"""Modify My Secondary Line Owner's Preferred Answer Endpoint."""
|
|
150
|
+
api = get_api(debug=debug)
|
|
151
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{line_owner_id}/preferredAnswerEndpoint"
|
|
152
|
+
if json_body:
|
|
153
|
+
body = json.loads(json_body)
|
|
154
|
+
else:
|
|
155
|
+
body = {}
|
|
156
|
+
if preferred_answer_endpoint_id is not None:
|
|
157
|
+
body["preferredAnswerEndpointId"] = preferred_answer_endpoint_id
|
|
158
|
+
try:
|
|
159
|
+
result = api.session.rest_put(url, json=body)
|
|
160
|
+
except WebexError as e:
|
|
161
|
+
handle_rest_error(e)
|
|
162
|
+
typer.echo(f"Updated.")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@app.command("show-webex-go-override")
|
|
167
|
+
def show_webex_go_override(
|
|
168
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
169
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
170
|
+
):
|
|
171
|
+
"""Get My WebexGoOverride Settings."""
|
|
172
|
+
api = get_api(debug=debug)
|
|
173
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/webexGoOverride"
|
|
174
|
+
try:
|
|
175
|
+
result = api.session.rest_get(url)
|
|
176
|
+
except WebexError as e:
|
|
177
|
+
handle_rest_error(e)
|
|
178
|
+
if output == "json":
|
|
179
|
+
print_json(result)
|
|
180
|
+
else:
|
|
181
|
+
if isinstance(result, dict):
|
|
182
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
183
|
+
elif isinstance(result, list):
|
|
184
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
185
|
+
else:
|
|
186
|
+
print_json(result)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
@app.command("update-webex-go-override")
|
|
191
|
+
def update_webex_go_override(
|
|
192
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="True if the \"Mobile User Aware\" override setting for Do Not"),
|
|
193
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
194
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
195
|
+
):
|
|
196
|
+
"""Modify My WebexGoOverride Settings."""
|
|
197
|
+
api = get_api(debug=debug)
|
|
198
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/webexGoOverride"
|
|
199
|
+
if json_body:
|
|
200
|
+
body = json.loads(json_body)
|
|
201
|
+
else:
|
|
202
|
+
body = {}
|
|
203
|
+
if enabled is not None:
|
|
204
|
+
body["enabled"] = enabled
|
|
205
|
+
try:
|
|
206
|
+
result = api.session.rest_put(url, json=body)
|
|
207
|
+
except WebexError as e:
|
|
208
|
+
handle_rest_error(e)
|
|
209
|
+
typer.echo(f"Updated.")
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@app.command("show-caller-id-settings")
|
|
214
|
+
def show_caller_id_settings(
|
|
215
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
216
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
217
|
+
):
|
|
218
|
+
"""Get My Caller ID Settings."""
|
|
219
|
+
api = get_api(debug=debug)
|
|
220
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callerId"
|
|
221
|
+
try:
|
|
222
|
+
result = api.session.rest_get(url)
|
|
223
|
+
except WebexError as e:
|
|
224
|
+
handle_rest_error(e)
|
|
225
|
+
if output == "json":
|
|
226
|
+
print_json(result)
|
|
227
|
+
else:
|
|
228
|
+
if isinstance(result, dict):
|
|
229
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
230
|
+
elif isinstance(result, list):
|
|
231
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
232
|
+
else:
|
|
233
|
+
print_json(result)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@app.command("update-caller-id-settings")
|
|
238
|
+
def update_caller_id_settings(
|
|
239
|
+
calling_line_id_delivery_blocking_enabled: bool = typer.Option(None, "--calling-line-id-delivery-blocking-enabled/--no-calling-line-id-delivery-blocking-enabled", help="If `true`, the user's name and phone number are not shown to"),
|
|
240
|
+
connected_line_identification_restriction_enabled: bool = typer.Option(None, "--connected-line-identification-restriction-enabled/--no-connected-line-identification-restriction-enabled", help="If `true`, the user's name and phone number are not shown wh"),
|
|
241
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
242
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
243
|
+
):
|
|
244
|
+
"""Modify My Caller ID Settings."""
|
|
245
|
+
api = get_api(debug=debug)
|
|
246
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callerId"
|
|
247
|
+
if json_body:
|
|
248
|
+
body = json.loads(json_body)
|
|
249
|
+
else:
|
|
250
|
+
body = {}
|
|
251
|
+
if calling_line_id_delivery_blocking_enabled is not None:
|
|
252
|
+
body["callingLineIdDeliveryBlockingEnabled"] = calling_line_id_delivery_blocking_enabled
|
|
253
|
+
if connected_line_identification_restriction_enabled is not None:
|
|
254
|
+
body["connectedLineIdentificationRestrictionEnabled"] = connected_line_identification_restriction_enabled
|
|
255
|
+
try:
|
|
256
|
+
result = api.session.rest_put(url, json=body)
|
|
257
|
+
except WebexError as e:
|
|
258
|
+
handle_rest_error(e)
|
|
259
|
+
typer.echo(f"Updated.")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@app.command("show-caller-id-secondary-lines")
|
|
264
|
+
def show_caller_id_secondary_lines(
|
|
265
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
266
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
267
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
268
|
+
):
|
|
269
|
+
"""Get My Secondary Line Owner Caller ID Settings."""
|
|
270
|
+
api = get_api(debug=debug)
|
|
271
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callerId"
|
|
272
|
+
try:
|
|
273
|
+
result = api.session.rest_get(url)
|
|
274
|
+
except WebexError as e:
|
|
275
|
+
handle_rest_error(e)
|
|
276
|
+
if output == "json":
|
|
277
|
+
print_json(result)
|
|
278
|
+
else:
|
|
279
|
+
if isinstance(result, dict):
|
|
280
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
281
|
+
elif isinstance(result, list):
|
|
282
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
283
|
+
else:
|
|
284
|
+
print_json(result)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
@app.command("update-caller-id-secondary-lines")
|
|
289
|
+
def update_caller_id_secondary_lines(
|
|
290
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
291
|
+
calling_line_id_delivery_blocking_enabled: bool = typer.Option(None, "--calling-line-id-delivery-blocking-enabled/--no-calling-line-id-delivery-blocking-enabled", help="If `true`, the user's name and phone number are not shown to"),
|
|
292
|
+
connected_line_identification_restriction_enabled: bool = typer.Option(None, "--connected-line-identification-restriction-enabled/--no-connected-line-identification-restriction-enabled", help="If `true`, the user's name and phone number are not shown wh"),
|
|
293
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
294
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
295
|
+
):
|
|
296
|
+
"""Modify My Secondary Line Owner Caller ID Settings."""
|
|
297
|
+
api = get_api(debug=debug)
|
|
298
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callerId"
|
|
299
|
+
if json_body:
|
|
300
|
+
body = json.loads(json_body)
|
|
301
|
+
else:
|
|
302
|
+
body = {}
|
|
303
|
+
if calling_line_id_delivery_blocking_enabled is not None:
|
|
304
|
+
body["callingLineIdDeliveryBlockingEnabled"] = calling_line_id_delivery_blocking_enabled
|
|
305
|
+
if connected_line_identification_restriction_enabled is not None:
|
|
306
|
+
body["connectedLineIdentificationRestrictionEnabled"] = connected_line_identification_restriction_enabled
|
|
307
|
+
try:
|
|
308
|
+
result = api.session.rest_put(url, json=body)
|
|
309
|
+
except WebexError as e:
|
|
310
|
+
handle_rest_error(e)
|
|
311
|
+
typer.echo(f"Updated.")
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
@app.command("show-selected-caller-id-settings")
|
|
316
|
+
def show_selected_caller_id_settings(
|
|
317
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
318
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
319
|
+
):
|
|
320
|
+
"""Read My Selected Caller ID Settings."""
|
|
321
|
+
api = get_api(debug=debug)
|
|
322
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectedCallerId"
|
|
323
|
+
try:
|
|
324
|
+
result = api.session.rest_get(url)
|
|
325
|
+
except WebexError as e:
|
|
326
|
+
handle_rest_error(e)
|
|
327
|
+
if output == "json":
|
|
328
|
+
print_json(result)
|
|
329
|
+
else:
|
|
330
|
+
if isinstance(result, dict):
|
|
331
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
332
|
+
elif isinstance(result, list):
|
|
333
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
334
|
+
else:
|
|
335
|
+
print_json(result)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@app.command("update-selected-caller-id-settings")
|
|
340
|
+
def update_selected_caller_id_settings(
|
|
341
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
342
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
343
|
+
):
|
|
344
|
+
"""Configure My Selected Caller ID Settings\n\nExample --json-body:\n '{"selected":{"type":"DEFAULT_CLID","id":"...","directNumber":"..."}}'."""
|
|
345
|
+
api = get_api(debug=debug)
|
|
346
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectedCallerId"
|
|
347
|
+
if json_body:
|
|
348
|
+
body = json.loads(json_body)
|
|
349
|
+
else:
|
|
350
|
+
body = {}
|
|
351
|
+
try:
|
|
352
|
+
result = api.session.rest_put(url, json=body)
|
|
353
|
+
except WebexError as e:
|
|
354
|
+
handle_rest_error(e)
|
|
355
|
+
typer.echo(f"Updated.")
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@app.command("show-selected-caller-id-secondary-lines")
|
|
360
|
+
def show_selected_caller_id_secondary_lines(
|
|
361
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
362
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
363
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
364
|
+
):
|
|
365
|
+
"""Get My Secondary Line Owner's Selected Caller ID Settings."""
|
|
366
|
+
api = get_api(debug=debug)
|
|
367
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/selectedCallerId"
|
|
368
|
+
try:
|
|
369
|
+
result = api.session.rest_get(url)
|
|
370
|
+
except WebexError as e:
|
|
371
|
+
handle_rest_error(e)
|
|
372
|
+
if output == "json":
|
|
373
|
+
print_json(result)
|
|
374
|
+
else:
|
|
375
|
+
if isinstance(result, dict):
|
|
376
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
377
|
+
elif isinstance(result, list):
|
|
378
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
379
|
+
else:
|
|
380
|
+
print_json(result)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
@app.command("update-selected-caller-id-secondary-lines")
|
|
385
|
+
def update_selected_caller_id_secondary_lines(
|
|
386
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
387
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
388
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
389
|
+
):
|
|
390
|
+
"""Modify My Secondary Line Owner's Selected Caller ID Settings\n\nExample --json-body:\n '{"selected":{"type":"DEFAULT_CLID","id":"...","directNumber":"..."}}'."""
|
|
391
|
+
api = get_api(debug=debug)
|
|
392
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/selectedCallerId"
|
|
393
|
+
if json_body:
|
|
394
|
+
body = json.loads(json_body)
|
|
395
|
+
else:
|
|
396
|
+
body = {}
|
|
397
|
+
try:
|
|
398
|
+
result = api.session.rest_put(url, json=body)
|
|
399
|
+
except WebexError as e:
|
|
400
|
+
handle_rest_error(e)
|
|
401
|
+
typer.echo(f"Updated.")
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@app.command("list-available-caller-ids-settings")
|
|
406
|
+
def list_available_caller_ids_settings(
|
|
407
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
408
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
409
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
410
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
411
|
+
):
|
|
412
|
+
"""Get My Available Caller ID List."""
|
|
413
|
+
api = get_api(debug=debug)
|
|
414
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/availableCallerIds"
|
|
415
|
+
params = {}
|
|
416
|
+
if limit > 0:
|
|
417
|
+
params["max"] = limit
|
|
418
|
+
if offset > 0:
|
|
419
|
+
params["start"] = offset
|
|
420
|
+
result = None
|
|
421
|
+
try:
|
|
422
|
+
result = api.session.rest_get(url, params=params)
|
|
423
|
+
except WebexError as e:
|
|
424
|
+
handle_rest_error(e)
|
|
425
|
+
result = result or []
|
|
426
|
+
items = result.get("availableCallerIds", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
427
|
+
if output == "json":
|
|
428
|
+
print_json(items)
|
|
429
|
+
else:
|
|
430
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
@app.command("list-available-caller-ids-secondary-lines")
|
|
435
|
+
def list_available_caller_ids_secondary_lines(
|
|
436
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
437
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
438
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
439
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
440
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
441
|
+
):
|
|
442
|
+
"""Get My Secondary Line Owner's Available Caller ID List."""
|
|
443
|
+
api = get_api(debug=debug)
|
|
444
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/availableCallerIds"
|
|
445
|
+
params = {}
|
|
446
|
+
if limit > 0:
|
|
447
|
+
params["max"] = limit
|
|
448
|
+
if offset > 0:
|
|
449
|
+
params["start"] = offset
|
|
450
|
+
result = None
|
|
451
|
+
try:
|
|
452
|
+
result = api.session.rest_get(url, params=params)
|
|
453
|
+
except WebexError as e:
|
|
454
|
+
handle_rest_error(e)
|
|
455
|
+
result = result or []
|
|
456
|
+
items = result.get("availableCallerIds", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
457
|
+
if output == "json":
|
|
458
|
+
print_json(items)
|
|
459
|
+
else:
|
|
460
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
@app.command("list-endpoints")
|
|
465
|
+
def list_endpoints(
|
|
466
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
467
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
468
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
469
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
470
|
+
):
|
|
471
|
+
"""Read the List of My Endpoints."""
|
|
472
|
+
api = get_api(debug=debug)
|
|
473
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/endpoints"
|
|
474
|
+
params = {}
|
|
475
|
+
if limit > 0:
|
|
476
|
+
params["max"] = limit
|
|
477
|
+
if offset > 0:
|
|
478
|
+
params["start"] = offset
|
|
479
|
+
result = None
|
|
480
|
+
try:
|
|
481
|
+
result = api.session.rest_get(url, params=params)
|
|
482
|
+
except WebexError as e:
|
|
483
|
+
handle_rest_error(e)
|
|
484
|
+
result = result or []
|
|
485
|
+
items = result.get("endpoints", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
486
|
+
if output == "json":
|
|
487
|
+
print_json(items)
|
|
488
|
+
else:
|
|
489
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
@app.command("show-endpoints")
|
|
494
|
+
def show_endpoints(
|
|
495
|
+
endpoint_id: str = typer.Argument(help="endpointId"),
|
|
496
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
497
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
498
|
+
):
|
|
499
|
+
"""Get My Endpoints Details."""
|
|
500
|
+
api = get_api(debug=debug)
|
|
501
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/endpoints/{endpoint_id}"
|
|
502
|
+
try:
|
|
503
|
+
result = api.session.rest_get(url)
|
|
504
|
+
except WebexError as e:
|
|
505
|
+
handle_rest_error(e)
|
|
506
|
+
if output == "json":
|
|
507
|
+
print_json(result)
|
|
508
|
+
else:
|
|
509
|
+
if isinstance(result, dict):
|
|
510
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
511
|
+
elif isinstance(result, list):
|
|
512
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
513
|
+
else:
|
|
514
|
+
print_json(result)
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
@app.command("update-endpoints")
|
|
519
|
+
def update_endpoints(
|
|
520
|
+
endpoint_id: str = typer.Argument(help="endpointId"),
|
|
521
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
522
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
523
|
+
):
|
|
524
|
+
"""Modify My Endpoints Details\n\nExample --json-body:\n '{"mobilitySettings":{"alertingEnabled":true}}'."""
|
|
525
|
+
api = get_api(debug=debug)
|
|
526
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/endpoints/{endpoint_id}"
|
|
527
|
+
if json_body:
|
|
528
|
+
body = json.loads(json_body)
|
|
529
|
+
else:
|
|
530
|
+
body = {}
|
|
531
|
+
try:
|
|
532
|
+
result = api.session.rest_put(url, json=body)
|
|
533
|
+
except WebexError as e:
|
|
534
|
+
handle_rest_error(e)
|
|
535
|
+
typer.echo(f"Updated.")
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
@app.command("show-call-recording-settings")
|
|
540
|
+
def show_call_recording_settings(
|
|
541
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
542
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
543
|
+
):
|
|
544
|
+
"""Get My Call Recording Settings."""
|
|
545
|
+
api = get_api(debug=debug)
|
|
546
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callRecording"
|
|
547
|
+
try:
|
|
548
|
+
result = api.session.rest_get(url)
|
|
549
|
+
except WebexError as e:
|
|
550
|
+
handle_rest_error(e)
|
|
551
|
+
if output == "json":
|
|
552
|
+
print_json(result)
|
|
553
|
+
else:
|
|
554
|
+
if isinstance(result, dict):
|
|
555
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
556
|
+
elif isinstance(result, list):
|
|
557
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
558
|
+
else:
|
|
559
|
+
print_json(result)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
@app.command("show-call-recording-secondary-lines")
|
|
564
|
+
def show_call_recording_secondary_lines(
|
|
565
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
566
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
567
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
568
|
+
):
|
|
569
|
+
"""Get My Secondary Line Owner's Call Recording Settings."""
|
|
570
|
+
api = get_api(debug=debug)
|
|
571
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callRecording"
|
|
572
|
+
try:
|
|
573
|
+
result = api.session.rest_get(url)
|
|
574
|
+
except WebexError as e:
|
|
575
|
+
handle_rest_error(e)
|
|
576
|
+
if output == "json":
|
|
577
|
+
print_json(result)
|
|
578
|
+
else:
|
|
579
|
+
if isinstance(result, dict):
|
|
580
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
581
|
+
elif isinstance(result, list):
|
|
582
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
583
|
+
else:
|
|
584
|
+
print_json(result)
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
@app.command("show-me")
|
|
589
|
+
def show_me(
|
|
590
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
591
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
592
|
+
):
|
|
593
|
+
"""Get My Own Details."""
|
|
594
|
+
api = get_api(debug=debug)
|
|
595
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me"
|
|
596
|
+
try:
|
|
597
|
+
result = api.session.rest_get(url)
|
|
598
|
+
except WebexError as e:
|
|
599
|
+
handle_rest_error(e)
|
|
600
|
+
if output == "json":
|
|
601
|
+
print_json(result)
|
|
602
|
+
else:
|
|
603
|
+
if isinstance(result, dict):
|
|
604
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
605
|
+
elif isinstance(result, list):
|
|
606
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
607
|
+
else:
|
|
608
|
+
print_json(result)
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
@app.command("list-feature-access-code-settings")
|
|
613
|
+
def list_feature_access_code_settings(
|
|
614
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
615
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
616
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
617
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
618
|
+
):
|
|
619
|
+
"""Get My Feature Access Codes."""
|
|
620
|
+
api = get_api(debug=debug)
|
|
621
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/featureAccessCode"
|
|
622
|
+
params = {}
|
|
623
|
+
if limit > 0:
|
|
624
|
+
params["max"] = limit
|
|
625
|
+
if offset > 0:
|
|
626
|
+
params["start"] = offset
|
|
627
|
+
result = None
|
|
628
|
+
try:
|
|
629
|
+
result = api.session.rest_get(url, params=params)
|
|
630
|
+
except WebexError as e:
|
|
631
|
+
handle_rest_error(e)
|
|
632
|
+
result = result or []
|
|
633
|
+
items = result.get("featureAccessCodeList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
634
|
+
if output == "json":
|
|
635
|
+
print_json(items)
|
|
636
|
+
else:
|
|
637
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
@app.command("list-feature-access-code-secondary-lines")
|
|
642
|
+
def list_feature_access_code_secondary_lines(
|
|
643
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
644
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
645
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
646
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
647
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
648
|
+
):
|
|
649
|
+
"""Get My Feature Access Codes For Secondary Line Owner."""
|
|
650
|
+
api = get_api(debug=debug)
|
|
651
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/featureAccessCode"
|
|
652
|
+
params = {}
|
|
653
|
+
if limit > 0:
|
|
654
|
+
params["max"] = limit
|
|
655
|
+
if offset > 0:
|
|
656
|
+
params["start"] = offset
|
|
657
|
+
result = None
|
|
658
|
+
try:
|
|
659
|
+
result = api.session.rest_get(url, params=params)
|
|
660
|
+
except WebexError as e:
|
|
661
|
+
handle_rest_error(e)
|
|
662
|
+
result = result or []
|
|
663
|
+
items = result.get("featureAccessCodeList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
664
|
+
if output == "json":
|
|
665
|
+
print_json(items)
|
|
666
|
+
else:
|
|
667
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
@app.command("list-assigned-assistants")
|
|
672
|
+
def list_assigned_assistants(
|
|
673
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
674
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
675
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
676
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
677
|
+
):
|
|
678
|
+
"""Get My Executive Assigned Assistants."""
|
|
679
|
+
api = get_api(debug=debug)
|
|
680
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/executive/assignedAssistants"
|
|
681
|
+
params = {}
|
|
682
|
+
if limit > 0:
|
|
683
|
+
params["max"] = limit
|
|
684
|
+
if offset > 0:
|
|
685
|
+
params["start"] = offset
|
|
686
|
+
result = None
|
|
687
|
+
try:
|
|
688
|
+
result = api.session.rest_get(url, params=params)
|
|
689
|
+
except WebexError as e:
|
|
690
|
+
handle_rest_error(e)
|
|
691
|
+
result = result or []
|
|
692
|
+
items = result.get("assistants", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
693
|
+
if output == "json":
|
|
694
|
+
print_json(items)
|
|
695
|
+
else:
|
|
696
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
@app.command("update-assigned-assistants")
|
|
701
|
+
def update_assigned_assistants(
|
|
702
|
+
allow_opt_in_out_enabled: bool = typer.Option(None, "--allow-opt-in-out-enabled/--no-allow-opt-in-out-enabled", help="If `true`, the executive can allow assistants to opt in or o"),
|
|
703
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
704
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
705
|
+
):
|
|
706
|
+
"""Modify My Executive Assigned Assistants\n\nExample --json-body:\n '{"allowOptInOutEnabled":true,"assistantIds":["..."]}'."""
|
|
707
|
+
api = get_api(debug=debug)
|
|
708
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/executive/assignedAssistants"
|
|
709
|
+
if json_body:
|
|
710
|
+
body = json.loads(json_body)
|
|
711
|
+
else:
|
|
712
|
+
body = {}
|
|
713
|
+
if allow_opt_in_out_enabled is not None:
|
|
714
|
+
body["allowOptInOutEnabled"] = allow_opt_in_out_enabled
|
|
715
|
+
try:
|
|
716
|
+
result = api.session.rest_put(url, json=body)
|
|
717
|
+
except WebexError as e:
|
|
718
|
+
handle_rest_error(e)
|
|
719
|
+
typer.echo(f"Updated.")
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
@app.command("list-available-assistants")
|
|
724
|
+
def list_available_assistants(
|
|
725
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
726
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
727
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
728
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
729
|
+
):
|
|
730
|
+
"""Get My Executive Available Assistants."""
|
|
731
|
+
api = get_api(debug=debug)
|
|
732
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/executive/availableAssistants"
|
|
733
|
+
params = {}
|
|
734
|
+
if limit > 0:
|
|
735
|
+
params["max"] = limit
|
|
736
|
+
if offset > 0:
|
|
737
|
+
params["start"] = offset
|
|
738
|
+
result = None
|
|
739
|
+
try:
|
|
740
|
+
result = api.session.rest_get(url, params=params)
|
|
741
|
+
except WebexError as e:
|
|
742
|
+
handle_rest_error(e)
|
|
743
|
+
result = result or []
|
|
744
|
+
items = result.get("assistants", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
745
|
+
if output == "json":
|
|
746
|
+
print_json(items)
|
|
747
|
+
else:
|
|
748
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
@app.command("list-assistant")
|
|
753
|
+
def list_assistant(
|
|
754
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
755
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
756
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
757
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
758
|
+
):
|
|
759
|
+
"""Get My Executive Assistant Settings."""
|
|
760
|
+
api = get_api(debug=debug)
|
|
761
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/executive/assistant"
|
|
762
|
+
params = {}
|
|
763
|
+
if limit > 0:
|
|
764
|
+
params["max"] = limit
|
|
765
|
+
if offset > 0:
|
|
766
|
+
params["start"] = offset
|
|
767
|
+
result = None
|
|
768
|
+
try:
|
|
769
|
+
result = api.session.rest_get(url, params=params)
|
|
770
|
+
except WebexError as e:
|
|
771
|
+
handle_rest_error(e)
|
|
772
|
+
result = result or []
|
|
773
|
+
items = result.get("executives", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
774
|
+
if output == "json":
|
|
775
|
+
print_json(items)
|
|
776
|
+
else:
|
|
777
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
@app.command("update-assistant")
|
|
782
|
+
def update_assistant(
|
|
783
|
+
forward_filtered_calls_enabled: bool = typer.Option(None, "--forward-filtered-calls-enabled/--no-forward-filtered-calls-enabled", help="If `true`, filtered calls to assistant are forwarded to the"),
|
|
784
|
+
forward_to_phone_number: str = typer.Option(None, "--forward-to-phone-number", help="Phone number to forward the filtered calls to. Mandatory if"),
|
|
785
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
786
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
787
|
+
):
|
|
788
|
+
"""Modify My Executive Assistant Settings\n\nExample --json-body:\n '{"forwardFilteredCallsEnabled":true,"forwardToPhoneNumber":"...","executives":[{"personId":"...","optInEnabled":"..."}]}'."""
|
|
789
|
+
api = get_api(debug=debug)
|
|
790
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/executive/assistant"
|
|
791
|
+
if json_body:
|
|
792
|
+
body = json.loads(json_body)
|
|
793
|
+
else:
|
|
794
|
+
body = {}
|
|
795
|
+
if forward_filtered_calls_enabled is not None:
|
|
796
|
+
body["forwardFilteredCallsEnabled"] = forward_filtered_calls_enabled
|
|
797
|
+
if forward_to_phone_number is not None:
|
|
798
|
+
body["forwardToPhoneNumber"] = forward_to_phone_number
|
|
799
|
+
try:
|
|
800
|
+
result = api.session.rest_put(url, json=body)
|
|
801
|
+
except WebexError as e:
|
|
802
|
+
handle_rest_error(e)
|
|
803
|
+
typer.echo(f"Updated.")
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
@app.command("list-services-settings")
|
|
808
|
+
def list_services_settings(
|
|
809
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
810
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
811
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
812
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
813
|
+
):
|
|
814
|
+
"""Get My Calling Services List."""
|
|
815
|
+
api = get_api(debug=debug)
|
|
816
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/services"
|
|
817
|
+
params = {}
|
|
818
|
+
if limit > 0:
|
|
819
|
+
params["max"] = limit
|
|
820
|
+
if offset > 0:
|
|
821
|
+
params["start"] = offset
|
|
822
|
+
result = None
|
|
823
|
+
try:
|
|
824
|
+
result = api.session.rest_get(url, params=params)
|
|
825
|
+
except WebexError as e:
|
|
826
|
+
handle_rest_error(e)
|
|
827
|
+
result = result or []
|
|
828
|
+
items = result.get("services", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
829
|
+
if output == "json":
|
|
830
|
+
print_json(items)
|
|
831
|
+
else:
|
|
832
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
@app.command("list-services-secondary-lines")
|
|
837
|
+
def list_services_secondary_lines(
|
|
838
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
839
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
840
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
841
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
842
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
843
|
+
):
|
|
844
|
+
"""Get My Secondary Line Owner Calling Services List."""
|
|
845
|
+
api = get_api(debug=debug)
|
|
846
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/services"
|
|
847
|
+
params = {}
|
|
848
|
+
if limit > 0:
|
|
849
|
+
params["max"] = limit
|
|
850
|
+
if offset > 0:
|
|
851
|
+
params["start"] = offset
|
|
852
|
+
result = None
|
|
853
|
+
try:
|
|
854
|
+
result = api.session.rest_get(url, params=params)
|
|
855
|
+
except WebexError as e:
|
|
856
|
+
handle_rest_error(e)
|
|
857
|
+
result = result or []
|
|
858
|
+
items = result.get("services", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
859
|
+
if output == "json":
|
|
860
|
+
print_json(items)
|
|
861
|
+
else:
|
|
862
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
|
|
866
|
+
@app.command("list-single-number-reach")
|
|
867
|
+
def list_single_number_reach(
|
|
868
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
869
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
870
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
871
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
872
|
+
):
|
|
873
|
+
"""Get User's Single Number Reach Settings."""
|
|
874
|
+
api = get_api(debug=debug)
|
|
875
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/singleNumberReach"
|
|
876
|
+
params = {}
|
|
877
|
+
if limit > 0:
|
|
878
|
+
params["max"] = limit
|
|
879
|
+
if offset > 0:
|
|
880
|
+
params["start"] = offset
|
|
881
|
+
result = None
|
|
882
|
+
try:
|
|
883
|
+
result = api.session.rest_get(url, params=params)
|
|
884
|
+
except WebexError as e:
|
|
885
|
+
handle_rest_error(e)
|
|
886
|
+
result = result or []
|
|
887
|
+
items = result.get("numbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
888
|
+
if output == "json":
|
|
889
|
+
print_json(items)
|
|
890
|
+
else:
|
|
891
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
@app.command("update-single-number-reach")
|
|
896
|
+
def update_single_number_reach(
|
|
897
|
+
alert_all_locations_for_click_to_dial_calls_enabled: bool = typer.Option(None, "--alert-all-locations-for-click-to-dial-calls-enabled/--no-alert-all-locations-for-click-to-dial-calls-enabled", help="If `true`, all locations will be alerted for click-to-dial c"),
|
|
898
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
899
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
900
|
+
):
|
|
901
|
+
"""Modify User's Single Number Reach Settings."""
|
|
902
|
+
api = get_api(debug=debug)
|
|
903
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/singleNumberReach"
|
|
904
|
+
if json_body:
|
|
905
|
+
body = json.loads(json_body)
|
|
906
|
+
else:
|
|
907
|
+
body = {}
|
|
908
|
+
if alert_all_locations_for_click_to_dial_calls_enabled is not None:
|
|
909
|
+
body["alertAllLocationsForClickToDialCallsEnabled"] = alert_all_locations_for_click_to_dial_calls_enabled
|
|
910
|
+
try:
|
|
911
|
+
result = api.session.rest_put(url, json=body)
|
|
912
|
+
except WebexError as e:
|
|
913
|
+
handle_rest_error(e)
|
|
914
|
+
typer.echo(f"Updated.")
|
|
915
|
+
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
@app.command("create")
|
|
919
|
+
def create(
|
|
920
|
+
phone_number: str = typer.Option(None, "--phone-number", help="(required) Phone number."),
|
|
921
|
+
name: str = typer.Option(None, "--name", help="(required) Name associated with the phone number."),
|
|
922
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="(required) If `true`, the phone number is enabled."),
|
|
923
|
+
do_not_forward_calls_enabled: bool = typer.Option(None, "--do-not-forward-calls-enabled/--no-do-not-forward-calls-enabled", help="Note that this setting attempts to prevent the Single Number"),
|
|
924
|
+
answer_confirmation_enabled: bool = typer.Option(None, "--answer-confirmation-enabled/--no-answer-confirmation-enabled", help="If `true`, answer confirmation is enabled. The default value"),
|
|
925
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
926
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
927
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
928
|
+
):
|
|
929
|
+
"""Add phone number as User's Single Number Reach."""
|
|
930
|
+
api = get_api(debug=debug)
|
|
931
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/singleNumberReach/numbers"
|
|
932
|
+
if json_body:
|
|
933
|
+
body = json.loads(json_body)
|
|
934
|
+
else:
|
|
935
|
+
body = {}
|
|
936
|
+
if phone_number is not None:
|
|
937
|
+
body["phoneNumber"] = phone_number
|
|
938
|
+
if name is not None:
|
|
939
|
+
body["name"] = name
|
|
940
|
+
if enabled is not None:
|
|
941
|
+
body["enabled"] = enabled
|
|
942
|
+
if do_not_forward_calls_enabled is not None:
|
|
943
|
+
body["doNotForwardCallsEnabled"] = do_not_forward_calls_enabled
|
|
944
|
+
if answer_confirmation_enabled is not None:
|
|
945
|
+
body["answerConfirmationEnabled"] = answer_confirmation_enabled
|
|
946
|
+
_missing = [f for f in ['phoneNumber', 'name', 'enabled'] if f not in body or body[f] is None]
|
|
947
|
+
if _missing:
|
|
948
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
949
|
+
raise typer.Exit(1)
|
|
950
|
+
try:
|
|
951
|
+
result = api.session.rest_post(url, json=body)
|
|
952
|
+
except WebexError as e:
|
|
953
|
+
handle_rest_error(e)
|
|
954
|
+
if output == "json":
|
|
955
|
+
print_json(result)
|
|
956
|
+
elif isinstance(result, dict) and "id" in result:
|
|
957
|
+
typer.echo(f"Created: {result['id']}")
|
|
958
|
+
elif not result or result == {}:
|
|
959
|
+
typer.echo("Created.")
|
|
960
|
+
else:
|
|
961
|
+
print_json(result)
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
@app.command("update-numbers")
|
|
966
|
+
def update_numbers(
|
|
967
|
+
phone_number_id: str = typer.Argument(help="phoneNumberId"),
|
|
968
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Phone number."),
|
|
969
|
+
name: str = typer.Option(None, "--name", help="Name associated with the phone number."),
|
|
970
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="If `true`, the phone number is enabled."),
|
|
971
|
+
do_not_forward_calls_enabled: bool = typer.Option(None, "--do-not-forward-calls-enabled/--no-do-not-forward-calls-enabled", help="If `true`, calls are not forwarded."),
|
|
972
|
+
answer_confirmation_enabled: bool = typer.Option(None, "--answer-confirmation-enabled/--no-answer-confirmation-enabled", help="If `true`, answer confirmation is enabled."),
|
|
973
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
974
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
975
|
+
):
|
|
976
|
+
"""Modify User's Single Number Reach Contact Settings."""
|
|
977
|
+
api = get_api(debug=debug)
|
|
978
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/singleNumberReach/numbers/{phone_number_id}"
|
|
979
|
+
if json_body:
|
|
980
|
+
body = json.loads(json_body)
|
|
981
|
+
else:
|
|
982
|
+
body = {}
|
|
983
|
+
if phone_number is not None:
|
|
984
|
+
body["phoneNumber"] = phone_number
|
|
985
|
+
if name is not None:
|
|
986
|
+
body["name"] = name
|
|
987
|
+
if enabled is not None:
|
|
988
|
+
body["enabled"] = enabled
|
|
989
|
+
if do_not_forward_calls_enabled is not None:
|
|
990
|
+
body["doNotForwardCallsEnabled"] = do_not_forward_calls_enabled
|
|
991
|
+
if answer_confirmation_enabled is not None:
|
|
992
|
+
body["answerConfirmationEnabled"] = answer_confirmation_enabled
|
|
993
|
+
try:
|
|
994
|
+
result = api.session.rest_put(url, json=body)
|
|
995
|
+
except WebexError as e:
|
|
996
|
+
handle_rest_error(e)
|
|
997
|
+
typer.echo(f"Updated.")
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
|
|
1001
|
+
@app.command("delete")
|
|
1002
|
+
def delete(
|
|
1003
|
+
phone_number_id: str = typer.Argument(help="phoneNumberId"),
|
|
1004
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1005
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1006
|
+
):
|
|
1007
|
+
"""Delete User's Single Number Reach Contact Settings."""
|
|
1008
|
+
if not force:
|
|
1009
|
+
typer.confirm(f"Delete {phone_number_id}?", abort=True)
|
|
1010
|
+
api = get_api(debug=debug)
|
|
1011
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/singleNumberReach/numbers/{phone_number_id}"
|
|
1012
|
+
try:
|
|
1013
|
+
api.session.rest_delete(url)
|
|
1014
|
+
except WebexError as e:
|
|
1015
|
+
handle_rest_error(e)
|
|
1016
|
+
typer.echo(f"Deleted: {phone_number_id}")
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
@app.command("show-call-forwarding-settings")
|
|
1021
|
+
def show_call_forwarding_settings(
|
|
1022
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1023
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1024
|
+
):
|
|
1025
|
+
"""Read My Call Forwarding Settings."""
|
|
1026
|
+
api = get_api(debug=debug)
|
|
1027
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callForwarding"
|
|
1028
|
+
try:
|
|
1029
|
+
result = api.session.rest_get(url)
|
|
1030
|
+
except WebexError as e:
|
|
1031
|
+
handle_rest_error(e)
|
|
1032
|
+
if output == "json":
|
|
1033
|
+
print_json(result)
|
|
1034
|
+
else:
|
|
1035
|
+
if isinstance(result, dict):
|
|
1036
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1037
|
+
elif isinstance(result, list):
|
|
1038
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1039
|
+
else:
|
|
1040
|
+
print_json(result)
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
@app.command("update-call-forwarding-settings")
|
|
1045
|
+
def update_call_forwarding_settings(
|
|
1046
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1047
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1048
|
+
):
|
|
1049
|
+
"""Configure My Call Forwarding Settings\n\nExample --json-body:\n '{"callForwarding":{"always":{"enabled":"...","destination":"...","ringReminderEnabled":"...","destinationVoicemailEnabled":"..."},"busy":{"enabled":"...","destination":"...","destinationVoicemailEnabled":"..."},"noAnswer":{"enabled":"...","destination":"...","numberOfRings":"...","destinationVoicemailEnabled":"..."}},"businessContinuity":{"enabled":true,"destination":"...","destinationVoicemailEnabled":true}}'."""
|
|
1050
|
+
api = get_api(debug=debug)
|
|
1051
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callForwarding"
|
|
1052
|
+
if json_body:
|
|
1053
|
+
body = json.loads(json_body)
|
|
1054
|
+
else:
|
|
1055
|
+
body = {}
|
|
1056
|
+
try:
|
|
1057
|
+
result = api.session.rest_put(url, json=body)
|
|
1058
|
+
except WebexError as e:
|
|
1059
|
+
handle_rest_error(e)
|
|
1060
|
+
typer.echo(f"Updated.")
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
|
|
1064
|
+
@app.command("show-call-forwarding-secondary-lines")
|
|
1065
|
+
def show_call_forwarding_secondary_lines(
|
|
1066
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1067
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1068
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1069
|
+
):
|
|
1070
|
+
"""Get My Secondary Line Owner's Call Forwarding Settings."""
|
|
1071
|
+
api = get_api(debug=debug)
|
|
1072
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callForwarding"
|
|
1073
|
+
try:
|
|
1074
|
+
result = api.session.rest_get(url)
|
|
1075
|
+
except WebexError as e:
|
|
1076
|
+
handle_rest_error(e)
|
|
1077
|
+
if output == "json":
|
|
1078
|
+
print_json(result)
|
|
1079
|
+
else:
|
|
1080
|
+
if isinstance(result, dict):
|
|
1081
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1082
|
+
elif isinstance(result, list):
|
|
1083
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1084
|
+
else:
|
|
1085
|
+
print_json(result)
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
@app.command("update-call-forwarding-secondary-lines")
|
|
1090
|
+
def update_call_forwarding_secondary_lines(
|
|
1091
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1092
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1093
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1094
|
+
):
|
|
1095
|
+
"""Modify My Secondary Line Owner's Call Forwarding Settings\n\nExample --json-body:\n '{"callForwarding":{"always":{"enabled":"...","destination":"...","ringReminderEnabled":"...","destinationVoicemailEnabled":"..."},"busy":{"enabled":"...","destination":"...","destinationVoicemailEnabled":"..."},"noAnswer":{"enabled":"...","destination":"...","numberOfRings":"...","destinationVoicemailEnabled":"..."}},"businessContinuity":{"enabled":true,"destination":"...","destinationVoicemailEnabled":true}}'."""
|
|
1096
|
+
api = get_api(debug=debug)
|
|
1097
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callForwarding"
|
|
1098
|
+
if json_body:
|
|
1099
|
+
body = json.loads(json_body)
|
|
1100
|
+
else:
|
|
1101
|
+
body = {}
|
|
1102
|
+
try:
|
|
1103
|
+
result = api.session.rest_put(url, json=body)
|
|
1104
|
+
except WebexError as e:
|
|
1105
|
+
handle_rest_error(e)
|
|
1106
|
+
typer.echo(f"Updated.")
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
|
|
1110
|
+
@app.command("list-call-pickup-group-settings")
|
|
1111
|
+
def list_call_pickup_group_settings(
|
|
1112
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1113
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1114
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1115
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1116
|
+
):
|
|
1117
|
+
"""Get My Call Pickup Group Settings."""
|
|
1118
|
+
api = get_api(debug=debug)
|
|
1119
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callPickupGroup"
|
|
1120
|
+
params = {}
|
|
1121
|
+
if limit > 0:
|
|
1122
|
+
params["max"] = limit
|
|
1123
|
+
if offset > 0:
|
|
1124
|
+
params["start"] = offset
|
|
1125
|
+
result = None
|
|
1126
|
+
try:
|
|
1127
|
+
result = api.session.rest_get(url, params=params)
|
|
1128
|
+
except WebexError as e:
|
|
1129
|
+
handle_rest_error(e)
|
|
1130
|
+
result = result or []
|
|
1131
|
+
items = result.get("memberList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1132
|
+
if output == "json":
|
|
1133
|
+
print_json(items)
|
|
1134
|
+
else:
|
|
1135
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
@app.command("list-call-pickup-group-secondary-lines")
|
|
1140
|
+
def list_call_pickup_group_secondary_lines(
|
|
1141
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1142
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1143
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1144
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1145
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1146
|
+
):
|
|
1147
|
+
"""Get My Secondary Line Owner Call Pickup Group Settings."""
|
|
1148
|
+
api = get_api(debug=debug)
|
|
1149
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callPickupGroup"
|
|
1150
|
+
params = {}
|
|
1151
|
+
if limit > 0:
|
|
1152
|
+
params["max"] = limit
|
|
1153
|
+
if offset > 0:
|
|
1154
|
+
params["start"] = offset
|
|
1155
|
+
result = None
|
|
1156
|
+
try:
|
|
1157
|
+
result = api.session.rest_get(url, params=params)
|
|
1158
|
+
except WebexError as e:
|
|
1159
|
+
handle_rest_error(e)
|
|
1160
|
+
result = result or []
|
|
1161
|
+
items = result.get("memberList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1162
|
+
if output == "json":
|
|
1163
|
+
print_json(items)
|
|
1164
|
+
else:
|
|
1165
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1166
|
+
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
@app.command("list-call-park-settings")
|
|
1170
|
+
def list_call_park_settings(
|
|
1171
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1172
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1173
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1174
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1175
|
+
):
|
|
1176
|
+
"""Get My Call Park Settings."""
|
|
1177
|
+
api = get_api(debug=debug)
|
|
1178
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callPark"
|
|
1179
|
+
params = {}
|
|
1180
|
+
if limit > 0:
|
|
1181
|
+
params["max"] = limit
|
|
1182
|
+
if offset > 0:
|
|
1183
|
+
params["start"] = offset
|
|
1184
|
+
result = None
|
|
1185
|
+
try:
|
|
1186
|
+
result = api.session.rest_get(url, params=params)
|
|
1187
|
+
except WebexError as e:
|
|
1188
|
+
handle_rest_error(e)
|
|
1189
|
+
result = result or []
|
|
1190
|
+
items = result.get("memberList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1191
|
+
if output == "json":
|
|
1192
|
+
print_json(items)
|
|
1193
|
+
else:
|
|
1194
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
@app.command("list-call-park-secondary-lines")
|
|
1199
|
+
def list_call_park_secondary_lines(
|
|
1200
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1201
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1202
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1203
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1204
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1205
|
+
):
|
|
1206
|
+
"""Get My Secondary Line Owner Call Park Settings."""
|
|
1207
|
+
api = get_api(debug=debug)
|
|
1208
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/callPark"
|
|
1209
|
+
params = {}
|
|
1210
|
+
if limit > 0:
|
|
1211
|
+
params["max"] = limit
|
|
1212
|
+
if offset > 0:
|
|
1213
|
+
params["start"] = offset
|
|
1214
|
+
result = None
|
|
1215
|
+
try:
|
|
1216
|
+
result = api.session.rest_get(url, params=params)
|
|
1217
|
+
except WebexError as e:
|
|
1218
|
+
handle_rest_error(e)
|
|
1219
|
+
result = result or []
|
|
1220
|
+
items = result.get("memberList", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1221
|
+
if output == "json":
|
|
1222
|
+
print_json(items)
|
|
1223
|
+
else:
|
|
1224
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1225
|
+
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
@app.command("show-voicemail-settings")
|
|
1229
|
+
def show_voicemail_settings(
|
|
1230
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1231
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1232
|
+
):
|
|
1233
|
+
"""Read Voicemail Settings for a Person."""
|
|
1234
|
+
api = get_api(debug=debug)
|
|
1235
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/voicemail"
|
|
1236
|
+
try:
|
|
1237
|
+
result = api.session.rest_get(url)
|
|
1238
|
+
except WebexError as e:
|
|
1239
|
+
handle_rest_error(e)
|
|
1240
|
+
if output == "json":
|
|
1241
|
+
print_json(result)
|
|
1242
|
+
else:
|
|
1243
|
+
if isinstance(result, dict):
|
|
1244
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1245
|
+
elif isinstance(result, list):
|
|
1246
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1247
|
+
else:
|
|
1248
|
+
print_json(result)
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
@app.command("update-voicemail-settings")
|
|
1253
|
+
def update_voicemail_settings(
|
|
1254
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Voicemail is enabled or disabled."),
|
|
1255
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1256
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1257
|
+
):
|
|
1258
|
+
"""Configure Voicemail Settings for a Person\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":"..."}}'."""
|
|
1259
|
+
api = get_api(debug=debug)
|
|
1260
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/voicemail"
|
|
1261
|
+
if json_body:
|
|
1262
|
+
body = json.loads(json_body)
|
|
1263
|
+
else:
|
|
1264
|
+
body = {}
|
|
1265
|
+
if enabled is not None:
|
|
1266
|
+
body["enabled"] = enabled
|
|
1267
|
+
try:
|
|
1268
|
+
result = api.session.rest_put(url, json=body)
|
|
1269
|
+
except WebexError as e:
|
|
1270
|
+
handle_rest_error(e)
|
|
1271
|
+
typer.echo(f"Updated.")
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
|
|
1275
|
+
@app.command("show-voicemail-secondary-lines")
|
|
1276
|
+
def show_voicemail_secondary_lines(
|
|
1277
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1278
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1279
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1280
|
+
):
|
|
1281
|
+
"""Get My Secondary Line Owner's Voicemail Settings."""
|
|
1282
|
+
api = get_api(debug=debug)
|
|
1283
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/voicemail"
|
|
1284
|
+
try:
|
|
1285
|
+
result = api.session.rest_get(url)
|
|
1286
|
+
except WebexError as e:
|
|
1287
|
+
handle_rest_error(e)
|
|
1288
|
+
if output == "json":
|
|
1289
|
+
print_json(result)
|
|
1290
|
+
else:
|
|
1291
|
+
if isinstance(result, dict):
|
|
1292
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1293
|
+
elif isinstance(result, list):
|
|
1294
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1295
|
+
else:
|
|
1296
|
+
print_json(result)
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
@app.command("update-voicemail-secondary-lines")
|
|
1301
|
+
def update_voicemail_secondary_lines(
|
|
1302
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1303
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Voicemail is enabled or disabled."),
|
|
1304
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1305
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1306
|
+
):
|
|
1307
|
+
"""Modify My Secondary Line Owner's Voicemail Settings\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":"..."}}'."""
|
|
1308
|
+
api = get_api(debug=debug)
|
|
1309
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/voicemail"
|
|
1310
|
+
if json_body:
|
|
1311
|
+
body = json.loads(json_body)
|
|
1312
|
+
else:
|
|
1313
|
+
body = {}
|
|
1314
|
+
if enabled is not None:
|
|
1315
|
+
body["enabled"] = enabled
|
|
1316
|
+
try:
|
|
1317
|
+
result = api.session.rest_put(url, json=body)
|
|
1318
|
+
except WebexError as e:
|
|
1319
|
+
handle_rest_error(e)
|
|
1320
|
+
typer.echo(f"Updated.")
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
@app.command("list-call-block")
|
|
1325
|
+
def list_call_block(
|
|
1326
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1327
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1328
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1329
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1330
|
+
):
|
|
1331
|
+
"""Get My Call Block Settings."""
|
|
1332
|
+
api = get_api(debug=debug)
|
|
1333
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callBlock"
|
|
1334
|
+
params = {}
|
|
1335
|
+
if limit > 0:
|
|
1336
|
+
params["max"] = limit
|
|
1337
|
+
if offset > 0:
|
|
1338
|
+
params["start"] = offset
|
|
1339
|
+
result = None
|
|
1340
|
+
try:
|
|
1341
|
+
result = api.session.rest_get(url, params=params)
|
|
1342
|
+
except WebexError as e:
|
|
1343
|
+
handle_rest_error(e)
|
|
1344
|
+
result = result or []
|
|
1345
|
+
items = result.get("numbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1346
|
+
if output == "json":
|
|
1347
|
+
print_json(items)
|
|
1348
|
+
else:
|
|
1349
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
|
|
1353
|
+
@app.command("create-numbers")
|
|
1354
|
+
def create_numbers(
|
|
1355
|
+
phone_number: str = typer.Option(None, "--phone-number", help="(required) Phone number which is blocked by user."),
|
|
1356
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1357
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1358
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1359
|
+
):
|
|
1360
|
+
"""Add a phone number to user's Call Block List."""
|
|
1361
|
+
api = get_api(debug=debug)
|
|
1362
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callBlock/numbers"
|
|
1363
|
+
if json_body:
|
|
1364
|
+
body = json.loads(json_body)
|
|
1365
|
+
else:
|
|
1366
|
+
body = {}
|
|
1367
|
+
if phone_number is not None:
|
|
1368
|
+
body["phoneNumber"] = phone_number
|
|
1369
|
+
_missing = [f for f in ['phoneNumber'] if f not in body or body[f] is None]
|
|
1370
|
+
if _missing:
|
|
1371
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1372
|
+
raise typer.Exit(1)
|
|
1373
|
+
try:
|
|
1374
|
+
result = api.session.rest_post(url, json=body)
|
|
1375
|
+
except WebexError as e:
|
|
1376
|
+
handle_rest_error(e)
|
|
1377
|
+
if output == "json":
|
|
1378
|
+
print_json(result)
|
|
1379
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1380
|
+
typer.echo(f"Created: {result['id']}")
|
|
1381
|
+
elif not result or result == {}:
|
|
1382
|
+
typer.echo("Created.")
|
|
1383
|
+
else:
|
|
1384
|
+
print_json(result)
|
|
1385
|
+
|
|
1386
|
+
|
|
1387
|
+
|
|
1388
|
+
@app.command("show-numbers")
|
|
1389
|
+
def show_numbers(
|
|
1390
|
+
phone_number_id: str = typer.Argument(help="phoneNumberId"),
|
|
1391
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1392
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1393
|
+
):
|
|
1394
|
+
"""Get My Call Block State For Specific Number."""
|
|
1395
|
+
api = get_api(debug=debug)
|
|
1396
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callBlock/numbers/{phone_number_id}"
|
|
1397
|
+
try:
|
|
1398
|
+
result = api.session.rest_get(url)
|
|
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("delete-numbers")
|
|
1414
|
+
def delete_numbers(
|
|
1415
|
+
phone_number_id: str = typer.Argument(help="phoneNumberId"),
|
|
1416
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1417
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1418
|
+
):
|
|
1419
|
+
"""Delete User Call Block Number."""
|
|
1420
|
+
if not force:
|
|
1421
|
+
typer.confirm(f"Delete {phone_number_id}?", abort=True)
|
|
1422
|
+
api = get_api(debug=debug)
|
|
1423
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callBlock/numbers/{phone_number_id}"
|
|
1424
|
+
try:
|
|
1425
|
+
api.session.rest_delete(url)
|
|
1426
|
+
except WebexError as e:
|
|
1427
|
+
handle_rest_error(e)
|
|
1428
|
+
typer.echo(f"Deleted: {phone_number_id}")
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
|
|
1432
|
+
@app.command("list-monitoring")
|
|
1433
|
+
def list_monitoring(
|
|
1434
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1435
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1436
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1437
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1438
|
+
):
|
|
1439
|
+
"""Get My Monitoring Settings."""
|
|
1440
|
+
api = get_api(debug=debug)
|
|
1441
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/monitoring"
|
|
1442
|
+
params = {}
|
|
1443
|
+
if limit > 0:
|
|
1444
|
+
params["max"] = limit
|
|
1445
|
+
if offset > 0:
|
|
1446
|
+
params["start"] = offset
|
|
1447
|
+
result = None
|
|
1448
|
+
try:
|
|
1449
|
+
result = api.session.rest_get(url, params=params)
|
|
1450
|
+
except WebexError as e:
|
|
1451
|
+
handle_rest_error(e)
|
|
1452
|
+
result = result or []
|
|
1453
|
+
items = result.get("monitoredElements", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1454
|
+
if output == "json":
|
|
1455
|
+
print_json(items)
|
|
1456
|
+
else:
|
|
1457
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
@app.command("list-queues-settings")
|
|
1462
|
+
def list_queues_settings(
|
|
1463
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1464
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1465
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1466
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1467
|
+
):
|
|
1468
|
+
"""Get My Call Center Settings."""
|
|
1469
|
+
api = get_api(debug=debug)
|
|
1470
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/queues"
|
|
1471
|
+
params = {}
|
|
1472
|
+
if limit > 0:
|
|
1473
|
+
params["max"] = limit
|
|
1474
|
+
if offset > 0:
|
|
1475
|
+
params["start"] = offset
|
|
1476
|
+
result = None
|
|
1477
|
+
try:
|
|
1478
|
+
result = api.session.rest_get(url, params=params)
|
|
1479
|
+
except WebexError as e:
|
|
1480
|
+
handle_rest_error(e)
|
|
1481
|
+
result = result or []
|
|
1482
|
+
items = result.get("queues", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1483
|
+
if output == "json":
|
|
1484
|
+
print_json(items)
|
|
1485
|
+
else:
|
|
1486
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
|
|
1490
|
+
@app.command("update-queues-settings")
|
|
1491
|
+
def update_queues_settings(
|
|
1492
|
+
agent_acd_state: str = typer.Option(None, "--agent-acd-state", help="Choices: SIGN_IN, SIGN_OUT, AVAILABLE, UNAVAILABLE, WRAP_UP"),
|
|
1493
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1494
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1495
|
+
):
|
|
1496
|
+
"""Modify My Call Center Settings\n\nExample --json-body:\n '{"agentACDState":"SIGN_IN","queues":[{"id":"...","available":"..."}]}'."""
|
|
1497
|
+
api = get_api(debug=debug)
|
|
1498
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/queues"
|
|
1499
|
+
if json_body:
|
|
1500
|
+
body = json.loads(json_body)
|
|
1501
|
+
else:
|
|
1502
|
+
body = {}
|
|
1503
|
+
if agent_acd_state is not None:
|
|
1504
|
+
body["agentACDState"] = agent_acd_state
|
|
1505
|
+
try:
|
|
1506
|
+
result = api.session.rest_put(url, json=body)
|
|
1507
|
+
except WebexError as e:
|
|
1508
|
+
handle_rest_error(e)
|
|
1509
|
+
typer.echo(f"Updated.")
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
@app.command("list-queues-secondary-lines")
|
|
1514
|
+
def list_queues_secondary_lines(
|
|
1515
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1516
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1517
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1518
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1519
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1520
|
+
):
|
|
1521
|
+
"""Get My Secondary Line Owner's Call Center Settings."""
|
|
1522
|
+
api = get_api(debug=debug)
|
|
1523
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/queues"
|
|
1524
|
+
params = {}
|
|
1525
|
+
if limit > 0:
|
|
1526
|
+
params["max"] = limit
|
|
1527
|
+
if offset > 0:
|
|
1528
|
+
params["start"] = offset
|
|
1529
|
+
result = None
|
|
1530
|
+
try:
|
|
1531
|
+
result = api.session.rest_get(url, params=params)
|
|
1532
|
+
except WebexError as e:
|
|
1533
|
+
handle_rest_error(e)
|
|
1534
|
+
result = result or []
|
|
1535
|
+
items = result.get("queues", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1536
|
+
if output == "json":
|
|
1537
|
+
print_json(items)
|
|
1538
|
+
else:
|
|
1539
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
@app.command("update-queues-secondary-lines")
|
|
1544
|
+
def update_queues_secondary_lines(
|
|
1545
|
+
lineowner_id: str = typer.Argument(help="lineownerId"),
|
|
1546
|
+
agent_acd_state: str = typer.Option(None, "--agent-acd-state", help="Choices: SIGN_IN, SIGN_OUT, AVAILABLE, UNAVAILABLE, WRAP_UP"),
|
|
1547
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1548
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1549
|
+
):
|
|
1550
|
+
"""Modify My Secondary Line Owner's Call Center Settings\n\nExample --json-body:\n '{"agentACDState":"SIGN_IN","queues":[{"id":"...","available":"..."}]}'."""
|
|
1551
|
+
api = get_api(debug=debug)
|
|
1552
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/secondaryLines/{lineowner_id}/queues"
|
|
1553
|
+
if json_body:
|
|
1554
|
+
body = json.loads(json_body)
|
|
1555
|
+
else:
|
|
1556
|
+
body = {}
|
|
1557
|
+
if agent_acd_state is not None:
|
|
1558
|
+
body["agentACDState"] = agent_acd_state
|
|
1559
|
+
try:
|
|
1560
|
+
result = api.session.rest_put(url, json=body)
|
|
1561
|
+
except WebexError as e:
|
|
1562
|
+
handle_rest_error(e)
|
|
1563
|
+
typer.echo(f"Updated.")
|
|
1564
|
+
|
|
1565
|
+
|
|
1566
|
+
|
|
1567
|
+
@app.command("show-call-captions")
|
|
1568
|
+
def show_call_captions(
|
|
1569
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1570
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1571
|
+
):
|
|
1572
|
+
"""Get my call captions settings."""
|
|
1573
|
+
api = get_api(debug=debug)
|
|
1574
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callCaptions"
|
|
1575
|
+
try:
|
|
1576
|
+
result = api.session.rest_get(url)
|
|
1577
|
+
except WebexError as e:
|
|
1578
|
+
handle_rest_error(e)
|
|
1579
|
+
if output == "json":
|
|
1580
|
+
print_json(result)
|
|
1581
|
+
else:
|
|
1582
|
+
if isinstance(result, dict):
|
|
1583
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1584
|
+
elif isinstance(result, list):
|
|
1585
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1586
|
+
else:
|
|
1587
|
+
print_json(result)
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
|
|
1591
|
+
@app.command("list-priority-alert")
|
|
1592
|
+
def list_priority_alert(
|
|
1593
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1594
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1595
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1596
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1597
|
+
):
|
|
1598
|
+
"""Get Priority Alert Settings."""
|
|
1599
|
+
api = get_api(debug=debug)
|
|
1600
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/priorityAlert"
|
|
1601
|
+
params = {}
|
|
1602
|
+
if limit > 0:
|
|
1603
|
+
params["max"] = limit
|
|
1604
|
+
if offset > 0:
|
|
1605
|
+
params["start"] = offset
|
|
1606
|
+
result = None
|
|
1607
|
+
try:
|
|
1608
|
+
result = api.session.rest_get(url, params=params)
|
|
1609
|
+
except WebexError as e:
|
|
1610
|
+
handle_rest_error(e)
|
|
1611
|
+
result = result or []
|
|
1612
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1613
|
+
if output == "json":
|
|
1614
|
+
print_json(items)
|
|
1615
|
+
else:
|
|
1616
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
|
|
1620
|
+
@app.command("update-priority-alert")
|
|
1621
|
+
def update_priority_alert(
|
|
1622
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Priority Alert feature is enabled."),
|
|
1623
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1624
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1625
|
+
):
|
|
1626
|
+
"""Modify Priority Alert Settings for User."""
|
|
1627
|
+
api = get_api(debug=debug)
|
|
1628
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/priorityAlert"
|
|
1629
|
+
if json_body:
|
|
1630
|
+
body = json.loads(json_body)
|
|
1631
|
+
else:
|
|
1632
|
+
body = {}
|
|
1633
|
+
if enabled is not None:
|
|
1634
|
+
body["enabled"] = enabled
|
|
1635
|
+
try:
|
|
1636
|
+
result = api.session.rest_put(url, json=body)
|
|
1637
|
+
except WebexError as e:
|
|
1638
|
+
handle_rest_error(e)
|
|
1639
|
+
typer.echo(f"Updated.")
|
|
1640
|
+
|
|
1641
|
+
|
|
1642
|
+
|
|
1643
|
+
@app.command("create-criteria-priority-alert")
|
|
1644
|
+
def create_criteria_priority_alert(
|
|
1645
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
1646
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
1647
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
1648
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
1649
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Indicates whether anonymous callers are included in this cri"),
|
|
1650
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Indicates whether unavailable callers are included in this c"),
|
|
1651
|
+
notification_enabled: bool = typer.Option(None, "--notification-enabled/--no-notification-enabled", help="Determines whether priority alerting is applied for calls ma"),
|
|
1652
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1653
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1654
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1655
|
+
):
|
|
1656
|
+
"""Add a Priority Alert Criteria\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"notificationEnabled":true}'."""
|
|
1657
|
+
api = get_api(debug=debug)
|
|
1658
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/priorityAlert/criteria"
|
|
1659
|
+
if json_body:
|
|
1660
|
+
body = json.loads(json_body)
|
|
1661
|
+
else:
|
|
1662
|
+
body = {}
|
|
1663
|
+
if schedule_name is not None:
|
|
1664
|
+
body["scheduleName"] = schedule_name
|
|
1665
|
+
if schedule_type is not None:
|
|
1666
|
+
body["scheduleType"] = schedule_type
|
|
1667
|
+
if schedule_level is not None:
|
|
1668
|
+
body["scheduleLevel"] = schedule_level
|
|
1669
|
+
if calls_from is not None:
|
|
1670
|
+
body["callsFrom"] = calls_from
|
|
1671
|
+
if anonymous_callers_enabled is not None:
|
|
1672
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
1673
|
+
if unavailable_callers_enabled is not None:
|
|
1674
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
1675
|
+
if notification_enabled is not None:
|
|
1676
|
+
body["notificationEnabled"] = notification_enabled
|
|
1677
|
+
try:
|
|
1678
|
+
result = api.session.rest_post(url, json=body)
|
|
1679
|
+
except WebexError as e:
|
|
1680
|
+
handle_rest_error(e)
|
|
1681
|
+
if output == "json":
|
|
1682
|
+
print_json(result)
|
|
1683
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1684
|
+
typer.echo(f"Created: {result['id']}")
|
|
1685
|
+
elif not result or result == {}:
|
|
1686
|
+
typer.echo("Created.")
|
|
1687
|
+
else:
|
|
1688
|
+
print_json(result)
|
|
1689
|
+
|
|
1690
|
+
|
|
1691
|
+
|
|
1692
|
+
@app.command("show-criteria-priority-alert")
|
|
1693
|
+
def show_criteria_priority_alert(
|
|
1694
|
+
id: str = typer.Argument(help="id"),
|
|
1695
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1696
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1697
|
+
):
|
|
1698
|
+
"""Get Priority Alert Criteria Settings."""
|
|
1699
|
+
api = get_api(debug=debug)
|
|
1700
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/priorityAlert/criteria/{id}"
|
|
1701
|
+
try:
|
|
1702
|
+
result = api.session.rest_get(url)
|
|
1703
|
+
except WebexError as e:
|
|
1704
|
+
handle_rest_error(e)
|
|
1705
|
+
if output == "json":
|
|
1706
|
+
print_json(result)
|
|
1707
|
+
else:
|
|
1708
|
+
if isinstance(result, dict):
|
|
1709
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1710
|
+
elif isinstance(result, list):
|
|
1711
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1712
|
+
else:
|
|
1713
|
+
print_json(result)
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
|
|
1717
|
+
@app.command("update-criteria-priority-alert")
|
|
1718
|
+
def update_criteria_priority_alert(
|
|
1719
|
+
id: str = typer.Argument(help="id"),
|
|
1720
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
1721
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
1722
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
1723
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
1724
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Indicates whether anonymous callers are included in this cri"),
|
|
1725
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Indicates whether unavailable callers are included in this c"),
|
|
1726
|
+
notification_enabled: bool = typer.Option(None, "--notification-enabled/--no-notification-enabled", help="Determines whether priority alerting is applied for calls ma"),
|
|
1727
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1728
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1729
|
+
):
|
|
1730
|
+
"""Modify Settings for a Priority Alert Criteria\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"notificationEnabled":true}'."""
|
|
1731
|
+
api = get_api(debug=debug)
|
|
1732
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/priorityAlert/criteria/{id}"
|
|
1733
|
+
if json_body:
|
|
1734
|
+
body = json.loads(json_body)
|
|
1735
|
+
else:
|
|
1736
|
+
body = {}
|
|
1737
|
+
if schedule_name is not None:
|
|
1738
|
+
body["scheduleName"] = schedule_name
|
|
1739
|
+
if schedule_type is not None:
|
|
1740
|
+
body["scheduleType"] = schedule_type
|
|
1741
|
+
if schedule_level is not None:
|
|
1742
|
+
body["scheduleLevel"] = schedule_level
|
|
1743
|
+
if calls_from is not None:
|
|
1744
|
+
body["callsFrom"] = calls_from
|
|
1745
|
+
if anonymous_callers_enabled is not None:
|
|
1746
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
1747
|
+
if unavailable_callers_enabled is not None:
|
|
1748
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
1749
|
+
if notification_enabled is not None:
|
|
1750
|
+
body["notificationEnabled"] = notification_enabled
|
|
1751
|
+
try:
|
|
1752
|
+
result = api.session.rest_put(url, json=body)
|
|
1753
|
+
except WebexError as e:
|
|
1754
|
+
handle_rest_error(e)
|
|
1755
|
+
typer.echo(f"Updated.")
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
|
|
1759
|
+
@app.command("delete-criteria-priority-alert")
|
|
1760
|
+
def delete_criteria_priority_alert(
|
|
1761
|
+
id: str = typer.Argument(help="id"),
|
|
1762
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1763
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1764
|
+
):
|
|
1765
|
+
"""Delete a Priority Alert Criteria."""
|
|
1766
|
+
if not force:
|
|
1767
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
1768
|
+
api = get_api(debug=debug)
|
|
1769
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/priorityAlert/criteria/{id}"
|
|
1770
|
+
try:
|
|
1771
|
+
api.session.rest_delete(url)
|
|
1772
|
+
except WebexError as e:
|
|
1773
|
+
handle_rest_error(e)
|
|
1774
|
+
typer.echo(f"Deleted: {id}")
|
|
1775
|
+
|
|
1776
|
+
|
|
1777
|
+
|
|
1778
|
+
@app.command("list-schedules")
|
|
1779
|
+
def list_schedules(
|
|
1780
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1781
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1782
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1783
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1784
|
+
):
|
|
1785
|
+
"""Get User (and Location) Schedules."""
|
|
1786
|
+
api = get_api(debug=debug)
|
|
1787
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules"
|
|
1788
|
+
params = {}
|
|
1789
|
+
if limit > 0:
|
|
1790
|
+
params["max"] = limit
|
|
1791
|
+
if offset > 0:
|
|
1792
|
+
params["start"] = offset
|
|
1793
|
+
result = None
|
|
1794
|
+
try:
|
|
1795
|
+
result = api.session.rest_get(url, params=params)
|
|
1796
|
+
except WebexError as e:
|
|
1797
|
+
handle_rest_error(e)
|
|
1798
|
+
result = result or []
|
|
1799
|
+
items = result.get("schedules", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1800
|
+
if output == "json":
|
|
1801
|
+
print_json(items)
|
|
1802
|
+
else:
|
|
1803
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1804
|
+
|
|
1805
|
+
|
|
1806
|
+
|
|
1807
|
+
@app.command("create-schedules")
|
|
1808
|
+
def create_schedules(
|
|
1809
|
+
type_param: str = typer.Option(None, "--type", help="(required) Choices: businessHours, holidays"),
|
|
1810
|
+
name: str = typer.Option(None, "--name", help="(required) Unique name for the schedule."),
|
|
1811
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1812
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1813
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1814
|
+
):
|
|
1815
|
+
"""Add a User level Schedule for Call Settings\n\nExample --json-body:\n '{"type":"businessHours","name":"...","events":[{"name":"...","startDate":"...","endDate":"...","startTime":"...","endTime":"...","allDayEnabled":"...","recurrence":"..."}]}'."""
|
|
1816
|
+
api = get_api(debug=debug)
|
|
1817
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules"
|
|
1818
|
+
if json_body:
|
|
1819
|
+
body = json.loads(json_body)
|
|
1820
|
+
else:
|
|
1821
|
+
body = {}
|
|
1822
|
+
if type_param is not None:
|
|
1823
|
+
body["type"] = type_param
|
|
1824
|
+
if name is not None:
|
|
1825
|
+
body["name"] = name
|
|
1826
|
+
_missing = [f for f in ['type', 'name'] if f not in body or body[f] is None]
|
|
1827
|
+
if _missing:
|
|
1828
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1829
|
+
raise typer.Exit(1)
|
|
1830
|
+
try:
|
|
1831
|
+
result = api.session.rest_post(url, json=body)
|
|
1832
|
+
except WebexError as e:
|
|
1833
|
+
handle_rest_error(e)
|
|
1834
|
+
if output == "json":
|
|
1835
|
+
print_json(result)
|
|
1836
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1837
|
+
typer.echo(f"Created: {result['id']}")
|
|
1838
|
+
elif not result or result == {}:
|
|
1839
|
+
typer.echo("Created.")
|
|
1840
|
+
else:
|
|
1841
|
+
print_json(result)
|
|
1842
|
+
|
|
1843
|
+
|
|
1844
|
+
|
|
1845
|
+
@app.command("show-schedules-me")
|
|
1846
|
+
def show_schedules_me(
|
|
1847
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
1848
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
1849
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1850
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1851
|
+
):
|
|
1852
|
+
"""Get User Schedule."""
|
|
1853
|
+
api = get_api(debug=debug)
|
|
1854
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}"
|
|
1855
|
+
try:
|
|
1856
|
+
result = api.session.rest_get(url)
|
|
1857
|
+
except WebexError as e:
|
|
1858
|
+
handle_rest_error(e)
|
|
1859
|
+
if output == "json":
|
|
1860
|
+
print_json(result)
|
|
1861
|
+
else:
|
|
1862
|
+
if isinstance(result, dict):
|
|
1863
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1864
|
+
elif isinstance(result, list):
|
|
1865
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1866
|
+
else:
|
|
1867
|
+
print_json(result)
|
|
1868
|
+
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+
@app.command("update-schedules")
|
|
1872
|
+
def update_schedules(
|
|
1873
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
1874
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
1875
|
+
name: str = typer.Option(None, "--name", help="Name of the schedule."),
|
|
1876
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1877
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1878
|
+
):
|
|
1879
|
+
"""Modify User Schedule\n\nExample --json-body:\n '{"name":"...","events":[{"name":"...","startDate":"...","endDate":"...","allDayEnabled":"...","newName":"...","startTime":"...","endTime":"...","recurrence":"..."}]}'."""
|
|
1880
|
+
api = get_api(debug=debug)
|
|
1881
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}"
|
|
1882
|
+
if json_body:
|
|
1883
|
+
body = json.loads(json_body)
|
|
1884
|
+
else:
|
|
1885
|
+
body = {}
|
|
1886
|
+
if name is not None:
|
|
1887
|
+
body["name"] = name
|
|
1888
|
+
try:
|
|
1889
|
+
result = api.session.rest_put(url, json=body)
|
|
1890
|
+
except WebexError as e:
|
|
1891
|
+
handle_rest_error(e)
|
|
1892
|
+
typer.echo(f"Updated.")
|
|
1893
|
+
|
|
1894
|
+
|
|
1895
|
+
|
|
1896
|
+
@app.command("delete-schedules")
|
|
1897
|
+
def delete_schedules(
|
|
1898
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
1899
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
1900
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
1901
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1902
|
+
):
|
|
1903
|
+
"""Delete a User Schedule."""
|
|
1904
|
+
if not force:
|
|
1905
|
+
typer.confirm(f"Delete {schedule_id}?", abort=True)
|
|
1906
|
+
api = get_api(debug=debug)
|
|
1907
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}"
|
|
1908
|
+
try:
|
|
1909
|
+
api.session.rest_delete(url)
|
|
1910
|
+
except WebexError as e:
|
|
1911
|
+
handle_rest_error(e)
|
|
1912
|
+
typer.echo(f"Deleted: {schedule_id}")
|
|
1913
|
+
|
|
1914
|
+
|
|
1915
|
+
|
|
1916
|
+
@app.command("create-events")
|
|
1917
|
+
def create_events(
|
|
1918
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
1919
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
1920
|
+
name: str = typer.Option(None, "--name", help="(required) Name for the event."),
|
|
1921
|
+
start_date: str = typer.Option(None, "--start-date", help="(required) Start Date of Event."),
|
|
1922
|
+
end_date: str = typer.Option(None, "--end-date", help="(required) End Date of Event."),
|
|
1923
|
+
start_time: str = typer.Option(None, "--start-time", help="Start time of event."),
|
|
1924
|
+
end_time: str = typer.Option(None, "--end-time", help="End time of event."),
|
|
1925
|
+
all_day_enabled: bool = typer.Option(None, "--all-day-enabled/--no-all-day-enabled", help="(required) An indication of whether given event is an all-day event or"),
|
|
1926
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1927
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1928
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1929
|
+
):
|
|
1930
|
+
"""Add an event for a User Schedule\n\nExample --json-body:\n '{"name":"...","startDate":"...","endDate":"...","allDayEnabled":true,"startTime":"...","endTime":"...","recurrence":{"recurForEver":true,"recurEndDate":"...","recurEndOccurrence":0,"recurDaily":{"recurInterval":"..."},"recurWeekly":{"sunday":"...","monday":"...","tuesday":"...","wednesday":"...","thursday":"...","friday":"...","saturday":"..."}}}'."""
|
|
1931
|
+
api = get_api(debug=debug)
|
|
1932
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}/events"
|
|
1933
|
+
if json_body:
|
|
1934
|
+
body = json.loads(json_body)
|
|
1935
|
+
else:
|
|
1936
|
+
body = {}
|
|
1937
|
+
if name is not None:
|
|
1938
|
+
body["name"] = name
|
|
1939
|
+
if start_date is not None:
|
|
1940
|
+
body["startDate"] = start_date
|
|
1941
|
+
if end_date is not None:
|
|
1942
|
+
body["endDate"] = end_date
|
|
1943
|
+
if start_time is not None:
|
|
1944
|
+
body["startTime"] = start_time
|
|
1945
|
+
if end_time is not None:
|
|
1946
|
+
body["endTime"] = end_time
|
|
1947
|
+
if all_day_enabled is not None:
|
|
1948
|
+
body["allDayEnabled"] = all_day_enabled
|
|
1949
|
+
_missing = [f for f in ['name', 'startDate', 'endDate', 'allDayEnabled'] if f not in body or body[f] is None]
|
|
1950
|
+
if _missing:
|
|
1951
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1952
|
+
raise typer.Exit(1)
|
|
1953
|
+
try:
|
|
1954
|
+
result = api.session.rest_post(url, json=body)
|
|
1955
|
+
except WebexError as e:
|
|
1956
|
+
handle_rest_error(e)
|
|
1957
|
+
if output == "json":
|
|
1958
|
+
print_json(result)
|
|
1959
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1960
|
+
typer.echo(f"Created: {result['id']}")
|
|
1961
|
+
elif not result or result == {}:
|
|
1962
|
+
typer.echo("Created.")
|
|
1963
|
+
else:
|
|
1964
|
+
print_json(result)
|
|
1965
|
+
|
|
1966
|
+
|
|
1967
|
+
|
|
1968
|
+
@app.command("show-events")
|
|
1969
|
+
def show_events(
|
|
1970
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
1971
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
1972
|
+
event_id: str = typer.Argument(help="eventId"),
|
|
1973
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1974
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1975
|
+
):
|
|
1976
|
+
"""Get User Schedule Event."""
|
|
1977
|
+
api = get_api(debug=debug)
|
|
1978
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}/events/{event_id}"
|
|
1979
|
+
try:
|
|
1980
|
+
result = api.session.rest_get(url)
|
|
1981
|
+
except WebexError as e:
|
|
1982
|
+
handle_rest_error(e)
|
|
1983
|
+
if output == "json":
|
|
1984
|
+
print_json(result)
|
|
1985
|
+
else:
|
|
1986
|
+
if isinstance(result, dict):
|
|
1987
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1988
|
+
elif isinstance(result, list):
|
|
1989
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1990
|
+
else:
|
|
1991
|
+
print_json(result)
|
|
1992
|
+
|
|
1993
|
+
|
|
1994
|
+
|
|
1995
|
+
@app.command("update-events")
|
|
1996
|
+
def update_events(
|
|
1997
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
1998
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
1999
|
+
event_id: str = typer.Argument(help="eventId"),
|
|
2000
|
+
name: str = typer.Option(None, "--name", help="Name for the event."),
|
|
2001
|
+
new_name: str = typer.Option(None, "--new-name", help="New Name for the event."),
|
|
2002
|
+
start_date: str = typer.Option(None, "--start-date", help="Start Date of Event."),
|
|
2003
|
+
end_date: str = typer.Option(None, "--end-date", help="End Date of Event."),
|
|
2004
|
+
start_time: str = typer.Option(None, "--start-time", help="Start time of event."),
|
|
2005
|
+
end_time: str = typer.Option(None, "--end-time", help="End time of event."),
|
|
2006
|
+
all_day_enabled: bool = typer.Option(None, "--all-day-enabled/--no-all-day-enabled", help="An indication of whether given event is an all-day event or"),
|
|
2007
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2008
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2009
|
+
):
|
|
2010
|
+
"""Modify User Schedule Event\n\nExample --json-body:\n '{"name":"...","startDate":"...","endDate":"...","allDayEnabled":true,"newName":"...","startTime":"...","endTime":"...","recurrence":{"recurForEver":true,"recurEndDate":"...","recurEndOccurrence":0,"recurDaily":{"recurInterval":"..."},"recurWeekly":{"sunday":"...","monday":"...","tuesday":"...","wednesday":"...","thursday":"...","friday":"...","saturday":"..."}}}'."""
|
|
2011
|
+
api = get_api(debug=debug)
|
|
2012
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}/events/{event_id}"
|
|
2013
|
+
if json_body:
|
|
2014
|
+
body = json.loads(json_body)
|
|
2015
|
+
else:
|
|
2016
|
+
body = {}
|
|
2017
|
+
if name is not None:
|
|
2018
|
+
body["name"] = name
|
|
2019
|
+
if new_name is not None:
|
|
2020
|
+
body["newName"] = new_name
|
|
2021
|
+
if start_date is not None:
|
|
2022
|
+
body["startDate"] = start_date
|
|
2023
|
+
if end_date is not None:
|
|
2024
|
+
body["endDate"] = end_date
|
|
2025
|
+
if start_time is not None:
|
|
2026
|
+
body["startTime"] = start_time
|
|
2027
|
+
if end_time is not None:
|
|
2028
|
+
body["endTime"] = end_time
|
|
2029
|
+
if all_day_enabled is not None:
|
|
2030
|
+
body["allDayEnabled"] = all_day_enabled
|
|
2031
|
+
try:
|
|
2032
|
+
result = api.session.rest_put(url, json=body)
|
|
2033
|
+
except WebexError as e:
|
|
2034
|
+
handle_rest_error(e)
|
|
2035
|
+
typer.echo(f"Updated.")
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
|
|
2039
|
+
@app.command("delete-events")
|
|
2040
|
+
def delete_events(
|
|
2041
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
2042
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
2043
|
+
event_id: str = typer.Argument(help="eventId"),
|
|
2044
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2045
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2046
|
+
):
|
|
2047
|
+
"""Delete User a Schedule Event."""
|
|
2048
|
+
if not force:
|
|
2049
|
+
typer.confirm(f"Delete {event_id}?", abort=True)
|
|
2050
|
+
api = get_api(debug=debug)
|
|
2051
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/schedules/{schedule_type}/{schedule_id}/events/{event_id}"
|
|
2052
|
+
try:
|
|
2053
|
+
api.session.rest_delete(url)
|
|
2054
|
+
except WebexError as e:
|
|
2055
|
+
handle_rest_error(e)
|
|
2056
|
+
typer.echo(f"Deleted: {event_id}")
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
|
|
2060
|
+
@app.command("show-schedules-locations")
|
|
2061
|
+
def show_schedules_locations(
|
|
2062
|
+
schedule_type: str = typer.Argument(help="scheduleType"),
|
|
2063
|
+
schedule_id: str = typer.Argument(help="scheduleId"),
|
|
2064
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2065
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2066
|
+
):
|
|
2067
|
+
"""Get User's Location Level Schedule."""
|
|
2068
|
+
api = get_api(debug=debug)
|
|
2069
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/locations/schedules/{schedule_type}/{schedule_id}"
|
|
2070
|
+
try:
|
|
2071
|
+
result = api.session.rest_get(url)
|
|
2072
|
+
except WebexError as e:
|
|
2073
|
+
handle_rest_error(e)
|
|
2074
|
+
if output == "json":
|
|
2075
|
+
print_json(result)
|
|
2076
|
+
else:
|
|
2077
|
+
if isinstance(result, dict):
|
|
2078
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2079
|
+
elif isinstance(result, list):
|
|
2080
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2081
|
+
else:
|
|
2082
|
+
print_json(result)
|
|
2083
|
+
|
|
2084
|
+
|
|
2085
|
+
|
|
2086
|
+
@app.command("list-call-notify")
|
|
2087
|
+
def list_call_notify(
|
|
2088
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2089
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2090
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2091
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2092
|
+
):
|
|
2093
|
+
"""Get Call Notify Settings for User."""
|
|
2094
|
+
api = get_api(debug=debug)
|
|
2095
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callNotify"
|
|
2096
|
+
params = {}
|
|
2097
|
+
if limit > 0:
|
|
2098
|
+
params["max"] = limit
|
|
2099
|
+
if offset > 0:
|
|
2100
|
+
params["start"] = offset
|
|
2101
|
+
result = None
|
|
2102
|
+
try:
|
|
2103
|
+
result = api.session.rest_get(url, params=params)
|
|
2104
|
+
except WebexError as e:
|
|
2105
|
+
handle_rest_error(e)
|
|
2106
|
+
result = result or []
|
|
2107
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2108
|
+
if output == "json":
|
|
2109
|
+
print_json(items)
|
|
2110
|
+
else:
|
|
2111
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
|
|
2115
|
+
@app.command("update-call-notify")
|
|
2116
|
+
def update_call_notify(
|
|
2117
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Indicates whether the call notify feature should be enabled"),
|
|
2118
|
+
email_address: str = typer.Option(None, "--email-address", help="Email Address to which call notifications to be received."),
|
|
2119
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2120
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2121
|
+
):
|
|
2122
|
+
"""Modify Call Notify Settings for User."""
|
|
2123
|
+
api = get_api(debug=debug)
|
|
2124
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callNotify"
|
|
2125
|
+
if json_body:
|
|
2126
|
+
body = json.loads(json_body)
|
|
2127
|
+
else:
|
|
2128
|
+
body = {}
|
|
2129
|
+
if enabled is not None:
|
|
2130
|
+
body["enabled"] = enabled
|
|
2131
|
+
if email_address is not None:
|
|
2132
|
+
body["emailAddress"] = email_address
|
|
2133
|
+
try:
|
|
2134
|
+
result = api.session.rest_put(url, json=body)
|
|
2135
|
+
except WebexError as e:
|
|
2136
|
+
handle_rest_error(e)
|
|
2137
|
+
typer.echo(f"Updated.")
|
|
2138
|
+
|
|
2139
|
+
|
|
2140
|
+
|
|
2141
|
+
@app.command("create-criteria-call-notify")
|
|
2142
|
+
def create_criteria_call_notify(
|
|
2143
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
2144
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2145
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
2146
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2147
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Indicates whether anonymous callers are included in this cri"),
|
|
2148
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Indicates whether unavailable callers are included in this c"),
|
|
2149
|
+
notification_enabled: bool = typer.Option(None, "--notification-enabled/--no-notification-enabled", help="Determines whether call notification is applied for calls ma"),
|
|
2150
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2151
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2152
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2153
|
+
):
|
|
2154
|
+
"""Add a Call Notify Criteria\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"notificationEnabled":true}'."""
|
|
2155
|
+
api = get_api(debug=debug)
|
|
2156
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callNotify/criteria"
|
|
2157
|
+
if json_body:
|
|
2158
|
+
body = json.loads(json_body)
|
|
2159
|
+
else:
|
|
2160
|
+
body = {}
|
|
2161
|
+
if schedule_name is not None:
|
|
2162
|
+
body["scheduleName"] = schedule_name
|
|
2163
|
+
if schedule_type is not None:
|
|
2164
|
+
body["scheduleType"] = schedule_type
|
|
2165
|
+
if schedule_level is not None:
|
|
2166
|
+
body["scheduleLevel"] = schedule_level
|
|
2167
|
+
if calls_from is not None:
|
|
2168
|
+
body["callsFrom"] = calls_from
|
|
2169
|
+
if anonymous_callers_enabled is not None:
|
|
2170
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2171
|
+
if unavailable_callers_enabled is not None:
|
|
2172
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2173
|
+
if notification_enabled is not None:
|
|
2174
|
+
body["notificationEnabled"] = notification_enabled
|
|
2175
|
+
try:
|
|
2176
|
+
result = api.session.rest_post(url, json=body)
|
|
2177
|
+
except WebexError as e:
|
|
2178
|
+
handle_rest_error(e)
|
|
2179
|
+
if output == "json":
|
|
2180
|
+
print_json(result)
|
|
2181
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2182
|
+
typer.echo(f"Created: {result['id']}")
|
|
2183
|
+
elif not result or result == {}:
|
|
2184
|
+
typer.echo("Created.")
|
|
2185
|
+
else:
|
|
2186
|
+
print_json(result)
|
|
2187
|
+
|
|
2188
|
+
|
|
2189
|
+
|
|
2190
|
+
@app.command("show-criteria-call-notify")
|
|
2191
|
+
def show_criteria_call_notify(
|
|
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
|
+
"""Get Call Notify Criteria Settings."""
|
|
2197
|
+
api = get_api(debug=debug)
|
|
2198
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callNotify/criteria/{id}"
|
|
2199
|
+
try:
|
|
2200
|
+
result = api.session.rest_get(url)
|
|
2201
|
+
except WebexError as e:
|
|
2202
|
+
handle_rest_error(e)
|
|
2203
|
+
if output == "json":
|
|
2204
|
+
print_json(result)
|
|
2205
|
+
else:
|
|
2206
|
+
if isinstance(result, dict):
|
|
2207
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2208
|
+
elif isinstance(result, list):
|
|
2209
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2210
|
+
else:
|
|
2211
|
+
print_json(result)
|
|
2212
|
+
|
|
2213
|
+
|
|
2214
|
+
|
|
2215
|
+
@app.command("update-criteria-call-notify")
|
|
2216
|
+
def update_criteria_call_notify(
|
|
2217
|
+
id: str = typer.Argument(help="id"),
|
|
2218
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
2219
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2220
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
2221
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2222
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Indicates whether anonymous callers are included in this cri"),
|
|
2223
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Indicates whether unavailable callers are included in this c"),
|
|
2224
|
+
notification_enabled: bool = typer.Option(None, "--notification-enabled/--no-notification-enabled", help="Determines whether call notification is applied for calls ma"),
|
|
2225
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2226
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2227
|
+
):
|
|
2228
|
+
"""Modify a Call Notify Criteria\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"notificationEnabled":true}'."""
|
|
2229
|
+
api = get_api(debug=debug)
|
|
2230
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callNotify/criteria/{id}"
|
|
2231
|
+
if json_body:
|
|
2232
|
+
body = json.loads(json_body)
|
|
2233
|
+
else:
|
|
2234
|
+
body = {}
|
|
2235
|
+
if schedule_name is not None:
|
|
2236
|
+
body["scheduleName"] = schedule_name
|
|
2237
|
+
if schedule_type is not None:
|
|
2238
|
+
body["scheduleType"] = schedule_type
|
|
2239
|
+
if schedule_level is not None:
|
|
2240
|
+
body["scheduleLevel"] = schedule_level
|
|
2241
|
+
if calls_from is not None:
|
|
2242
|
+
body["callsFrom"] = calls_from
|
|
2243
|
+
if anonymous_callers_enabled is not None:
|
|
2244
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2245
|
+
if unavailable_callers_enabled is not None:
|
|
2246
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2247
|
+
if notification_enabled is not None:
|
|
2248
|
+
body["notificationEnabled"] = notification_enabled
|
|
2249
|
+
try:
|
|
2250
|
+
result = api.session.rest_put(url, json=body)
|
|
2251
|
+
except WebexError as e:
|
|
2252
|
+
handle_rest_error(e)
|
|
2253
|
+
typer.echo(f"Updated.")
|
|
2254
|
+
|
|
2255
|
+
|
|
2256
|
+
|
|
2257
|
+
@app.command("delete-criteria-call-notify")
|
|
2258
|
+
def delete_criteria_call_notify(
|
|
2259
|
+
id: str = typer.Argument(help="id"),
|
|
2260
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2261
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2262
|
+
):
|
|
2263
|
+
"""Delete a Call Notify Criteria."""
|
|
2264
|
+
if not force:
|
|
2265
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2266
|
+
api = get_api(debug=debug)
|
|
2267
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callNotify/criteria/{id}"
|
|
2268
|
+
try:
|
|
2269
|
+
api.session.rest_delete(url)
|
|
2270
|
+
except WebexError as e:
|
|
2271
|
+
handle_rest_error(e)
|
|
2272
|
+
typer.echo(f"Deleted: {id}")
|
|
2273
|
+
|
|
2274
|
+
|
|
2275
|
+
|
|
2276
|
+
@app.command("list-selective-accept")
|
|
2277
|
+
def list_selective_accept(
|
|
2278
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2279
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2280
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2281
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2282
|
+
):
|
|
2283
|
+
"""Get Selective Call Accept Settings for User."""
|
|
2284
|
+
api = get_api(debug=debug)
|
|
2285
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveAccept"
|
|
2286
|
+
params = {}
|
|
2287
|
+
if limit > 0:
|
|
2288
|
+
params["max"] = limit
|
|
2289
|
+
if offset > 0:
|
|
2290
|
+
params["start"] = offset
|
|
2291
|
+
result = None
|
|
2292
|
+
try:
|
|
2293
|
+
result = api.session.rest_get(url, params=params)
|
|
2294
|
+
except WebexError as e:
|
|
2295
|
+
handle_rest_error(e)
|
|
2296
|
+
result = result or []
|
|
2297
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2298
|
+
if output == "json":
|
|
2299
|
+
print_json(items)
|
|
2300
|
+
else:
|
|
2301
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2302
|
+
|
|
2303
|
+
|
|
2304
|
+
|
|
2305
|
+
@app.command("update-selective-accept")
|
|
2306
|
+
def update_selective_accept(
|
|
2307
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="indicates whether selective accept is enabled or not."),
|
|
2308
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2309
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2310
|
+
):
|
|
2311
|
+
"""Modify Selective Call Accept Settings for User."""
|
|
2312
|
+
api = get_api(debug=debug)
|
|
2313
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveAccept"
|
|
2314
|
+
if json_body:
|
|
2315
|
+
body = json.loads(json_body)
|
|
2316
|
+
else:
|
|
2317
|
+
body = {}
|
|
2318
|
+
if enabled is not None:
|
|
2319
|
+
body["enabled"] = enabled
|
|
2320
|
+
try:
|
|
2321
|
+
result = api.session.rest_put(url, json=body)
|
|
2322
|
+
except WebexError as e:
|
|
2323
|
+
handle_rest_error(e)
|
|
2324
|
+
typer.echo(f"Updated.")
|
|
2325
|
+
|
|
2326
|
+
|
|
2327
|
+
|
|
2328
|
+
@app.command("create-criteria-selective-accept")
|
|
2329
|
+
def create_criteria_selective_accept(
|
|
2330
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to which the criteria is created."),
|
|
2331
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2332
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, GROUP"),
|
|
2333
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2334
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Boolean flag indicating if calls from custom numbers, privat"),
|
|
2335
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Boolean flag indicating if calls from custom numbers, unavai"),
|
|
2336
|
+
accept_enabled: bool = typer.Option(None, "--accept-enabled/--no-accept-enabled", help="(required) Boolean flag indicating if selective call accept is enabled."),
|
|
2337
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2338
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2339
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2340
|
+
):
|
|
2341
|
+
"""Add User Selective Call Accept Criteria\n\nExample --json-body:\n '{"callsFrom":"ANY_PHONE_NUMBER","acceptEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2342
|
+
api = get_api(debug=debug)
|
|
2343
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveAccept/criteria"
|
|
2344
|
+
if json_body:
|
|
2345
|
+
body = json.loads(json_body)
|
|
2346
|
+
else:
|
|
2347
|
+
body = {}
|
|
2348
|
+
if schedule_name is not None:
|
|
2349
|
+
body["scheduleName"] = schedule_name
|
|
2350
|
+
if schedule_type is not None:
|
|
2351
|
+
body["scheduleType"] = schedule_type
|
|
2352
|
+
if schedule_level is not None:
|
|
2353
|
+
body["scheduleLevel"] = schedule_level
|
|
2354
|
+
if calls_from is not None:
|
|
2355
|
+
body["callsFrom"] = calls_from
|
|
2356
|
+
if anonymous_callers_enabled is not None:
|
|
2357
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2358
|
+
if unavailable_callers_enabled is not None:
|
|
2359
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2360
|
+
if accept_enabled is not None:
|
|
2361
|
+
body["acceptEnabled"] = accept_enabled
|
|
2362
|
+
_missing = [f for f in ['callsFrom', 'acceptEnabled'] if f not in body or body[f] is None]
|
|
2363
|
+
if _missing:
|
|
2364
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
2365
|
+
raise typer.Exit(1)
|
|
2366
|
+
try:
|
|
2367
|
+
result = api.session.rest_post(url, json=body)
|
|
2368
|
+
except WebexError as e:
|
|
2369
|
+
handle_rest_error(e)
|
|
2370
|
+
if output == "json":
|
|
2371
|
+
print_json(result)
|
|
2372
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2373
|
+
typer.echo(f"Created: {result['id']}")
|
|
2374
|
+
elif not result or result == {}:
|
|
2375
|
+
typer.echo("Created.")
|
|
2376
|
+
else:
|
|
2377
|
+
print_json(result)
|
|
2378
|
+
|
|
2379
|
+
|
|
2380
|
+
|
|
2381
|
+
@app.command("show-criteria-selective-accept")
|
|
2382
|
+
def show_criteria_selective_accept(
|
|
2383
|
+
id: str = typer.Argument(help="id"),
|
|
2384
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2385
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2386
|
+
):
|
|
2387
|
+
"""Get Selective Call Accept Criteria Settings for User."""
|
|
2388
|
+
api = get_api(debug=debug)
|
|
2389
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveAccept/criteria/{id}"
|
|
2390
|
+
try:
|
|
2391
|
+
result = api.session.rest_get(url)
|
|
2392
|
+
except WebexError as e:
|
|
2393
|
+
handle_rest_error(e)
|
|
2394
|
+
if output == "json":
|
|
2395
|
+
print_json(result)
|
|
2396
|
+
else:
|
|
2397
|
+
if isinstance(result, dict):
|
|
2398
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2399
|
+
elif isinstance(result, list):
|
|
2400
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2401
|
+
else:
|
|
2402
|
+
print_json(result)
|
|
2403
|
+
|
|
2404
|
+
|
|
2405
|
+
|
|
2406
|
+
@app.command("update-criteria-selective-accept")
|
|
2407
|
+
def update_criteria_selective_accept(
|
|
2408
|
+
id: str = typer.Argument(help="id"),
|
|
2409
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to which the criteria is created."),
|
|
2410
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2411
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, GROUP"),
|
|
2412
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
2413
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Boolean flag indicating if calls from custom numbers, privat"),
|
|
2414
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Boolean flag indicating if calls from custom numbers, unavai"),
|
|
2415
|
+
accept_enabled: bool = typer.Option(None, "--accept-enabled/--no-accept-enabled", help="Boolean flag to enable/disable the selective accept criteria"),
|
|
2416
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2417
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2418
|
+
):
|
|
2419
|
+
"""Modify a Selective Call Accept Criteria\n\nExample --json-body:\n '{"callsFrom":"ANY_PHONE_NUMBER","acceptEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2420
|
+
api = get_api(debug=debug)
|
|
2421
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveAccept/criteria/{id}"
|
|
2422
|
+
if json_body:
|
|
2423
|
+
body = json.loads(json_body)
|
|
2424
|
+
else:
|
|
2425
|
+
body = {}
|
|
2426
|
+
if schedule_name is not None:
|
|
2427
|
+
body["scheduleName"] = schedule_name
|
|
2428
|
+
if schedule_type is not None:
|
|
2429
|
+
body["scheduleType"] = schedule_type
|
|
2430
|
+
if schedule_level is not None:
|
|
2431
|
+
body["scheduleLevel"] = schedule_level
|
|
2432
|
+
if calls_from is not None:
|
|
2433
|
+
body["callsFrom"] = calls_from
|
|
2434
|
+
if anonymous_callers_enabled is not None:
|
|
2435
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2436
|
+
if unavailable_callers_enabled is not None:
|
|
2437
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2438
|
+
if accept_enabled is not None:
|
|
2439
|
+
body["acceptEnabled"] = accept_enabled
|
|
2440
|
+
try:
|
|
2441
|
+
result = api.session.rest_put(url, json=body)
|
|
2442
|
+
except WebexError as e:
|
|
2443
|
+
handle_rest_error(e)
|
|
2444
|
+
typer.echo(f"Updated.")
|
|
2445
|
+
|
|
2446
|
+
|
|
2447
|
+
|
|
2448
|
+
@app.command("delete-criteria-selective-accept")
|
|
2449
|
+
def delete_criteria_selective_accept(
|
|
2450
|
+
id: str = typer.Argument(help="id"),
|
|
2451
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2452
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2453
|
+
):
|
|
2454
|
+
"""Delete a Selective Call Accept Criteria."""
|
|
2455
|
+
if not force:
|
|
2456
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2457
|
+
api = get_api(debug=debug)
|
|
2458
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveAccept/criteria/{id}"
|
|
2459
|
+
try:
|
|
2460
|
+
api.session.rest_delete(url)
|
|
2461
|
+
except WebexError as e:
|
|
2462
|
+
handle_rest_error(e)
|
|
2463
|
+
typer.echo(f"Deleted: {id}")
|
|
2464
|
+
|
|
2465
|
+
|
|
2466
|
+
|
|
2467
|
+
@app.command("list-assigned-numbers")
|
|
2468
|
+
def list_assigned_numbers(
|
|
2469
|
+
name: str = typer.Option(None, "--name", help="List numbers whose owner name contains this string."),
|
|
2470
|
+
phone_number: str = typer.Option(None, "--phone-number", help="List numbers whose phoneNumber contains this string."),
|
|
2471
|
+
extension: str = typer.Option(None, "--extension", help="List numbers whose extension contains this string."),
|
|
2472
|
+
order: str = typer.Option(None, "--order", help="Sort the list of numbers based on `lastName`, `dn`, `extensi"),
|
|
2473
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2474
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2475
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2476
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2477
|
+
):
|
|
2478
|
+
"""Get Available Numbers for User's Location."""
|
|
2479
|
+
api = get_api(debug=debug)
|
|
2480
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/location/assignedNumbers"
|
|
2481
|
+
params = {}
|
|
2482
|
+
if name is not None:
|
|
2483
|
+
params["name"] = name
|
|
2484
|
+
if phone_number is not None:
|
|
2485
|
+
params["phoneNumber"] = phone_number
|
|
2486
|
+
if extension is not None:
|
|
2487
|
+
params["extension"] = extension
|
|
2488
|
+
if order is not None:
|
|
2489
|
+
params["order"] = order
|
|
2490
|
+
if limit > 0:
|
|
2491
|
+
params["max"] = limit
|
|
2492
|
+
if offset > 0:
|
|
2493
|
+
params["start"] = offset
|
|
2494
|
+
result = None
|
|
2495
|
+
try:
|
|
2496
|
+
result = api.session.rest_get(url, params=params)
|
|
2497
|
+
except WebexError as e:
|
|
2498
|
+
handle_rest_error(e)
|
|
2499
|
+
result = result or []
|
|
2500
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2501
|
+
if output == "json":
|
|
2502
|
+
print_json(items)
|
|
2503
|
+
else:
|
|
2504
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2505
|
+
|
|
2506
|
+
|
|
2507
|
+
|
|
2508
|
+
@app.command("create-criteria-selective-forward")
|
|
2509
|
+
def create_criteria_selective_forward(
|
|
2510
|
+
forward_to_phone_number: str = typer.Option(None, "--forward-to-phone-number", help="The phone number to which calls are forwarded when the crite"),
|
|
2511
|
+
destination_voicemail_enabled: bool = typer.Option(None, "--destination-voicemail-enabled/--no-destination-voicemail-enabled", help="Indicates whether calls that meet the criteria are forwarded"),
|
|
2512
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
2513
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2514
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
2515
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, ANY_INTERNAL, ANY_EXTERNAL"),
|
|
2516
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Indicates whether anonymous callers are included in this cri"),
|
|
2517
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Indicates whether unavailable callers are included in this c"),
|
|
2518
|
+
forward_enabled: bool = typer.Option(None, "--forward-enabled/--no-forward-enabled", help="Determines whether selective call forwarding is applied for"),
|
|
2519
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2520
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2521
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2522
|
+
):
|
|
2523
|
+
"""Add a Selective Call Forwarding Criteria\n\nExample --json-body:\n '{"forwardToPhoneNumber":"...","destinationVoicemailEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true}'."""
|
|
2524
|
+
api = get_api(debug=debug)
|
|
2525
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveForward/criteria"
|
|
2526
|
+
if json_body:
|
|
2527
|
+
body = json.loads(json_body)
|
|
2528
|
+
else:
|
|
2529
|
+
body = {}
|
|
2530
|
+
if forward_to_phone_number is not None:
|
|
2531
|
+
body["forwardToPhoneNumber"] = forward_to_phone_number
|
|
2532
|
+
if destination_voicemail_enabled is not None:
|
|
2533
|
+
body["destinationVoicemailEnabled"] = destination_voicemail_enabled
|
|
2534
|
+
if schedule_name is not None:
|
|
2535
|
+
body["scheduleName"] = schedule_name
|
|
2536
|
+
if schedule_type is not None:
|
|
2537
|
+
body["scheduleType"] = schedule_type
|
|
2538
|
+
if schedule_level is not None:
|
|
2539
|
+
body["scheduleLevel"] = schedule_level
|
|
2540
|
+
if calls_from is not None:
|
|
2541
|
+
body["callsFrom"] = calls_from
|
|
2542
|
+
if anonymous_callers_enabled is not None:
|
|
2543
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2544
|
+
if unavailable_callers_enabled is not None:
|
|
2545
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2546
|
+
if forward_enabled is not None:
|
|
2547
|
+
body["forwardEnabled"] = forward_enabled
|
|
2548
|
+
try:
|
|
2549
|
+
result = api.session.rest_post(url, json=body)
|
|
2550
|
+
except WebexError as e:
|
|
2551
|
+
handle_rest_error(e)
|
|
2552
|
+
if output == "json":
|
|
2553
|
+
print_json(result)
|
|
2554
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2555
|
+
typer.echo(f"Created: {result['id']}")
|
|
2556
|
+
elif not result or result == {}:
|
|
2557
|
+
typer.echo("Created.")
|
|
2558
|
+
else:
|
|
2559
|
+
print_json(result)
|
|
2560
|
+
|
|
2561
|
+
|
|
2562
|
+
|
|
2563
|
+
@app.command("show-criteria-selective-forward")
|
|
2564
|
+
def show_criteria_selective_forward(
|
|
2565
|
+
id: str = typer.Argument(help="id"),
|
|
2566
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2567
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2568
|
+
):
|
|
2569
|
+
"""Get Settings for a Selective Call Forwarding Criteria."""
|
|
2570
|
+
api = get_api(debug=debug)
|
|
2571
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveForward/criteria/{id}"
|
|
2572
|
+
try:
|
|
2573
|
+
result = api.session.rest_get(url)
|
|
2574
|
+
except WebexError as e:
|
|
2575
|
+
handle_rest_error(e)
|
|
2576
|
+
if output == "json":
|
|
2577
|
+
print_json(result)
|
|
2578
|
+
else:
|
|
2579
|
+
if isinstance(result, dict):
|
|
2580
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2581
|
+
elif isinstance(result, list):
|
|
2582
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2583
|
+
else:
|
|
2584
|
+
print_json(result)
|
|
2585
|
+
|
|
2586
|
+
|
|
2587
|
+
|
|
2588
|
+
@app.command("update-criteria-selective-forward")
|
|
2589
|
+
def update_criteria_selective_forward(
|
|
2590
|
+
id: str = typer.Argument(help="id"),
|
|
2591
|
+
forward_to_phone_number: str = typer.Option(None, "--forward-to-phone-number", help="The phone number to which calls are forwarded when the crite"),
|
|
2592
|
+
destination_voicemail_enabled: bool = typer.Option(None, "--destination-voicemail-enabled/--no-destination-voicemail-enabled", help="Indicates whether calls that meet the criteria are forwarded"),
|
|
2593
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
2594
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2595
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
2596
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, ANY_INTERNAL, ANY_EXTERNAL"),
|
|
2597
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Indicates whether anonymous callers are included in this cri"),
|
|
2598
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Indicates whether unavailable callers are included in this c"),
|
|
2599
|
+
forward_enabled: bool = typer.Option(None, "--forward-enabled/--no-forward-enabled", help="Determines whether selective call forwarding is applied for"),
|
|
2600
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2601
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2602
|
+
):
|
|
2603
|
+
"""Modify Settings for a Selective Call Forwarding Criteria\n\nExample --json-body:\n '{"forwardToPhoneNumber":"...","destinationVoicemailEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true}'."""
|
|
2604
|
+
api = get_api(debug=debug)
|
|
2605
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveForward/criteria/{id}"
|
|
2606
|
+
if json_body:
|
|
2607
|
+
body = json.loads(json_body)
|
|
2608
|
+
else:
|
|
2609
|
+
body = {}
|
|
2610
|
+
if forward_to_phone_number is not None:
|
|
2611
|
+
body["forwardToPhoneNumber"] = forward_to_phone_number
|
|
2612
|
+
if destination_voicemail_enabled is not None:
|
|
2613
|
+
body["destinationVoicemailEnabled"] = destination_voicemail_enabled
|
|
2614
|
+
if schedule_name is not None:
|
|
2615
|
+
body["scheduleName"] = schedule_name
|
|
2616
|
+
if schedule_type is not None:
|
|
2617
|
+
body["scheduleType"] = schedule_type
|
|
2618
|
+
if schedule_level is not None:
|
|
2619
|
+
body["scheduleLevel"] = schedule_level
|
|
2620
|
+
if calls_from is not None:
|
|
2621
|
+
body["callsFrom"] = calls_from
|
|
2622
|
+
if anonymous_callers_enabled is not None:
|
|
2623
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2624
|
+
if unavailable_callers_enabled is not None:
|
|
2625
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2626
|
+
if forward_enabled is not None:
|
|
2627
|
+
body["forwardEnabled"] = forward_enabled
|
|
2628
|
+
try:
|
|
2629
|
+
result = api.session.rest_put(url, json=body)
|
|
2630
|
+
except WebexError as e:
|
|
2631
|
+
handle_rest_error(e)
|
|
2632
|
+
typer.echo(f"Updated.")
|
|
2633
|
+
|
|
2634
|
+
|
|
2635
|
+
|
|
2636
|
+
@app.command("delete-criteria-selective-forward")
|
|
2637
|
+
def delete_criteria_selective_forward(
|
|
2638
|
+
id: str = typer.Argument(help="id"),
|
|
2639
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2640
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2641
|
+
):
|
|
2642
|
+
"""Delete a Selective Call Forwarding Criteria."""
|
|
2643
|
+
if not force:
|
|
2644
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2645
|
+
api = get_api(debug=debug)
|
|
2646
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveForward/criteria/{id}"
|
|
2647
|
+
try:
|
|
2648
|
+
api.session.rest_delete(url)
|
|
2649
|
+
except WebexError as e:
|
|
2650
|
+
handle_rest_error(e)
|
|
2651
|
+
typer.echo(f"Deleted: {id}")
|
|
2652
|
+
|
|
2653
|
+
|
|
2654
|
+
|
|
2655
|
+
@app.command("list-selective-forward")
|
|
2656
|
+
def list_selective_forward(
|
|
2657
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2658
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2659
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2660
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2661
|
+
):
|
|
2662
|
+
"""Get Selective Call Forward Settings for User."""
|
|
2663
|
+
api = get_api(debug=debug)
|
|
2664
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveForward"
|
|
2665
|
+
params = {}
|
|
2666
|
+
if limit > 0:
|
|
2667
|
+
params["max"] = limit
|
|
2668
|
+
if offset > 0:
|
|
2669
|
+
params["start"] = offset
|
|
2670
|
+
result = None
|
|
2671
|
+
try:
|
|
2672
|
+
result = api.session.rest_get(url, params=params)
|
|
2673
|
+
except WebexError as e:
|
|
2674
|
+
handle_rest_error(e)
|
|
2675
|
+
result = result or []
|
|
2676
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2677
|
+
if output == "json":
|
|
2678
|
+
print_json(items)
|
|
2679
|
+
else:
|
|
2680
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2681
|
+
|
|
2682
|
+
|
|
2683
|
+
|
|
2684
|
+
@app.command("update-selective-forward")
|
|
2685
|
+
def update_selective_forward(
|
|
2686
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="`true` if the Selective Forward feature is enabled."),
|
|
2687
|
+
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"),
|
|
2688
|
+
ring_reminder_enabled: bool = typer.Option(None, "--ring-reminder-enabled/--no-ring-reminder-enabled", help="When `true`, enables a ring reminder for such calls."),
|
|
2689
|
+
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"),
|
|
2690
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2691
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2692
|
+
):
|
|
2693
|
+
"""Modify Selective Call Forward Settings for User."""
|
|
2694
|
+
api = get_api(debug=debug)
|
|
2695
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveForward"
|
|
2696
|
+
if json_body:
|
|
2697
|
+
body = json.loads(json_body)
|
|
2698
|
+
else:
|
|
2699
|
+
body = {}
|
|
2700
|
+
if enabled is not None:
|
|
2701
|
+
body["enabled"] = enabled
|
|
2702
|
+
if default_phone_number_to_forward is not None:
|
|
2703
|
+
body["defaultPhoneNumberToForward"] = default_phone_number_to_forward
|
|
2704
|
+
if ring_reminder_enabled is not None:
|
|
2705
|
+
body["ringReminderEnabled"] = ring_reminder_enabled
|
|
2706
|
+
if destination_voicemail_enabled is not None:
|
|
2707
|
+
body["destinationVoicemailEnabled"] = destination_voicemail_enabled
|
|
2708
|
+
try:
|
|
2709
|
+
result = api.session.rest_put(url, json=body)
|
|
2710
|
+
except WebexError as e:
|
|
2711
|
+
handle_rest_error(e)
|
|
2712
|
+
typer.echo(f"Updated.")
|
|
2713
|
+
|
|
2714
|
+
|
|
2715
|
+
|
|
2716
|
+
@app.command("list-selective-reject")
|
|
2717
|
+
def list_selective_reject(
|
|
2718
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
2719
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
2720
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
2721
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2722
|
+
):
|
|
2723
|
+
"""Get Selective Call Reject Settings for User."""
|
|
2724
|
+
api = get_api(debug=debug)
|
|
2725
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveReject"
|
|
2726
|
+
params = {}
|
|
2727
|
+
if limit > 0:
|
|
2728
|
+
params["max"] = limit
|
|
2729
|
+
if offset > 0:
|
|
2730
|
+
params["start"] = offset
|
|
2731
|
+
result = None
|
|
2732
|
+
try:
|
|
2733
|
+
result = api.session.rest_get(url, params=params)
|
|
2734
|
+
except WebexError as e:
|
|
2735
|
+
handle_rest_error(e)
|
|
2736
|
+
result = result or []
|
|
2737
|
+
items = result.get("criteria", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
2738
|
+
if output == "json":
|
|
2739
|
+
print_json(items)
|
|
2740
|
+
else:
|
|
2741
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
2742
|
+
|
|
2743
|
+
|
|
2744
|
+
|
|
2745
|
+
@app.command("update-selective-reject")
|
|
2746
|
+
def update_selective_reject(
|
|
2747
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="if `true`, selective reject is enabled."),
|
|
2748
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2749
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2750
|
+
):
|
|
2751
|
+
"""Modify Selective Call Reject Settings for User."""
|
|
2752
|
+
api = get_api(debug=debug)
|
|
2753
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveReject"
|
|
2754
|
+
if json_body:
|
|
2755
|
+
body = json.loads(json_body)
|
|
2756
|
+
else:
|
|
2757
|
+
body = {}
|
|
2758
|
+
if enabled is not None:
|
|
2759
|
+
body["enabled"] = enabled
|
|
2760
|
+
try:
|
|
2761
|
+
result = api.session.rest_put(url, json=body)
|
|
2762
|
+
except WebexError as e:
|
|
2763
|
+
handle_rest_error(e)
|
|
2764
|
+
typer.echo(f"Updated.")
|
|
2765
|
+
|
|
2766
|
+
|
|
2767
|
+
|
|
2768
|
+
@app.command("create-criteria-selective-reject")
|
|
2769
|
+
def create_criteria_selective_reject(
|
|
2770
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to which the criteria is created."),
|
|
2771
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2772
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, GROUP"),
|
|
2773
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, FORWARDED"),
|
|
2774
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Boolean flag indicating if calls from custom numbers, privat"),
|
|
2775
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Boolean flag indicating if calls from custom numbers, unavai"),
|
|
2776
|
+
reject_enabled: bool = typer.Option(None, "--reject-enabled/--no-reject-enabled", help="(required) Boolean flag to enable/disable rejection."),
|
|
2777
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2778
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
2779
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2780
|
+
):
|
|
2781
|
+
"""Add User Selective Call Reject Criteria\n\nExample --json-body:\n '{"callsFrom":"ANY_PHONE_NUMBER","rejectEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2782
|
+
api = get_api(debug=debug)
|
|
2783
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveReject/criteria"
|
|
2784
|
+
if json_body:
|
|
2785
|
+
body = json.loads(json_body)
|
|
2786
|
+
else:
|
|
2787
|
+
body = {}
|
|
2788
|
+
if schedule_name is not None:
|
|
2789
|
+
body["scheduleName"] = schedule_name
|
|
2790
|
+
if schedule_type is not None:
|
|
2791
|
+
body["scheduleType"] = schedule_type
|
|
2792
|
+
if schedule_level is not None:
|
|
2793
|
+
body["scheduleLevel"] = schedule_level
|
|
2794
|
+
if calls_from is not None:
|
|
2795
|
+
body["callsFrom"] = calls_from
|
|
2796
|
+
if anonymous_callers_enabled is not None:
|
|
2797
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2798
|
+
if unavailable_callers_enabled is not None:
|
|
2799
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2800
|
+
if reject_enabled is not None:
|
|
2801
|
+
body["rejectEnabled"] = reject_enabled
|
|
2802
|
+
_missing = [f for f in ['callsFrom', 'rejectEnabled'] if f not in body or body[f] is None]
|
|
2803
|
+
if _missing:
|
|
2804
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
2805
|
+
raise typer.Exit(1)
|
|
2806
|
+
try:
|
|
2807
|
+
result = api.session.rest_post(url, json=body)
|
|
2808
|
+
except WebexError as e:
|
|
2809
|
+
handle_rest_error(e)
|
|
2810
|
+
if output == "json":
|
|
2811
|
+
print_json(result)
|
|
2812
|
+
elif isinstance(result, dict) and "id" in result:
|
|
2813
|
+
typer.echo(f"Created: {result['id']}")
|
|
2814
|
+
elif not result or result == {}:
|
|
2815
|
+
typer.echo("Created.")
|
|
2816
|
+
else:
|
|
2817
|
+
print_json(result)
|
|
2818
|
+
|
|
2819
|
+
|
|
2820
|
+
|
|
2821
|
+
@app.command("show-anonymous-call-reject")
|
|
2822
|
+
def show_anonymous_call_reject(
|
|
2823
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2824
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2825
|
+
):
|
|
2826
|
+
"""Get Anonymous Call Rejection Settings for User."""
|
|
2827
|
+
api = get_api(debug=debug)
|
|
2828
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/anonymousCallReject"
|
|
2829
|
+
try:
|
|
2830
|
+
result = api.session.rest_get(url)
|
|
2831
|
+
except WebexError as e:
|
|
2832
|
+
handle_rest_error(e)
|
|
2833
|
+
if output == "json":
|
|
2834
|
+
print_json(result)
|
|
2835
|
+
else:
|
|
2836
|
+
if isinstance(result, dict):
|
|
2837
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2838
|
+
elif isinstance(result, list):
|
|
2839
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2840
|
+
else:
|
|
2841
|
+
print_json(result)
|
|
2842
|
+
|
|
2843
|
+
|
|
2844
|
+
|
|
2845
|
+
@app.command("update-anonymous-call-reject")
|
|
2846
|
+
def update_anonymous_call_reject(
|
|
2847
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Indicates whether Anonymous Call Rejection is enabled or not"),
|
|
2848
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2849
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2850
|
+
):
|
|
2851
|
+
"""Modify Anonymous Call Rejection Settings for User."""
|
|
2852
|
+
api = get_api(debug=debug)
|
|
2853
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/anonymousCallReject"
|
|
2854
|
+
if json_body:
|
|
2855
|
+
body = json.loads(json_body)
|
|
2856
|
+
else:
|
|
2857
|
+
body = {}
|
|
2858
|
+
if enabled is not None:
|
|
2859
|
+
body["enabled"] = enabled
|
|
2860
|
+
try:
|
|
2861
|
+
result = api.session.rest_put(url, json=body)
|
|
2862
|
+
except WebexError as e:
|
|
2863
|
+
handle_rest_error(e)
|
|
2864
|
+
typer.echo(f"Updated.")
|
|
2865
|
+
|
|
2866
|
+
|
|
2867
|
+
|
|
2868
|
+
@app.command("show-criteria-selective-reject")
|
|
2869
|
+
def show_criteria_selective_reject(
|
|
2870
|
+
id: str = typer.Argument(help="id"),
|
|
2871
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2872
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2873
|
+
):
|
|
2874
|
+
"""Get Selective Call Reject Criteria Settings for User."""
|
|
2875
|
+
api = get_api(debug=debug)
|
|
2876
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveReject/criteria/{id}"
|
|
2877
|
+
try:
|
|
2878
|
+
result = api.session.rest_get(url)
|
|
2879
|
+
except WebexError as e:
|
|
2880
|
+
handle_rest_error(e)
|
|
2881
|
+
if output == "json":
|
|
2882
|
+
print_json(result)
|
|
2883
|
+
else:
|
|
2884
|
+
if isinstance(result, dict):
|
|
2885
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2886
|
+
elif isinstance(result, list):
|
|
2887
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2888
|
+
else:
|
|
2889
|
+
print_json(result)
|
|
2890
|
+
|
|
2891
|
+
|
|
2892
|
+
|
|
2893
|
+
@app.command("update-criteria-selective-reject")
|
|
2894
|
+
def update_criteria_selective_reject(
|
|
2895
|
+
id: str = typer.Argument(help="id"),
|
|
2896
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to which the criteria is created."),
|
|
2897
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
2898
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, GROUP"),
|
|
2899
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS, FORWARDED"),
|
|
2900
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="Boolean flag indicating if calls from custom numbers, privat"),
|
|
2901
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="Boolean flag indicating if calls from custom numbers, unavai"),
|
|
2902
|
+
reject_enabled: bool = typer.Option(None, "--reject-enabled/--no-reject-enabled", help="Boolean flag to enable/disable rejection."),
|
|
2903
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2904
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2905
|
+
):
|
|
2906
|
+
"""Modify a Selective Call Reject Criteria\n\nExample --json-body:\n '{"callsFrom":"ANY_PHONE_NUMBER","rejectEnabled":true,"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
2907
|
+
api = get_api(debug=debug)
|
|
2908
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveReject/criteria/{id}"
|
|
2909
|
+
if json_body:
|
|
2910
|
+
body = json.loads(json_body)
|
|
2911
|
+
else:
|
|
2912
|
+
body = {}
|
|
2913
|
+
if schedule_name is not None:
|
|
2914
|
+
body["scheduleName"] = schedule_name
|
|
2915
|
+
if schedule_type is not None:
|
|
2916
|
+
body["scheduleType"] = schedule_type
|
|
2917
|
+
if schedule_level is not None:
|
|
2918
|
+
body["scheduleLevel"] = schedule_level
|
|
2919
|
+
if calls_from is not None:
|
|
2920
|
+
body["callsFrom"] = calls_from
|
|
2921
|
+
if anonymous_callers_enabled is not None:
|
|
2922
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
2923
|
+
if unavailable_callers_enabled is not None:
|
|
2924
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
2925
|
+
if reject_enabled is not None:
|
|
2926
|
+
body["rejectEnabled"] = reject_enabled
|
|
2927
|
+
try:
|
|
2928
|
+
result = api.session.rest_put(url, json=body)
|
|
2929
|
+
except WebexError as e:
|
|
2930
|
+
handle_rest_error(e)
|
|
2931
|
+
typer.echo(f"Updated.")
|
|
2932
|
+
|
|
2933
|
+
|
|
2934
|
+
|
|
2935
|
+
@app.command("delete-criteria-selective-reject")
|
|
2936
|
+
def delete_criteria_selective_reject(
|
|
2937
|
+
id: str = typer.Argument(help="id"),
|
|
2938
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
2939
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2940
|
+
):
|
|
2941
|
+
"""Delete a Selective Call Reject Criteria."""
|
|
2942
|
+
if not force:
|
|
2943
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
2944
|
+
api = get_api(debug=debug)
|
|
2945
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/selectiveReject/criteria/{id}"
|
|
2946
|
+
try:
|
|
2947
|
+
api.session.rest_delete(url)
|
|
2948
|
+
except WebexError as e:
|
|
2949
|
+
handle_rest_error(e)
|
|
2950
|
+
typer.echo(f"Deleted: {id}")
|
|
2951
|
+
|
|
2952
|
+
|
|
2953
|
+
|
|
2954
|
+
@app.command("show-call-waiting")
|
|
2955
|
+
def show_call_waiting(
|
|
2956
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
2957
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2958
|
+
):
|
|
2959
|
+
"""Get Call Waiting Settings for User."""
|
|
2960
|
+
api = get_api(debug=debug)
|
|
2961
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callWaiting"
|
|
2962
|
+
try:
|
|
2963
|
+
result = api.session.rest_get(url)
|
|
2964
|
+
except WebexError as e:
|
|
2965
|
+
handle_rest_error(e)
|
|
2966
|
+
if output == "json":
|
|
2967
|
+
print_json(result)
|
|
2968
|
+
else:
|
|
2969
|
+
if isinstance(result, dict):
|
|
2970
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
2971
|
+
elif isinstance(result, list):
|
|
2972
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
2973
|
+
else:
|
|
2974
|
+
print_json(result)
|
|
2975
|
+
|
|
2976
|
+
|
|
2977
|
+
|
|
2978
|
+
@app.command("update-call-waiting")
|
|
2979
|
+
def update_call_waiting(
|
|
2980
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Enable or disable Call Waiting for the user."),
|
|
2981
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
2982
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
2983
|
+
):
|
|
2984
|
+
"""Modify Call Waiting Settings for User."""
|
|
2985
|
+
api = get_api(debug=debug)
|
|
2986
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/callWaiting"
|
|
2987
|
+
if json_body:
|
|
2988
|
+
body = json.loads(json_body)
|
|
2989
|
+
else:
|
|
2990
|
+
body = {}
|
|
2991
|
+
if enabled is not None:
|
|
2992
|
+
body["enabled"] = enabled
|
|
2993
|
+
try:
|
|
2994
|
+
result = api.session.rest_put(url, json=body)
|
|
2995
|
+
except WebexError as e:
|
|
2996
|
+
handle_rest_error(e)
|
|
2997
|
+
typer.echo(f"Updated.")
|
|
2998
|
+
|
|
2999
|
+
|
|
3000
|
+
|
|
3001
|
+
@app.command("list-sequential-ring")
|
|
3002
|
+
def list_sequential_ring(
|
|
3003
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3004
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3005
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3006
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3007
|
+
):
|
|
3008
|
+
"""Get Sequential Ring Settings for User."""
|
|
3009
|
+
api = get_api(debug=debug)
|
|
3010
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/sequentialRing"
|
|
3011
|
+
params = {}
|
|
3012
|
+
if limit > 0:
|
|
3013
|
+
params["max"] = limit
|
|
3014
|
+
if offset > 0:
|
|
3015
|
+
params["start"] = offset
|
|
3016
|
+
result = None
|
|
3017
|
+
try:
|
|
3018
|
+
result = api.session.rest_get(url, params=params)
|
|
3019
|
+
except WebexError as e:
|
|
3020
|
+
handle_rest_error(e)
|
|
3021
|
+
result = result or []
|
|
3022
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3023
|
+
if output == "json":
|
|
3024
|
+
print_json(items)
|
|
3025
|
+
else:
|
|
3026
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
|
|
3030
|
+
@app.command("update-sequential-ring")
|
|
3031
|
+
def update_sequential_ring(
|
|
3032
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Enable or disable sequential ring for the user."),
|
|
3033
|
+
ring_base_location_first_enabled: bool = typer.Option(None, "--ring-base-location-first-enabled/--no-ring-base-location-first-enabled", help="When `true`, the user's own devices ring before sequential r"),
|
|
3034
|
+
base_location_number_of_rings: str = typer.Option(None, "--base-location-number-of-rings", help="Number of rings for the user's own devices. Minimum: 2, Maxi"),
|
|
3035
|
+
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 `true`, sequential ring continues even when the user is"),
|
|
3036
|
+
calls_to_voicemail_enabled: bool = typer.Option(None, "--calls-to-voicemail-enabled/--no-calls-to-voicemail-enabled", help="When `true`, the caller is provided the option to press the"),
|
|
3037
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3038
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3039
|
+
):
|
|
3040
|
+
"""Modify Sequential Ring Settings for User\n\nExample --json-body:\n '{"enabled":true,"ringBaseLocationFirstEnabled":true,"baseLocationNumberOfRings":0,"continueIfBaseLocationIsBusyEnabled":true,"callsToVoicemailEnabled":true,"phoneNumbers":[{"answerConfirmationRequiredEnabled":"...","numberOfRings":"...","phoneNumber":"..."}]}'."""
|
|
3041
|
+
api = get_api(debug=debug)
|
|
3042
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/sequentialRing"
|
|
3043
|
+
if json_body:
|
|
3044
|
+
body = json.loads(json_body)
|
|
3045
|
+
else:
|
|
3046
|
+
body = {}
|
|
3047
|
+
if enabled is not None:
|
|
3048
|
+
body["enabled"] = enabled
|
|
3049
|
+
if ring_base_location_first_enabled is not None:
|
|
3050
|
+
body["ringBaseLocationFirstEnabled"] = ring_base_location_first_enabled
|
|
3051
|
+
if base_location_number_of_rings is not None:
|
|
3052
|
+
body["baseLocationNumberOfRings"] = base_location_number_of_rings
|
|
3053
|
+
if continue_if_base_location_is_busy_enabled is not None:
|
|
3054
|
+
body["continueIfBaseLocationIsBusyEnabled"] = continue_if_base_location_is_busy_enabled
|
|
3055
|
+
if calls_to_voicemail_enabled is not None:
|
|
3056
|
+
body["callsToVoicemailEnabled"] = calls_to_voicemail_enabled
|
|
3057
|
+
try:
|
|
3058
|
+
result = api.session.rest_put(url, json=body)
|
|
3059
|
+
except WebexError as e:
|
|
3060
|
+
handle_rest_error(e)
|
|
3061
|
+
typer.echo(f"Updated.")
|
|
3062
|
+
|
|
3063
|
+
|
|
3064
|
+
|
|
3065
|
+
@app.command("create-criteria-sequential-ring")
|
|
3066
|
+
def create_criteria_sequential_ring(
|
|
3067
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the location's schedule which determines when the se"),
|
|
3068
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: holidays, businessHours"),
|
|
3069
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: GROUP"),
|
|
3070
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: SELECT_PHONE_NUMBERS, ANY_PHONE_NUMBER"),
|
|
3071
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true` incoming calls from private numbers are allowed."),
|
|
3072
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true` incoming calls from unavailable numbers are allo"),
|
|
3073
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="(required) When set to `true` sequential ringing is enabled for calls t"),
|
|
3074
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3075
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
3076
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3077
|
+
):
|
|
3078
|
+
"""Add User Sequential Ring Criteria\n\nExample --json-body:\n '{"callsFrom":"SELECT_PHONE_NUMBERS","ringEnabled":true,"scheduleName":"...","scheduleType":"holidays","scheduleLevel":"GROUP","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
3079
|
+
api = get_api(debug=debug)
|
|
3080
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/sequentialRing/criteria"
|
|
3081
|
+
if json_body:
|
|
3082
|
+
body = json.loads(json_body)
|
|
3083
|
+
else:
|
|
3084
|
+
body = {}
|
|
3085
|
+
if schedule_name is not None:
|
|
3086
|
+
body["scheduleName"] = schedule_name
|
|
3087
|
+
if schedule_type is not None:
|
|
3088
|
+
body["scheduleType"] = schedule_type
|
|
3089
|
+
if schedule_level is not None:
|
|
3090
|
+
body["scheduleLevel"] = schedule_level
|
|
3091
|
+
if calls_from is not None:
|
|
3092
|
+
body["callsFrom"] = calls_from
|
|
3093
|
+
if anonymous_callers_enabled is not None:
|
|
3094
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3095
|
+
if unavailable_callers_enabled is not None:
|
|
3096
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3097
|
+
if ring_enabled is not None:
|
|
3098
|
+
body["ringEnabled"] = ring_enabled
|
|
3099
|
+
_missing = [f for f in ['callsFrom', 'ringEnabled'] if f not in body or body[f] is None]
|
|
3100
|
+
if _missing:
|
|
3101
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
3102
|
+
raise typer.Exit(1)
|
|
3103
|
+
try:
|
|
3104
|
+
result = api.session.rest_post(url, json=body)
|
|
3105
|
+
except WebexError as e:
|
|
3106
|
+
handle_rest_error(e)
|
|
3107
|
+
if output == "json":
|
|
3108
|
+
print_json(result)
|
|
3109
|
+
elif isinstance(result, dict) and "id" in result:
|
|
3110
|
+
typer.echo(f"Created: {result['id']}")
|
|
3111
|
+
elif not result or result == {}:
|
|
3112
|
+
typer.echo("Created.")
|
|
3113
|
+
else:
|
|
3114
|
+
print_json(result)
|
|
3115
|
+
|
|
3116
|
+
|
|
3117
|
+
|
|
3118
|
+
@app.command("show-criteria-sequential-ring")
|
|
3119
|
+
def show_criteria_sequential_ring(
|
|
3120
|
+
id: str = typer.Argument(help="id"),
|
|
3121
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
3122
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3123
|
+
):
|
|
3124
|
+
"""Get Sequential Ring Criteria Settings for User."""
|
|
3125
|
+
api = get_api(debug=debug)
|
|
3126
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/sequentialRing/criteria/{id}"
|
|
3127
|
+
try:
|
|
3128
|
+
result = api.session.rest_get(url)
|
|
3129
|
+
except WebexError as e:
|
|
3130
|
+
handle_rest_error(e)
|
|
3131
|
+
if output == "json":
|
|
3132
|
+
print_json(result)
|
|
3133
|
+
else:
|
|
3134
|
+
if isinstance(result, dict):
|
|
3135
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
3136
|
+
elif isinstance(result, list):
|
|
3137
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
3138
|
+
else:
|
|
3139
|
+
print_json(result)
|
|
3140
|
+
|
|
3141
|
+
|
|
3142
|
+
|
|
3143
|
+
@app.command("update-criteria-sequential-ring")
|
|
3144
|
+
def update_criteria_sequential_ring(
|
|
3145
|
+
id: str = typer.Argument(help="id"),
|
|
3146
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule to be associated with the criteria."),
|
|
3147
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
3148
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, LOCATION"),
|
|
3149
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
3150
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, means this criteria applies for anonymous calle"),
|
|
3151
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, means this criteria applies for unavailable cal"),
|
|
3152
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="Determines whether sequential ring is applied for calls matc"),
|
|
3153
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3154
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3155
|
+
):
|
|
3156
|
+
"""Modify Sequential Ring Criteria Settings for User\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"ringEnabled":true}'."""
|
|
3157
|
+
api = get_api(debug=debug)
|
|
3158
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/sequentialRing/criteria/{id}"
|
|
3159
|
+
if json_body:
|
|
3160
|
+
body = json.loads(json_body)
|
|
3161
|
+
else:
|
|
3162
|
+
body = {}
|
|
3163
|
+
if schedule_name is not None:
|
|
3164
|
+
body["scheduleName"] = schedule_name
|
|
3165
|
+
if schedule_type is not None:
|
|
3166
|
+
body["scheduleType"] = schedule_type
|
|
3167
|
+
if schedule_level is not None:
|
|
3168
|
+
body["scheduleLevel"] = schedule_level
|
|
3169
|
+
if calls_from is not None:
|
|
3170
|
+
body["callsFrom"] = calls_from
|
|
3171
|
+
if anonymous_callers_enabled is not None:
|
|
3172
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3173
|
+
if unavailable_callers_enabled is not None:
|
|
3174
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3175
|
+
if ring_enabled is not None:
|
|
3176
|
+
body["ringEnabled"] = ring_enabled
|
|
3177
|
+
try:
|
|
3178
|
+
result = api.session.rest_put(url, json=body)
|
|
3179
|
+
except WebexError as e:
|
|
3180
|
+
handle_rest_error(e)
|
|
3181
|
+
typer.echo(f"Updated.")
|
|
3182
|
+
|
|
3183
|
+
|
|
3184
|
+
|
|
3185
|
+
@app.command("delete-criteria-sequential-ring")
|
|
3186
|
+
def delete_criteria_sequential_ring(
|
|
3187
|
+
id: str = typer.Argument(help="id"),
|
|
3188
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
3189
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3190
|
+
):
|
|
3191
|
+
"""Delete Sequential Ring Criteria."""
|
|
3192
|
+
if not force:
|
|
3193
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
3194
|
+
api = get_api(debug=debug)
|
|
3195
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/sequentialRing/criteria/{id}"
|
|
3196
|
+
try:
|
|
3197
|
+
api.session.rest_delete(url)
|
|
3198
|
+
except WebexError as e:
|
|
3199
|
+
handle_rest_error(e)
|
|
3200
|
+
typer.echo(f"Deleted: {id}")
|
|
3201
|
+
|
|
3202
|
+
|
|
3203
|
+
|
|
3204
|
+
@app.command("list-simultaneous-ring")
|
|
3205
|
+
def list_simultaneous_ring(
|
|
3206
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3207
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3208
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3209
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3210
|
+
):
|
|
3211
|
+
"""Retrieve My Simultaneous Ring Settings."""
|
|
3212
|
+
api = get_api(debug=debug)
|
|
3213
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/simultaneousRing"
|
|
3214
|
+
params = {}
|
|
3215
|
+
if limit > 0:
|
|
3216
|
+
params["max"] = limit
|
|
3217
|
+
if offset > 0:
|
|
3218
|
+
params["start"] = offset
|
|
3219
|
+
result = None
|
|
3220
|
+
try:
|
|
3221
|
+
result = api.session.rest_get(url, params=params)
|
|
3222
|
+
except WebexError as e:
|
|
3223
|
+
handle_rest_error(e)
|
|
3224
|
+
result = result or []
|
|
3225
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3226
|
+
if output == "json":
|
|
3227
|
+
print_json(items)
|
|
3228
|
+
else:
|
|
3229
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3230
|
+
|
|
3231
|
+
|
|
3232
|
+
|
|
3233
|
+
@app.command("update-simultaneous-ring")
|
|
3234
|
+
def update_simultaneous_ring(
|
|
3235
|
+
enabled: bool = typer.Option(None, "--enabled/--no-enabled", help="Simultaneous Ring is enabled or not."),
|
|
3236
|
+
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"),
|
|
3237
|
+
criterias_enabled: bool = typer.Option(None, "--criterias-enabled/--no-criterias-enabled", help="Controls whether the criteria for simultaneous ring are enab"),
|
|
3238
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3239
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3240
|
+
):
|
|
3241
|
+
"""Modify My Simultaneous Ring Settings\n\nExample --json-body:\n '{"enabled":true,"doNotRingIfOnCallEnabled":true,"phoneNumbers":[{"phoneNumber":"...","answerConfirmationEnabled":"..."}],"criteriasEnabled":true}'."""
|
|
3242
|
+
api = get_api(debug=debug)
|
|
3243
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/simultaneousRing"
|
|
3244
|
+
if json_body:
|
|
3245
|
+
body = json.loads(json_body)
|
|
3246
|
+
else:
|
|
3247
|
+
body = {}
|
|
3248
|
+
if enabled is not None:
|
|
3249
|
+
body["enabled"] = enabled
|
|
3250
|
+
if do_not_ring_if_on_call_enabled is not None:
|
|
3251
|
+
body["doNotRingIfOnCallEnabled"] = do_not_ring_if_on_call_enabled
|
|
3252
|
+
if criterias_enabled is not None:
|
|
3253
|
+
body["criteriasEnabled"] = criterias_enabled
|
|
3254
|
+
try:
|
|
3255
|
+
result = api.session.rest_put(url, json=body)
|
|
3256
|
+
except WebexError as e:
|
|
3257
|
+
handle_rest_error(e)
|
|
3258
|
+
typer.echo(f"Updated.")
|
|
3259
|
+
|
|
3260
|
+
|
|
3261
|
+
|
|
3262
|
+
@app.command("show-criteria-simultaneous-ring")
|
|
3263
|
+
def show_criteria_simultaneous_ring(
|
|
3264
|
+
id: str = typer.Argument(help="id"),
|
|
3265
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
3266
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3267
|
+
):
|
|
3268
|
+
"""Retrieve My Simultaneous Ring Criteria."""
|
|
3269
|
+
api = get_api(debug=debug)
|
|
3270
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/simultaneousRing/criteria/{id}"
|
|
3271
|
+
try:
|
|
3272
|
+
result = api.session.rest_get(url)
|
|
3273
|
+
except WebexError as e:
|
|
3274
|
+
handle_rest_error(e)
|
|
3275
|
+
if output == "json":
|
|
3276
|
+
print_json(result)
|
|
3277
|
+
else:
|
|
3278
|
+
if isinstance(result, dict):
|
|
3279
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
3280
|
+
elif isinstance(result, list):
|
|
3281
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
3282
|
+
else:
|
|
3283
|
+
print_json(result)
|
|
3284
|
+
|
|
3285
|
+
|
|
3286
|
+
|
|
3287
|
+
@app.command("update-criteria-simultaneous-ring")
|
|
3288
|
+
def update_criteria_simultaneous_ring(
|
|
3289
|
+
id: str = typer.Argument(help="id"),
|
|
3290
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="Name of the schedule which determines when the simultaneous"),
|
|
3291
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="Choices: businessHours, holidays"),
|
|
3292
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="Choices: PEOPLE, GROUP"),
|
|
3293
|
+
calls_from: str = typer.Option(None, "--calls-from", help="Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
3294
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, the criteria applies to calls from anonymous ca"),
|
|
3295
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, the criteria applies to calls from unavailable"),
|
|
3296
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="When set to `true` simultaneous ringing is enabled for calls"),
|
|
3297
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3298
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3299
|
+
):
|
|
3300
|
+
"""Modify My Simultaneous Ring Criteria\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."],"ringEnabled":true}'."""
|
|
3301
|
+
api = get_api(debug=debug)
|
|
3302
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/simultaneousRing/criteria/{id}"
|
|
3303
|
+
if json_body:
|
|
3304
|
+
body = json.loads(json_body)
|
|
3305
|
+
else:
|
|
3306
|
+
body = {}
|
|
3307
|
+
if schedule_name is not None:
|
|
3308
|
+
body["scheduleName"] = schedule_name
|
|
3309
|
+
if schedule_type is not None:
|
|
3310
|
+
body["scheduleType"] = schedule_type
|
|
3311
|
+
if schedule_level is not None:
|
|
3312
|
+
body["scheduleLevel"] = schedule_level
|
|
3313
|
+
if calls_from is not None:
|
|
3314
|
+
body["callsFrom"] = calls_from
|
|
3315
|
+
if anonymous_callers_enabled is not None:
|
|
3316
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3317
|
+
if unavailable_callers_enabled is not None:
|
|
3318
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3319
|
+
if ring_enabled is not None:
|
|
3320
|
+
body["ringEnabled"] = ring_enabled
|
|
3321
|
+
try:
|
|
3322
|
+
result = api.session.rest_put(url, json=body)
|
|
3323
|
+
except WebexError as e:
|
|
3324
|
+
handle_rest_error(e)
|
|
3325
|
+
typer.echo(f"Updated.")
|
|
3326
|
+
|
|
3327
|
+
|
|
3328
|
+
|
|
3329
|
+
@app.command("delete-criteria-simultaneous-ring")
|
|
3330
|
+
def delete_criteria_simultaneous_ring(
|
|
3331
|
+
id: str = typer.Argument(help="id"),
|
|
3332
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
3333
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3334
|
+
):
|
|
3335
|
+
"""Delete My Simultaneous Ring Criteria."""
|
|
3336
|
+
if not force:
|
|
3337
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
3338
|
+
api = get_api(debug=debug)
|
|
3339
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/simultaneousRing/criteria/{id}"
|
|
3340
|
+
try:
|
|
3341
|
+
api.session.rest_delete(url)
|
|
3342
|
+
except WebexError as e:
|
|
3343
|
+
handle_rest_error(e)
|
|
3344
|
+
typer.echo(f"Deleted: {id}")
|
|
3345
|
+
|
|
3346
|
+
|
|
3347
|
+
|
|
3348
|
+
@app.command("create-criteria-simultaneous-ring")
|
|
3349
|
+
def create_criteria_simultaneous_ring(
|
|
3350
|
+
schedule_name: str = typer.Option(None, "--schedule-name", help="(required) Name of the schedule which determines when the simultaneous"),
|
|
3351
|
+
schedule_type: str = typer.Option(None, "--schedule-type", help="(required) Choices: businessHours, holidays"),
|
|
3352
|
+
schedule_level: str = typer.Option(None, "--schedule-level", help="(required) Choices: PEOPLE, GROUP"),
|
|
3353
|
+
calls_from: str = typer.Option(None, "--calls-from", help="(required) Choices: ANY_PHONE_NUMBER, SELECT_PHONE_NUMBERS"),
|
|
3354
|
+
anonymous_callers_enabled: bool = typer.Option(None, "--anonymous-callers-enabled/--no-anonymous-callers-enabled", help="When `true`, the criteria applies to calls from anonymous ca"),
|
|
3355
|
+
unavailable_callers_enabled: bool = typer.Option(None, "--unavailable-callers-enabled/--no-unavailable-callers-enabled", help="When `true`, the criteria applies to calls from unavailable"),
|
|
3356
|
+
ring_enabled: bool = typer.Option(None, "--ring-enabled/--no-ring-enabled", help="(required) When set to `true` simultaneous ringing is enabled for calls"),
|
|
3357
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3358
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
3359
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3360
|
+
):
|
|
3361
|
+
"""Create My Simultaneous Ring Criteria\n\nExample --json-body:\n '{"scheduleName":"...","scheduleType":"businessHours","scheduleLevel":"PEOPLE","callsFrom":"ANY_PHONE_NUMBER","ringEnabled":true,"anonymousCallersEnabled":true,"unavailableCallersEnabled":true,"phoneNumbers":["..."]}'."""
|
|
3362
|
+
api = get_api(debug=debug)
|
|
3363
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/simultaneousRing/criteria"
|
|
3364
|
+
if json_body:
|
|
3365
|
+
body = json.loads(json_body)
|
|
3366
|
+
else:
|
|
3367
|
+
body = {}
|
|
3368
|
+
if schedule_name is not None:
|
|
3369
|
+
body["scheduleName"] = schedule_name
|
|
3370
|
+
if schedule_type is not None:
|
|
3371
|
+
body["scheduleType"] = schedule_type
|
|
3372
|
+
if schedule_level is not None:
|
|
3373
|
+
body["scheduleLevel"] = schedule_level
|
|
3374
|
+
if calls_from is not None:
|
|
3375
|
+
body["callsFrom"] = calls_from
|
|
3376
|
+
if anonymous_callers_enabled is not None:
|
|
3377
|
+
body["anonymousCallersEnabled"] = anonymous_callers_enabled
|
|
3378
|
+
if unavailable_callers_enabled is not None:
|
|
3379
|
+
body["unavailableCallersEnabled"] = unavailable_callers_enabled
|
|
3380
|
+
if ring_enabled is not None:
|
|
3381
|
+
body["ringEnabled"] = ring_enabled
|
|
3382
|
+
_missing = [f for f in ['scheduleName', 'scheduleType', 'scheduleLevel', 'callsFrom', 'ringEnabled'] if f not in body or body[f] is None]
|
|
3383
|
+
if _missing:
|
|
3384
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
3385
|
+
raise typer.Exit(1)
|
|
3386
|
+
try:
|
|
3387
|
+
result = api.session.rest_post(url, json=body)
|
|
3388
|
+
except WebexError as e:
|
|
3389
|
+
handle_rest_error(e)
|
|
3390
|
+
if output == "json":
|
|
3391
|
+
print_json(result)
|
|
3392
|
+
elif isinstance(result, dict) and "id" in result:
|
|
3393
|
+
typer.echo(f"Created: {result['id']}")
|
|
3394
|
+
elif not result or result == {}:
|
|
3395
|
+
typer.echo("Created.")
|
|
3396
|
+
else:
|
|
3397
|
+
print_json(result)
|
|
3398
|
+
|
|
3399
|
+
|
|
3400
|
+
|
|
3401
|
+
@app.command("list-numbers")
|
|
3402
|
+
def list_numbers(
|
|
3403
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3404
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3405
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3406
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3407
|
+
):
|
|
3408
|
+
"""Retrieve My Guest Calling Numbers."""
|
|
3409
|
+
api = get_api(debug=debug)
|
|
3410
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/guestCalling/numbers"
|
|
3411
|
+
params = {}
|
|
3412
|
+
if limit > 0:
|
|
3413
|
+
params["max"] = limit
|
|
3414
|
+
if offset > 0:
|
|
3415
|
+
params["start"] = offset
|
|
3416
|
+
result = None
|
|
3417
|
+
try:
|
|
3418
|
+
result = api.session.rest_get(url, params=params)
|
|
3419
|
+
except WebexError as e:
|
|
3420
|
+
handle_rest_error(e)
|
|
3421
|
+
result = result or []
|
|
3422
|
+
items = result.get("phoneNumbers", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3423
|
+
if output == "json":
|
|
3424
|
+
print_json(items)
|
|
3425
|
+
else:
|
|
3426
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3427
|
+
|
|
3428
|
+
|
|
3429
|
+
|
|
3430
|
+
@app.command("list-speed-dials")
|
|
3431
|
+
def list_speed_dials(
|
|
3432
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3433
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3434
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3435
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3436
|
+
):
|
|
3437
|
+
"""Get Speed Dials."""
|
|
3438
|
+
api = get_api(debug=debug)
|
|
3439
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/speedDials"
|
|
3440
|
+
params = {}
|
|
3441
|
+
if limit > 0:
|
|
3442
|
+
params["max"] = limit
|
|
3443
|
+
if offset > 0:
|
|
3444
|
+
params["start"] = offset
|
|
3445
|
+
result = None
|
|
3446
|
+
try:
|
|
3447
|
+
result = api.session.rest_get(url, params=params)
|
|
3448
|
+
except WebexError as e:
|
|
3449
|
+
handle_rest_error(e)
|
|
3450
|
+
result = result or []
|
|
3451
|
+
items = result.get("speedDials", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3452
|
+
if output == "json":
|
|
3453
|
+
print_json(items)
|
|
3454
|
+
else:
|
|
3455
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3456
|
+
|
|
3457
|
+
|
|
3458
|
+
|
|
3459
|
+
@app.command("update-speed-dials")
|
|
3460
|
+
def update_speed_dials(
|
|
3461
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
3462
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3463
|
+
):
|
|
3464
|
+
"""Modify Speed Dials\n\nExample --json-body:\n '{"speedDials":[{"id":"...","phoneNumber":"...","lineKeyLabel":"..."}]}'."""
|
|
3465
|
+
api = get_api(debug=debug)
|
|
3466
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/speedDials"
|
|
3467
|
+
if json_body:
|
|
3468
|
+
body = json.loads(json_body)
|
|
3469
|
+
else:
|
|
3470
|
+
body = {}
|
|
3471
|
+
try:
|
|
3472
|
+
result = api.session.rest_put(url, json=body)
|
|
3473
|
+
except WebexError as e:
|
|
3474
|
+
handle_rest_error(e)
|
|
3475
|
+
typer.echo(f"Updated.")
|
|
3476
|
+
|
|
3477
|
+
|
|
3478
|
+
|
|
3479
|
+
@app.command("list-available-members")
|
|
3480
|
+
def list_available_members(
|
|
3481
|
+
location_id: str = typer.Option(None, "--location-id", help="Return the members list available in this location."),
|
|
3482
|
+
name: str = typer.Option(None, "--name", help="Search (Contains) based on first name and last name."),
|
|
3483
|
+
phone_number: str = typer.Option(None, "--phone-number", help="Search (Contains) based on number and extension."),
|
|
3484
|
+
order: str = typer.Option(None, "--order", help="Sort by first name (`firstName`) or last name (`lastName`)."),
|
|
3485
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3486
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3487
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3488
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3489
|
+
):
|
|
3490
|
+
"""Get Speed Dial Available Members."""
|
|
3491
|
+
api = get_api(debug=debug)
|
|
3492
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/settings/speedDials/availableMembers"
|
|
3493
|
+
params = {}
|
|
3494
|
+
if location_id is not None:
|
|
3495
|
+
params["locationId"] = location_id
|
|
3496
|
+
if name is not None:
|
|
3497
|
+
params["name"] = name
|
|
3498
|
+
if phone_number is not None:
|
|
3499
|
+
params["phoneNumber"] = phone_number
|
|
3500
|
+
if order is not None:
|
|
3501
|
+
params["order"] = order
|
|
3502
|
+
if limit > 0:
|
|
3503
|
+
params["max"] = limit
|
|
3504
|
+
if offset > 0:
|
|
3505
|
+
params["start"] = offset
|
|
3506
|
+
result = None
|
|
3507
|
+
try:
|
|
3508
|
+
result = api.session.rest_get(url, params=params)
|
|
3509
|
+
except WebexError as e:
|
|
3510
|
+
handle_rest_error(e)
|
|
3511
|
+
result = result or []
|
|
3512
|
+
items = result.get("members", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3513
|
+
if output == "json":
|
|
3514
|
+
print_json(items)
|
|
3515
|
+
else:
|
|
3516
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3517
|
+
|
|
3518
|
+
|
|
3519
|
+
|
|
3520
|
+
@app.command("list-organization")
|
|
3521
|
+
def list_organization(
|
|
3522
|
+
name: str = typer.Option(None, "--name", help="Search (Contains) based on location name. Multiple values ar"),
|
|
3523
|
+
order: str = typer.Option(None, "--order", help="Sort by location name (`name`). Sort directions asc or desc."),
|
|
3524
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
3525
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
3526
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
3527
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3528
|
+
):
|
|
3529
|
+
"""Get Location List for My Organization."""
|
|
3530
|
+
api = get_api(debug=debug)
|
|
3531
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/organization/locations"
|
|
3532
|
+
params = {}
|
|
3533
|
+
if name is not None:
|
|
3534
|
+
params["name"] = name
|
|
3535
|
+
if order is not None:
|
|
3536
|
+
params["order"] = order
|
|
3537
|
+
if limit > 0:
|
|
3538
|
+
params["max"] = limit
|
|
3539
|
+
if offset > 0:
|
|
3540
|
+
params["start"] = offset
|
|
3541
|
+
result = None
|
|
3542
|
+
try:
|
|
3543
|
+
result = api.session.rest_get(url, params=params)
|
|
3544
|
+
except WebexError as e:
|
|
3545
|
+
handle_rest_error(e)
|
|
3546
|
+
result = result or []
|
|
3547
|
+
items = result.get("locations", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
3548
|
+
if output == "json":
|
|
3549
|
+
print_json(items)
|
|
3550
|
+
else:
|
|
3551
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
3552
|
+
|
|
3553
|
+
|
|
3554
|
+
|
|
3555
|
+
@app.command("show-large-org-status")
|
|
3556
|
+
def show_large_org_status(
|
|
3557
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
3558
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
3559
|
+
):
|
|
3560
|
+
"""Get Large Organization Status."""
|
|
3561
|
+
api = get_api(debug=debug)
|
|
3562
|
+
url = f"https://webexapis.com/v1/telephony/config/people/me/organization/largeOrgStatus"
|
|
3563
|
+
try:
|
|
3564
|
+
result = api.session.rest_get(url)
|
|
3565
|
+
except WebexError as e:
|
|
3566
|
+
handle_rest_error(e)
|
|
3567
|
+
if output == "json":
|
|
3568
|
+
print_json(result)
|
|
3569
|
+
else:
|
|
3570
|
+
if isinstance(result, dict):
|
|
3571
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
3572
|
+
elif isinstance(result, list):
|
|
3573
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
3574
|
+
else:
|
|
3575
|
+
print_json(result)
|
|
3576
|
+
|
|
3577
|
+
|