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,1304 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
from wxcli.config import get_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling call-controls.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("create")
|
|
13
|
+
def create(
|
|
14
|
+
destination: str = typer.Option(None, "--destination", help="(required) The destination to be dialed. The destination can be digits"),
|
|
15
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the call. The"),
|
|
16
|
+
single_number_reach_phone_number: str = typer.Option(None, "--single-number-reach-phone-number", help="The Single Number Reach phone number to use for the call. Mu"),
|
|
17
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
18
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
19
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
20
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
21
|
+
):
|
|
22
|
+
"""Dial."""
|
|
23
|
+
api = get_api(debug=debug)
|
|
24
|
+
url = f"https://webexapis.com/v1/telephony/calls/dial"
|
|
25
|
+
if json_body:
|
|
26
|
+
body = json.loads(json_body)
|
|
27
|
+
else:
|
|
28
|
+
body = {}
|
|
29
|
+
if destination is not None:
|
|
30
|
+
body["destination"] = destination
|
|
31
|
+
if endpoint_id is not None:
|
|
32
|
+
body["endpointId"] = endpoint_id
|
|
33
|
+
if single_number_reach_phone_number is not None:
|
|
34
|
+
body["singleNumberReachPhoneNumber"] = single_number_reach_phone_number
|
|
35
|
+
if line_owner_id is not None:
|
|
36
|
+
body["lineOwnerId"] = line_owner_id
|
|
37
|
+
_missing = [f for f in ['destination'] if f not in body or body[f] is None]
|
|
38
|
+
if _missing:
|
|
39
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
40
|
+
raise typer.Exit(1)
|
|
41
|
+
try:
|
|
42
|
+
result = api.session.rest_post(url, json=body)
|
|
43
|
+
except WebexError as e:
|
|
44
|
+
handle_rest_error(e)
|
|
45
|
+
if output == "json":
|
|
46
|
+
print_json(result)
|
|
47
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
48
|
+
typer.echo(f"Created: {result['callId']}")
|
|
49
|
+
elif isinstance(result, dict) and "id" in result:
|
|
50
|
+
typer.echo(f"Created: {result['id']}")
|
|
51
|
+
elif not result or result == {}:
|
|
52
|
+
typer.echo("Created.")
|
|
53
|
+
else:
|
|
54
|
+
print_json(result)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@app.command("create-answer-calls")
|
|
59
|
+
def create_answer_calls(
|
|
60
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to be answered."),
|
|
61
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to answer the call on. T"),
|
|
62
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
63
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
64
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
65
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
66
|
+
):
|
|
67
|
+
"""Answer."""
|
|
68
|
+
api = get_api(debug=debug)
|
|
69
|
+
url = f"https://webexapis.com/v1/telephony/calls/answer"
|
|
70
|
+
if json_body:
|
|
71
|
+
body = json.loads(json_body)
|
|
72
|
+
else:
|
|
73
|
+
body = {}
|
|
74
|
+
if call_id is not None:
|
|
75
|
+
body["callId"] = call_id
|
|
76
|
+
if endpoint_id is not None:
|
|
77
|
+
body["endpointId"] = endpoint_id
|
|
78
|
+
if line_owner_id is not None:
|
|
79
|
+
body["lineOwnerId"] = line_owner_id
|
|
80
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
81
|
+
if _missing:
|
|
82
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
83
|
+
raise typer.Exit(1)
|
|
84
|
+
try:
|
|
85
|
+
result = api.session.rest_post(url, json=body)
|
|
86
|
+
except WebexError as e:
|
|
87
|
+
handle_rest_error(e)
|
|
88
|
+
if output == "json":
|
|
89
|
+
print_json(result)
|
|
90
|
+
elif isinstance(result, dict) and "id" in result:
|
|
91
|
+
typer.echo(f"Created: {result['id']}")
|
|
92
|
+
elif not result or result == {}:
|
|
93
|
+
typer.echo("Created.")
|
|
94
|
+
else:
|
|
95
|
+
print_json(result)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@app.command("create-reject")
|
|
100
|
+
def create_reject(
|
|
101
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to be rejected."),
|
|
102
|
+
action: str = typer.Option(None, "--action", help="The rejection action to apply to the call. The busy action i"),
|
|
103
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
104
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
105
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
106
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
107
|
+
):
|
|
108
|
+
"""Reject."""
|
|
109
|
+
api = get_api(debug=debug)
|
|
110
|
+
url = f"https://webexapis.com/v1/telephony/calls/reject"
|
|
111
|
+
if json_body:
|
|
112
|
+
body = json.loads(json_body)
|
|
113
|
+
else:
|
|
114
|
+
body = {}
|
|
115
|
+
if call_id is not None:
|
|
116
|
+
body["callId"] = call_id
|
|
117
|
+
if action is not None:
|
|
118
|
+
body["action"] = action
|
|
119
|
+
if line_owner_id is not None:
|
|
120
|
+
body["lineOwnerId"] = line_owner_id
|
|
121
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
122
|
+
if _missing:
|
|
123
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
124
|
+
raise typer.Exit(1)
|
|
125
|
+
try:
|
|
126
|
+
result = api.session.rest_post(url, json=body)
|
|
127
|
+
except WebexError as e:
|
|
128
|
+
handle_rest_error(e)
|
|
129
|
+
if output == "json":
|
|
130
|
+
print_json(result)
|
|
131
|
+
elif isinstance(result, dict) and "id" in result:
|
|
132
|
+
typer.echo(f"Created: {result['id']}")
|
|
133
|
+
elif not result or result == {}:
|
|
134
|
+
typer.echo("Created.")
|
|
135
|
+
else:
|
|
136
|
+
print_json(result)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@app.command("create-hangup-calls")
|
|
141
|
+
def create_hangup_calls(
|
|
142
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to hangup."),
|
|
143
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
144
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
145
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
146
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
147
|
+
):
|
|
148
|
+
"""Hangup."""
|
|
149
|
+
api = get_api(debug=debug)
|
|
150
|
+
url = f"https://webexapis.com/v1/telephony/calls/hangup"
|
|
151
|
+
if json_body:
|
|
152
|
+
body = json.loads(json_body)
|
|
153
|
+
else:
|
|
154
|
+
body = {}
|
|
155
|
+
if call_id is not None:
|
|
156
|
+
body["callId"] = call_id
|
|
157
|
+
if line_owner_id is not None:
|
|
158
|
+
body["lineOwnerId"] = line_owner_id
|
|
159
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
160
|
+
if _missing:
|
|
161
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
162
|
+
raise typer.Exit(1)
|
|
163
|
+
try:
|
|
164
|
+
result = api.session.rest_post(url, json=body)
|
|
165
|
+
except WebexError as e:
|
|
166
|
+
handle_rest_error(e)
|
|
167
|
+
if output == "json":
|
|
168
|
+
print_json(result)
|
|
169
|
+
elif isinstance(result, dict) and "id" in result:
|
|
170
|
+
typer.echo(f"Created: {result['id']}")
|
|
171
|
+
elif not result or result == {}:
|
|
172
|
+
typer.echo("Created.")
|
|
173
|
+
else:
|
|
174
|
+
print_json(result)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@app.command("create-hold")
|
|
179
|
+
def create_hold(
|
|
180
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to hold."),
|
|
181
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
182
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
183
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
184
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
185
|
+
):
|
|
186
|
+
"""Hold."""
|
|
187
|
+
api = get_api(debug=debug)
|
|
188
|
+
url = f"https://webexapis.com/v1/telephony/calls/hold"
|
|
189
|
+
if json_body:
|
|
190
|
+
body = json.loads(json_body)
|
|
191
|
+
else:
|
|
192
|
+
body = {}
|
|
193
|
+
if call_id is not None:
|
|
194
|
+
body["callId"] = call_id
|
|
195
|
+
if line_owner_id is not None:
|
|
196
|
+
body["lineOwnerId"] = line_owner_id
|
|
197
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
198
|
+
if _missing:
|
|
199
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
200
|
+
raise typer.Exit(1)
|
|
201
|
+
try:
|
|
202
|
+
result = api.session.rest_post(url, json=body)
|
|
203
|
+
except WebexError as e:
|
|
204
|
+
handle_rest_error(e)
|
|
205
|
+
if output == "json":
|
|
206
|
+
print_json(result)
|
|
207
|
+
elif isinstance(result, dict) and "id" in result:
|
|
208
|
+
typer.echo(f"Created: {result['id']}")
|
|
209
|
+
elif not result or result == {}:
|
|
210
|
+
typer.echo("Created.")
|
|
211
|
+
else:
|
|
212
|
+
print_json(result)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@app.command("create-resume")
|
|
217
|
+
def create_resume(
|
|
218
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to resume."),
|
|
219
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
220
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
221
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
222
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
223
|
+
):
|
|
224
|
+
"""Resume."""
|
|
225
|
+
api = get_api(debug=debug)
|
|
226
|
+
url = f"https://webexapis.com/v1/telephony/calls/resume"
|
|
227
|
+
if json_body:
|
|
228
|
+
body = json.loads(json_body)
|
|
229
|
+
else:
|
|
230
|
+
body = {}
|
|
231
|
+
if call_id is not None:
|
|
232
|
+
body["callId"] = call_id
|
|
233
|
+
if line_owner_id is not None:
|
|
234
|
+
body["lineOwnerId"] = line_owner_id
|
|
235
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
236
|
+
if _missing:
|
|
237
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
238
|
+
raise typer.Exit(1)
|
|
239
|
+
try:
|
|
240
|
+
result = api.session.rest_post(url, json=body)
|
|
241
|
+
except WebexError as e:
|
|
242
|
+
handle_rest_error(e)
|
|
243
|
+
if output == "json":
|
|
244
|
+
print_json(result)
|
|
245
|
+
elif isinstance(result, dict) and "id" in result:
|
|
246
|
+
typer.echo(f"Created: {result['id']}")
|
|
247
|
+
elif not result or result == {}:
|
|
248
|
+
typer.echo("Created.")
|
|
249
|
+
else:
|
|
250
|
+
print_json(result)
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
@app.command("create-mute")
|
|
255
|
+
def create_mute(
|
|
256
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to mute."),
|
|
257
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
258
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
259
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
260
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
261
|
+
):
|
|
262
|
+
"""Mute."""
|
|
263
|
+
api = get_api(debug=debug)
|
|
264
|
+
url = f"https://webexapis.com/v1/telephony/calls/mute"
|
|
265
|
+
if json_body:
|
|
266
|
+
body = json.loads(json_body)
|
|
267
|
+
else:
|
|
268
|
+
body = {}
|
|
269
|
+
if call_id is not None:
|
|
270
|
+
body["callId"] = call_id
|
|
271
|
+
if line_owner_id is not None:
|
|
272
|
+
body["lineOwnerId"] = line_owner_id
|
|
273
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
274
|
+
if _missing:
|
|
275
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
276
|
+
raise typer.Exit(1)
|
|
277
|
+
try:
|
|
278
|
+
result = api.session.rest_post(url, json=body)
|
|
279
|
+
except WebexError as e:
|
|
280
|
+
handle_rest_error(e)
|
|
281
|
+
if output == "json":
|
|
282
|
+
print_json(result)
|
|
283
|
+
elif isinstance(result, dict) and "id" in result:
|
|
284
|
+
typer.echo(f"Created: {result['id']}")
|
|
285
|
+
elif not result or result == {}:
|
|
286
|
+
typer.echo("Created.")
|
|
287
|
+
else:
|
|
288
|
+
print_json(result)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@app.command("create-unmute")
|
|
293
|
+
def create_unmute(
|
|
294
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to unmute."),
|
|
295
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
296
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
297
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
298
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
299
|
+
):
|
|
300
|
+
"""Unmute."""
|
|
301
|
+
api = get_api(debug=debug)
|
|
302
|
+
url = f"https://webexapis.com/v1/telephony/calls/unmute"
|
|
303
|
+
if json_body:
|
|
304
|
+
body = json.loads(json_body)
|
|
305
|
+
else:
|
|
306
|
+
body = {}
|
|
307
|
+
if call_id is not None:
|
|
308
|
+
body["callId"] = call_id
|
|
309
|
+
if line_owner_id is not None:
|
|
310
|
+
body["lineOwnerId"] = line_owner_id
|
|
311
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
312
|
+
if _missing:
|
|
313
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
314
|
+
raise typer.Exit(1)
|
|
315
|
+
try:
|
|
316
|
+
result = api.session.rest_post(url, json=body)
|
|
317
|
+
except WebexError as e:
|
|
318
|
+
handle_rest_error(e)
|
|
319
|
+
if output == "json":
|
|
320
|
+
print_json(result)
|
|
321
|
+
elif isinstance(result, dict) and "id" in result:
|
|
322
|
+
typer.echo(f"Created: {result['id']}")
|
|
323
|
+
elif not result or result == {}:
|
|
324
|
+
typer.echo("Created.")
|
|
325
|
+
else:
|
|
326
|
+
print_json(result)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
@app.command("create-divert")
|
|
331
|
+
def create_divert(
|
|
332
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to divert."),
|
|
333
|
+
destination: str = typer.Option(None, "--destination", help="The destination to divert the call to. If toVoicemail is fal"),
|
|
334
|
+
to_voicemail: bool = typer.Option(None, "--to-voicemail/--no-to-voicemail", help="If set to true, the call is diverted to voicemail. If no des"),
|
|
335
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
336
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
337
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
338
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
339
|
+
):
|
|
340
|
+
"""Divert."""
|
|
341
|
+
api = get_api(debug=debug)
|
|
342
|
+
url = f"https://webexapis.com/v1/telephony/calls/divert"
|
|
343
|
+
if json_body:
|
|
344
|
+
body = json.loads(json_body)
|
|
345
|
+
else:
|
|
346
|
+
body = {}
|
|
347
|
+
if call_id is not None:
|
|
348
|
+
body["callId"] = call_id
|
|
349
|
+
if destination is not None:
|
|
350
|
+
body["destination"] = destination
|
|
351
|
+
if to_voicemail is not None:
|
|
352
|
+
body["toVoicemail"] = to_voicemail
|
|
353
|
+
if line_owner_id is not None:
|
|
354
|
+
body["lineOwnerId"] = line_owner_id
|
|
355
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
356
|
+
if _missing:
|
|
357
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
358
|
+
raise typer.Exit(1)
|
|
359
|
+
try:
|
|
360
|
+
result = api.session.rest_post(url, json=body)
|
|
361
|
+
except WebexError as e:
|
|
362
|
+
handle_rest_error(e)
|
|
363
|
+
if output == "json":
|
|
364
|
+
print_json(result)
|
|
365
|
+
elif isinstance(result, dict) and "id" in result:
|
|
366
|
+
typer.echo(f"Created: {result['id']}")
|
|
367
|
+
elif not result or result == {}:
|
|
368
|
+
typer.echo("Created.")
|
|
369
|
+
else:
|
|
370
|
+
print_json(result)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
@app.command("create-transfer")
|
|
375
|
+
def create_transfer(
|
|
376
|
+
call_id1: str = typer.Option(None, "--call-id1", help="The call identifier of the first call to transfer. This para"),
|
|
377
|
+
call_id2: str = typer.Option(None, "--call-id2", help="The call identifier of the second call to transfer. This par"),
|
|
378
|
+
destination: str = typer.Option(None, "--destination", help="The destination to be transferred to. The destination can be"),
|
|
379
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
380
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
381
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
382
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
383
|
+
):
|
|
384
|
+
"""Transfer."""
|
|
385
|
+
api = get_api(debug=debug)
|
|
386
|
+
url = f"https://webexapis.com/v1/telephony/calls/transfer"
|
|
387
|
+
if json_body:
|
|
388
|
+
body = json.loads(json_body)
|
|
389
|
+
else:
|
|
390
|
+
body = {}
|
|
391
|
+
if call_id1 is not None:
|
|
392
|
+
body["callId1"] = call_id1
|
|
393
|
+
if call_id2 is not None:
|
|
394
|
+
body["callId2"] = call_id2
|
|
395
|
+
if destination is not None:
|
|
396
|
+
body["destination"] = destination
|
|
397
|
+
if line_owner_id is not None:
|
|
398
|
+
body["lineOwnerId"] = line_owner_id
|
|
399
|
+
try:
|
|
400
|
+
result = api.session.rest_post(url, json=body)
|
|
401
|
+
except WebexError as e:
|
|
402
|
+
handle_rest_error(e)
|
|
403
|
+
if output == "json":
|
|
404
|
+
print_json(result)
|
|
405
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
406
|
+
typer.echo(f"Created: {result['callId']}")
|
|
407
|
+
elif isinstance(result, dict) and "id" in result:
|
|
408
|
+
typer.echo(f"Created: {result['id']}")
|
|
409
|
+
elif not result or result == {}:
|
|
410
|
+
typer.echo("Created.")
|
|
411
|
+
else:
|
|
412
|
+
print_json(result)
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
@app.command("create-park")
|
|
417
|
+
def create_park(
|
|
418
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to park."),
|
|
419
|
+
destination: str = typer.Option(None, "--destination", help="Identifes where the call is to be parked. If not provided, t"),
|
|
420
|
+
is_group_park: bool = typer.Option(None, "--is-group-park/--no-is-group-park", help="If set to`true`, the call is parked against an automatically"),
|
|
421
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
422
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
423
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
424
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
425
|
+
):
|
|
426
|
+
"""Park."""
|
|
427
|
+
api = get_api(debug=debug)
|
|
428
|
+
url = f"https://webexapis.com/v1/telephony/calls/park"
|
|
429
|
+
if json_body:
|
|
430
|
+
body = json.loads(json_body)
|
|
431
|
+
else:
|
|
432
|
+
body = {}
|
|
433
|
+
if call_id is not None:
|
|
434
|
+
body["callId"] = call_id
|
|
435
|
+
if destination is not None:
|
|
436
|
+
body["destination"] = destination
|
|
437
|
+
if is_group_park is not None:
|
|
438
|
+
body["isGroupPark"] = is_group_park
|
|
439
|
+
if line_owner_id is not None:
|
|
440
|
+
body["lineOwnerId"] = line_owner_id
|
|
441
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
442
|
+
if _missing:
|
|
443
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
444
|
+
raise typer.Exit(1)
|
|
445
|
+
try:
|
|
446
|
+
result = api.session.rest_post(url, json=body)
|
|
447
|
+
except WebexError as e:
|
|
448
|
+
handle_rest_error(e)
|
|
449
|
+
if output == "json":
|
|
450
|
+
print_json(result)
|
|
451
|
+
elif isinstance(result, dict) and "id" in result:
|
|
452
|
+
typer.echo(f"Created: {result['id']}")
|
|
453
|
+
elif not result or result == {}:
|
|
454
|
+
typer.echo("Created.")
|
|
455
|
+
else:
|
|
456
|
+
print_json(result)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
@app.command("create-retrieve")
|
|
461
|
+
def create_retrieve(
|
|
462
|
+
destination: str = typer.Option(None, "--destination", help="Identifies where the call is parked. The number field from t"),
|
|
463
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the retrieval"),
|
|
464
|
+
single_number_reach_phone_number: str = typer.Option(None, "--single-number-reach-phone-number", help="The Single Number Reach phone number to use for the retrieva"),
|
|
465
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
466
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
467
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
468
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
469
|
+
):
|
|
470
|
+
"""Retrieve."""
|
|
471
|
+
api = get_api(debug=debug)
|
|
472
|
+
url = f"https://webexapis.com/v1/telephony/calls/retrieve"
|
|
473
|
+
if json_body:
|
|
474
|
+
body = json.loads(json_body)
|
|
475
|
+
else:
|
|
476
|
+
body = {}
|
|
477
|
+
if destination is not None:
|
|
478
|
+
body["destination"] = destination
|
|
479
|
+
if endpoint_id is not None:
|
|
480
|
+
body["endpointId"] = endpoint_id
|
|
481
|
+
if single_number_reach_phone_number is not None:
|
|
482
|
+
body["singleNumberReachPhoneNumber"] = single_number_reach_phone_number
|
|
483
|
+
if line_owner_id is not None:
|
|
484
|
+
body["lineOwnerId"] = line_owner_id
|
|
485
|
+
try:
|
|
486
|
+
result = api.session.rest_post(url, json=body)
|
|
487
|
+
except WebexError as e:
|
|
488
|
+
handle_rest_error(e)
|
|
489
|
+
if output == "json":
|
|
490
|
+
print_json(result)
|
|
491
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
492
|
+
typer.echo(f"Created: {result['callId']}")
|
|
493
|
+
elif isinstance(result, dict) and "id" in result:
|
|
494
|
+
typer.echo(f"Created: {result['id']}")
|
|
495
|
+
elif not result or result == {}:
|
|
496
|
+
typer.echo("Created.")
|
|
497
|
+
else:
|
|
498
|
+
print_json(result)
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
@app.command("create-start-recording")
|
|
503
|
+
def create_start_recording(
|
|
504
|
+
call_id: str = typer.Option(None, "--call-id", help="The call identifier of the call to start recording."),
|
|
505
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
506
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
507
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
508
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
509
|
+
):
|
|
510
|
+
"""Start Recording."""
|
|
511
|
+
api = get_api(debug=debug)
|
|
512
|
+
url = f"https://webexapis.com/v1/telephony/calls/startRecording"
|
|
513
|
+
if json_body:
|
|
514
|
+
body = json.loads(json_body)
|
|
515
|
+
else:
|
|
516
|
+
body = {}
|
|
517
|
+
if call_id is not None:
|
|
518
|
+
body["callId"] = call_id
|
|
519
|
+
if line_owner_id is not None:
|
|
520
|
+
body["lineOwnerId"] = line_owner_id
|
|
521
|
+
try:
|
|
522
|
+
result = api.session.rest_post(url, json=body)
|
|
523
|
+
except WebexError as e:
|
|
524
|
+
handle_rest_error(e)
|
|
525
|
+
if output == "json":
|
|
526
|
+
print_json(result)
|
|
527
|
+
elif isinstance(result, dict) and "id" in result:
|
|
528
|
+
typer.echo(f"Created: {result['id']}")
|
|
529
|
+
elif not result or result == {}:
|
|
530
|
+
typer.echo("Created.")
|
|
531
|
+
else:
|
|
532
|
+
print_json(result)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
@app.command("create-stop-recording")
|
|
537
|
+
def create_stop_recording(
|
|
538
|
+
call_id: str = typer.Option(None, "--call-id", help="The call identifier of the call to stop recording."),
|
|
539
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
540
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
541
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
542
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
543
|
+
):
|
|
544
|
+
"""Stop Recording."""
|
|
545
|
+
api = get_api(debug=debug)
|
|
546
|
+
url = f"https://webexapis.com/v1/telephony/calls/stopRecording"
|
|
547
|
+
if json_body:
|
|
548
|
+
body = json.loads(json_body)
|
|
549
|
+
else:
|
|
550
|
+
body = {}
|
|
551
|
+
if call_id is not None:
|
|
552
|
+
body["callId"] = call_id
|
|
553
|
+
if line_owner_id is not None:
|
|
554
|
+
body["lineOwnerId"] = line_owner_id
|
|
555
|
+
try:
|
|
556
|
+
result = api.session.rest_post(url, json=body)
|
|
557
|
+
except WebexError as e:
|
|
558
|
+
handle_rest_error(e)
|
|
559
|
+
if output == "json":
|
|
560
|
+
print_json(result)
|
|
561
|
+
elif isinstance(result, dict) and "id" in result:
|
|
562
|
+
typer.echo(f"Created: {result['id']}")
|
|
563
|
+
elif not result or result == {}:
|
|
564
|
+
typer.echo("Created.")
|
|
565
|
+
else:
|
|
566
|
+
print_json(result)
|
|
567
|
+
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
@app.command("create-pause-recording")
|
|
571
|
+
def create_pause_recording(
|
|
572
|
+
call_id: str = typer.Option(None, "--call-id", help="The call identifier of the call to pause recording."),
|
|
573
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
574
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
575
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
576
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
577
|
+
):
|
|
578
|
+
"""Pause Recording."""
|
|
579
|
+
api = get_api(debug=debug)
|
|
580
|
+
url = f"https://webexapis.com/v1/telephony/calls/pauseRecording"
|
|
581
|
+
if json_body:
|
|
582
|
+
body = json.loads(json_body)
|
|
583
|
+
else:
|
|
584
|
+
body = {}
|
|
585
|
+
if call_id is not None:
|
|
586
|
+
body["callId"] = call_id
|
|
587
|
+
if line_owner_id is not None:
|
|
588
|
+
body["lineOwnerId"] = line_owner_id
|
|
589
|
+
try:
|
|
590
|
+
result = api.session.rest_post(url, json=body)
|
|
591
|
+
except WebexError as e:
|
|
592
|
+
handle_rest_error(e)
|
|
593
|
+
if output == "json":
|
|
594
|
+
print_json(result)
|
|
595
|
+
elif isinstance(result, dict) and "id" in result:
|
|
596
|
+
typer.echo(f"Created: {result['id']}")
|
|
597
|
+
elif not result or result == {}:
|
|
598
|
+
typer.echo("Created.")
|
|
599
|
+
else:
|
|
600
|
+
print_json(result)
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
@app.command("create-resume-recording")
|
|
605
|
+
def create_resume_recording(
|
|
606
|
+
call_id: str = typer.Option(None, "--call-id", help="The call identifier of the call to resume recording."),
|
|
607
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
608
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
609
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
610
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
611
|
+
):
|
|
612
|
+
"""Resume Recording."""
|
|
613
|
+
api = get_api(debug=debug)
|
|
614
|
+
url = f"https://webexapis.com/v1/telephony/calls/resumeRecording"
|
|
615
|
+
if json_body:
|
|
616
|
+
body = json.loads(json_body)
|
|
617
|
+
else:
|
|
618
|
+
body = {}
|
|
619
|
+
if call_id is not None:
|
|
620
|
+
body["callId"] = call_id
|
|
621
|
+
if line_owner_id is not None:
|
|
622
|
+
body["lineOwnerId"] = line_owner_id
|
|
623
|
+
try:
|
|
624
|
+
result = api.session.rest_post(url, json=body)
|
|
625
|
+
except WebexError as e:
|
|
626
|
+
handle_rest_error(e)
|
|
627
|
+
if output == "json":
|
|
628
|
+
print_json(result)
|
|
629
|
+
elif isinstance(result, dict) and "id" in result:
|
|
630
|
+
typer.echo(f"Created: {result['id']}")
|
|
631
|
+
elif not result or result == {}:
|
|
632
|
+
typer.echo("Created.")
|
|
633
|
+
else:
|
|
634
|
+
print_json(result)
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
@app.command("create-transmit-dtmf")
|
|
639
|
+
def create_transmit_dtmf(
|
|
640
|
+
call_id: str = typer.Option(None, "--call-id", help="The call identifier of the call to transmit DTMF digits for."),
|
|
641
|
+
dtmf: str = typer.Option(None, "--dtmf", help="The DTMF digits to transmit. Each digit must be part of the"),
|
|
642
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
643
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
644
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
645
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
646
|
+
):
|
|
647
|
+
"""Transmit DTMF."""
|
|
648
|
+
api = get_api(debug=debug)
|
|
649
|
+
url = f"https://webexapis.com/v1/telephony/calls/transmitDtmf"
|
|
650
|
+
if json_body:
|
|
651
|
+
body = json.loads(json_body)
|
|
652
|
+
else:
|
|
653
|
+
body = {}
|
|
654
|
+
if call_id is not None:
|
|
655
|
+
body["callId"] = call_id
|
|
656
|
+
if dtmf is not None:
|
|
657
|
+
body["dtmf"] = dtmf
|
|
658
|
+
if line_owner_id is not None:
|
|
659
|
+
body["lineOwnerId"] = line_owner_id
|
|
660
|
+
try:
|
|
661
|
+
result = api.session.rest_post(url, json=body)
|
|
662
|
+
except WebexError as e:
|
|
663
|
+
handle_rest_error(e)
|
|
664
|
+
if output == "json":
|
|
665
|
+
print_json(result)
|
|
666
|
+
elif isinstance(result, dict) and "id" in result:
|
|
667
|
+
typer.echo(f"Created: {result['id']}")
|
|
668
|
+
elif not result or result == {}:
|
|
669
|
+
typer.echo("Created.")
|
|
670
|
+
else:
|
|
671
|
+
print_json(result)
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
@app.command("create-push")
|
|
676
|
+
def create_push(
|
|
677
|
+
call_id: str = typer.Option(None, "--call-id", help="The call identifier of the call to push."),
|
|
678
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
679
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
680
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
681
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
682
|
+
):
|
|
683
|
+
"""Push."""
|
|
684
|
+
api = get_api(debug=debug)
|
|
685
|
+
url = f"https://webexapis.com/v1/telephony/calls/push"
|
|
686
|
+
if json_body:
|
|
687
|
+
body = json.loads(json_body)
|
|
688
|
+
else:
|
|
689
|
+
body = {}
|
|
690
|
+
if call_id is not None:
|
|
691
|
+
body["callId"] = call_id
|
|
692
|
+
if line_owner_id is not None:
|
|
693
|
+
body["lineOwnerId"] = line_owner_id
|
|
694
|
+
try:
|
|
695
|
+
result = api.session.rest_post(url, json=body)
|
|
696
|
+
except WebexError as e:
|
|
697
|
+
handle_rest_error(e)
|
|
698
|
+
if output == "json":
|
|
699
|
+
print_json(result)
|
|
700
|
+
elif isinstance(result, dict) and "id" in result:
|
|
701
|
+
typer.echo(f"Created: {result['id']}")
|
|
702
|
+
elif not result or result == {}:
|
|
703
|
+
typer.echo("Created.")
|
|
704
|
+
else:
|
|
705
|
+
print_json(result)
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
|
|
709
|
+
@app.command("create-pickup")
|
|
710
|
+
def create_pickup(
|
|
711
|
+
target: str = typer.Option(None, "--target", help="Identifies the user to pickup an incoming call from. If not"),
|
|
712
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the pickup. T"),
|
|
713
|
+
single_number_reach_phone_number: str = typer.Option(None, "--single-number-reach-phone-number", help="The Single Number Reach phone number to use for the pickup."),
|
|
714
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
715
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
716
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
717
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
718
|
+
):
|
|
719
|
+
"""Pickup."""
|
|
720
|
+
api = get_api(debug=debug)
|
|
721
|
+
url = f"https://webexapis.com/v1/telephony/calls/pickup"
|
|
722
|
+
if json_body:
|
|
723
|
+
body = json.loads(json_body)
|
|
724
|
+
else:
|
|
725
|
+
body = {}
|
|
726
|
+
if target is not None:
|
|
727
|
+
body["target"] = target
|
|
728
|
+
if endpoint_id is not None:
|
|
729
|
+
body["endpointId"] = endpoint_id
|
|
730
|
+
if single_number_reach_phone_number is not None:
|
|
731
|
+
body["singleNumberReachPhoneNumber"] = single_number_reach_phone_number
|
|
732
|
+
if line_owner_id is not None:
|
|
733
|
+
body["lineOwnerId"] = line_owner_id
|
|
734
|
+
try:
|
|
735
|
+
result = api.session.rest_post(url, json=body)
|
|
736
|
+
except WebexError as e:
|
|
737
|
+
handle_rest_error(e)
|
|
738
|
+
if output == "json":
|
|
739
|
+
print_json(result)
|
|
740
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
741
|
+
typer.echo(f"Created: {result['callId']}")
|
|
742
|
+
elif isinstance(result, dict) and "id" in result:
|
|
743
|
+
typer.echo(f"Created: {result['id']}")
|
|
744
|
+
elif not result or result == {}:
|
|
745
|
+
typer.echo("Created.")
|
|
746
|
+
else:
|
|
747
|
+
print_json(result)
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
@app.command("create-barge-in")
|
|
752
|
+
def create_barge_in(
|
|
753
|
+
target: str = typer.Option(None, "--target", help="(required) Identifies the user to barge-in on. The target can be digits"),
|
|
754
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the barge-in."),
|
|
755
|
+
single_number_reach_phone_number: str = typer.Option(None, "--single-number-reach-phone-number", help="The Single Number Reach phone number to use for the barge-in"),
|
|
756
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
757
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
758
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
759
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
760
|
+
):
|
|
761
|
+
"""Barge In."""
|
|
762
|
+
api = get_api(debug=debug)
|
|
763
|
+
url = f"https://webexapis.com/v1/telephony/calls/bargeIn"
|
|
764
|
+
if json_body:
|
|
765
|
+
body = json.loads(json_body)
|
|
766
|
+
else:
|
|
767
|
+
body = {}
|
|
768
|
+
if target is not None:
|
|
769
|
+
body["target"] = target
|
|
770
|
+
if endpoint_id is not None:
|
|
771
|
+
body["endpointId"] = endpoint_id
|
|
772
|
+
if single_number_reach_phone_number is not None:
|
|
773
|
+
body["singleNumberReachPhoneNumber"] = single_number_reach_phone_number
|
|
774
|
+
if line_owner_id is not None:
|
|
775
|
+
body["lineOwnerId"] = line_owner_id
|
|
776
|
+
_missing = [f for f in ['target'] if f not in body or body[f] is None]
|
|
777
|
+
if _missing:
|
|
778
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
779
|
+
raise typer.Exit(1)
|
|
780
|
+
try:
|
|
781
|
+
result = api.session.rest_post(url, json=body)
|
|
782
|
+
except WebexError as e:
|
|
783
|
+
handle_rest_error(e)
|
|
784
|
+
if output == "json":
|
|
785
|
+
print_json(result)
|
|
786
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
787
|
+
typer.echo(f"Created: {result['callId']}")
|
|
788
|
+
elif isinstance(result, dict) and "id" in result:
|
|
789
|
+
typer.echo(f"Created: {result['id']}")
|
|
790
|
+
elif not result or result == {}:
|
|
791
|
+
typer.echo("Created.")
|
|
792
|
+
else:
|
|
793
|
+
print_json(result)
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
@app.command("list")
|
|
798
|
+
def cmd_list(
|
|
799
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
800
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
801
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
802
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
803
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
804
|
+
):
|
|
805
|
+
"""List Calls."""
|
|
806
|
+
api = get_api(debug=debug)
|
|
807
|
+
url = f"https://webexapis.com/v1/telephony/calls"
|
|
808
|
+
params = {}
|
|
809
|
+
if line_owner_id is not None:
|
|
810
|
+
params["lineOwnerId"] = line_owner_id
|
|
811
|
+
if limit > 0:
|
|
812
|
+
params["max"] = limit
|
|
813
|
+
if offset > 0:
|
|
814
|
+
params["start"] = offset
|
|
815
|
+
result = None
|
|
816
|
+
try:
|
|
817
|
+
result = api.session.rest_get(url, params=params)
|
|
818
|
+
except WebexError as e:
|
|
819
|
+
handle_rest_error(e)
|
|
820
|
+
result = result or []
|
|
821
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
822
|
+
if output == "json":
|
|
823
|
+
print_json(items)
|
|
824
|
+
else:
|
|
825
|
+
print_table(items, columns=[('Call ID', 'id'), ('Personality', 'personality'), ('State', 'state'), ('Remote Party', 'remoteParty.name')], limit=limit)
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
@app.command("show")
|
|
830
|
+
def show(
|
|
831
|
+
call_id: str = typer.Argument(help="callId"),
|
|
832
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
833
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
834
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
835
|
+
):
|
|
836
|
+
"""Get Call Details."""
|
|
837
|
+
api = get_api(debug=debug)
|
|
838
|
+
url = f"https://webexapis.com/v1/telephony/calls/{call_id}"
|
|
839
|
+
params = {}
|
|
840
|
+
if line_owner_id is not None:
|
|
841
|
+
params["lineOwnerId"] = line_owner_id
|
|
842
|
+
try:
|
|
843
|
+
result = api.session.rest_get(url, params=params)
|
|
844
|
+
except WebexError as e:
|
|
845
|
+
handle_rest_error(e)
|
|
846
|
+
if output == "json":
|
|
847
|
+
print_json(result)
|
|
848
|
+
else:
|
|
849
|
+
if isinstance(result, dict):
|
|
850
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
851
|
+
elif isinstance(result, list):
|
|
852
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
853
|
+
else:
|
|
854
|
+
print_json(result)
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
@app.command("list-history")
|
|
859
|
+
def list_history(
|
|
860
|
+
type_param: str = typer.Option(None, "--type", help="Choices: placed, missed, received"),
|
|
861
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
862
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
863
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
864
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
865
|
+
):
|
|
866
|
+
"""List Call History."""
|
|
867
|
+
api = get_api(debug=debug)
|
|
868
|
+
url = f"https://webexapis.com/v1/telephony/calls/history"
|
|
869
|
+
params = {}
|
|
870
|
+
if type_param is not None:
|
|
871
|
+
params["type"] = type_param
|
|
872
|
+
if limit > 0:
|
|
873
|
+
params["max"] = limit
|
|
874
|
+
if offset > 0:
|
|
875
|
+
params["start"] = offset
|
|
876
|
+
result = None
|
|
877
|
+
try:
|
|
878
|
+
result = api.session.rest_get(url, params=params)
|
|
879
|
+
except WebexError as e:
|
|
880
|
+
handle_rest_error(e)
|
|
881
|
+
result = result or []
|
|
882
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
883
|
+
if output == "json":
|
|
884
|
+
print_json(items)
|
|
885
|
+
else:
|
|
886
|
+
print_table(items, columns=[('Type', 'type'), ('Name', 'name'), ('Number', 'number'), ('Time', 'time')], limit=limit)
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
@app.command("create-pull")
|
|
891
|
+
def create_pull(
|
|
892
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the retrieval"),
|
|
893
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
894
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
895
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
896
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
897
|
+
):
|
|
898
|
+
"""Pull."""
|
|
899
|
+
api = get_api(debug=debug)
|
|
900
|
+
url = f"https://webexapis.com/v1/telephony/calls/pull"
|
|
901
|
+
if json_body:
|
|
902
|
+
body = json.loads(json_body)
|
|
903
|
+
else:
|
|
904
|
+
body = {}
|
|
905
|
+
if endpoint_id is not None:
|
|
906
|
+
body["endpointId"] = endpoint_id
|
|
907
|
+
if line_owner_id is not None:
|
|
908
|
+
body["lineOwnerId"] = line_owner_id
|
|
909
|
+
try:
|
|
910
|
+
result = api.session.rest_post(url, json=body)
|
|
911
|
+
except WebexError as e:
|
|
912
|
+
handle_rest_error(e)
|
|
913
|
+
if output == "json":
|
|
914
|
+
print_json(result)
|
|
915
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
916
|
+
typer.echo(f"Created: {result['callId']}")
|
|
917
|
+
elif isinstance(result, dict) and "id" in result:
|
|
918
|
+
typer.echo(f"Created: {result['id']}")
|
|
919
|
+
elif not result or result == {}:
|
|
920
|
+
typer.echo("Created.")
|
|
921
|
+
else:
|
|
922
|
+
print_json(result)
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
@app.command("create-dial-members")
|
|
927
|
+
def create_dial_members(
|
|
928
|
+
member_id: str = typer.Argument(help="memberId"),
|
|
929
|
+
destination: str = typer.Option(None, "--destination", help="(required) The destination to be dialed. The destination can be digits"),
|
|
930
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the call. The"),
|
|
931
|
+
single_number_reach_phone_number: str = typer.Option(None, "--single-number-reach-phone-number", help="The Single Number Reach phone number to use for the call. Mu"),
|
|
932
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
933
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
934
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
935
|
+
):
|
|
936
|
+
"""Dial by Member ID."""
|
|
937
|
+
api = get_api(debug=debug)
|
|
938
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/{member_id}/dial"
|
|
939
|
+
params = {}
|
|
940
|
+
org_id = get_org_id()
|
|
941
|
+
if org_id is not None:
|
|
942
|
+
params["orgId"] = org_id
|
|
943
|
+
if json_body:
|
|
944
|
+
body = json.loads(json_body)
|
|
945
|
+
else:
|
|
946
|
+
body = {}
|
|
947
|
+
if destination is not None:
|
|
948
|
+
body["destination"] = destination
|
|
949
|
+
if endpoint_id is not None:
|
|
950
|
+
body["endpointId"] = endpoint_id
|
|
951
|
+
if single_number_reach_phone_number is not None:
|
|
952
|
+
body["singleNumberReachPhoneNumber"] = single_number_reach_phone_number
|
|
953
|
+
_missing = [f for f in ['destination'] if f not in body or body[f] is None]
|
|
954
|
+
if _missing:
|
|
955
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
956
|
+
raise typer.Exit(1)
|
|
957
|
+
try:
|
|
958
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
959
|
+
except WebexError as e:
|
|
960
|
+
handle_rest_error(e)
|
|
961
|
+
if output == "json":
|
|
962
|
+
print_json(result)
|
|
963
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
964
|
+
typer.echo(f"Created: {result['callId']}")
|
|
965
|
+
elif isinstance(result, dict) and "id" in result:
|
|
966
|
+
typer.echo(f"Created: {result['id']}")
|
|
967
|
+
elif not result or result == {}:
|
|
968
|
+
typer.echo("Created.")
|
|
969
|
+
else:
|
|
970
|
+
print_json(result)
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
@app.command("create-answer-members")
|
|
975
|
+
def create_answer_members(
|
|
976
|
+
member_id: str = typer.Argument(help="memberId"),
|
|
977
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to be answered."),
|
|
978
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to answer the call on. T"),
|
|
979
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
980
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
981
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
982
|
+
):
|
|
983
|
+
"""Answer by Member ID."""
|
|
984
|
+
api = get_api(debug=debug)
|
|
985
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/{member_id}/answer"
|
|
986
|
+
params = {}
|
|
987
|
+
org_id = get_org_id()
|
|
988
|
+
if org_id is not None:
|
|
989
|
+
params["orgId"] = org_id
|
|
990
|
+
if json_body:
|
|
991
|
+
body = json.loads(json_body)
|
|
992
|
+
else:
|
|
993
|
+
body = {}
|
|
994
|
+
if call_id is not None:
|
|
995
|
+
body["callId"] = call_id
|
|
996
|
+
if endpoint_id is not None:
|
|
997
|
+
body["endpointId"] = endpoint_id
|
|
998
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
999
|
+
if _missing:
|
|
1000
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1001
|
+
raise typer.Exit(1)
|
|
1002
|
+
try:
|
|
1003
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1004
|
+
except WebexError as e:
|
|
1005
|
+
handle_rest_error(e)
|
|
1006
|
+
if output == "json":
|
|
1007
|
+
print_json(result)
|
|
1008
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1009
|
+
typer.echo(f"Created: {result['id']}")
|
|
1010
|
+
elif not result or result == {}:
|
|
1011
|
+
typer.echo("Created.")
|
|
1012
|
+
else:
|
|
1013
|
+
print_json(result)
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
@app.command("create-hangup-members")
|
|
1018
|
+
def create_hangup_members(
|
|
1019
|
+
member_id: str = typer.Argument(help="memberId"),
|
|
1020
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to hangup."),
|
|
1021
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1022
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1023
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1024
|
+
):
|
|
1025
|
+
"""Hangup by Member ID."""
|
|
1026
|
+
api = get_api(debug=debug)
|
|
1027
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/{member_id}/hangup"
|
|
1028
|
+
params = {}
|
|
1029
|
+
org_id = get_org_id()
|
|
1030
|
+
if org_id is not None:
|
|
1031
|
+
params["orgId"] = org_id
|
|
1032
|
+
if json_body:
|
|
1033
|
+
body = json.loads(json_body)
|
|
1034
|
+
else:
|
|
1035
|
+
body = {}
|
|
1036
|
+
if call_id is not None:
|
|
1037
|
+
body["callId"] = call_id
|
|
1038
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
1039
|
+
if _missing:
|
|
1040
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1041
|
+
raise typer.Exit(1)
|
|
1042
|
+
try:
|
|
1043
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
1044
|
+
except WebexError as e:
|
|
1045
|
+
handle_rest_error(e)
|
|
1046
|
+
if output == "json":
|
|
1047
|
+
print_json(result)
|
|
1048
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1049
|
+
typer.echo(f"Created: {result['id']}")
|
|
1050
|
+
elif not result or result == {}:
|
|
1051
|
+
typer.echo("Created.")
|
|
1052
|
+
else:
|
|
1053
|
+
print_json(result)
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
@app.command("list-calls-members")
|
|
1058
|
+
def list_calls_members(
|
|
1059
|
+
member_id: str = typer.Argument(help="memberId"),
|
|
1060
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1061
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1062
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1063
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1064
|
+
):
|
|
1065
|
+
"""List Calls by Member ID."""
|
|
1066
|
+
api = get_api(debug=debug)
|
|
1067
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/{member_id}/calls"
|
|
1068
|
+
params = {}
|
|
1069
|
+
if limit > 0:
|
|
1070
|
+
params["max"] = limit
|
|
1071
|
+
if offset > 0:
|
|
1072
|
+
params["start"] = offset
|
|
1073
|
+
org_id = get_org_id()
|
|
1074
|
+
if org_id is not None:
|
|
1075
|
+
params["orgId"] = org_id
|
|
1076
|
+
result = None
|
|
1077
|
+
try:
|
|
1078
|
+
result = api.session.rest_get(url, params=params)
|
|
1079
|
+
except WebexError as e:
|
|
1080
|
+
handle_rest_error(e)
|
|
1081
|
+
result = result or []
|
|
1082
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1083
|
+
if output == "json":
|
|
1084
|
+
print_json(items)
|
|
1085
|
+
else:
|
|
1086
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
@app.command("show-calls-members")
|
|
1091
|
+
def show_calls_members(
|
|
1092
|
+
member_id: str = typer.Argument(help="memberId"),
|
|
1093
|
+
call_id: str = typer.Argument(help="callId"),
|
|
1094
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1095
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1096
|
+
):
|
|
1097
|
+
"""Get Call Details by Member ID."""
|
|
1098
|
+
api = get_api(debug=debug)
|
|
1099
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/{member_id}/calls/{call_id}"
|
|
1100
|
+
params = {}
|
|
1101
|
+
org_id = get_org_id()
|
|
1102
|
+
if org_id is not None:
|
|
1103
|
+
params["orgId"] = org_id
|
|
1104
|
+
try:
|
|
1105
|
+
result = api.session.rest_get(url, params=params)
|
|
1106
|
+
except WebexError as e:
|
|
1107
|
+
handle_rest_error(e)
|
|
1108
|
+
if output == "json":
|
|
1109
|
+
print_json(result)
|
|
1110
|
+
else:
|
|
1111
|
+
if isinstance(result, dict):
|
|
1112
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1113
|
+
elif isinstance(result, list):
|
|
1114
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1115
|
+
else:
|
|
1116
|
+
print_json(result)
|
|
1117
|
+
|
|
1118
|
+
|
|
1119
|
+
|
|
1120
|
+
@app.command("create-dial-me")
|
|
1121
|
+
def create_dial_me(
|
|
1122
|
+
destination: str = typer.Option(None, "--destination", help="(required) The destination to be dialed. The destination can be digits"),
|
|
1123
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to use for the call. The"),
|
|
1124
|
+
single_number_reach_phone_number: str = typer.Option(None, "--single-number-reach-phone-number", help="The Single Number Reach phone number to use for the call. Mu"),
|
|
1125
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
1126
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1127
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1128
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1129
|
+
):
|
|
1130
|
+
"""Dial."""
|
|
1131
|
+
api = get_api(debug=debug)
|
|
1132
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/me/dial"
|
|
1133
|
+
if json_body:
|
|
1134
|
+
body = json.loads(json_body)
|
|
1135
|
+
else:
|
|
1136
|
+
body = {}
|
|
1137
|
+
if destination is not None:
|
|
1138
|
+
body["destination"] = destination
|
|
1139
|
+
if endpoint_id is not None:
|
|
1140
|
+
body["endpointId"] = endpoint_id
|
|
1141
|
+
if single_number_reach_phone_number is not None:
|
|
1142
|
+
body["singleNumberReachPhoneNumber"] = single_number_reach_phone_number
|
|
1143
|
+
if line_owner_id is not None:
|
|
1144
|
+
body["lineOwnerId"] = line_owner_id
|
|
1145
|
+
_missing = [f for f in ['destination'] if f not in body or body[f] is None]
|
|
1146
|
+
if _missing:
|
|
1147
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1148
|
+
raise typer.Exit(1)
|
|
1149
|
+
try:
|
|
1150
|
+
result = api.session.rest_post(url, json=body)
|
|
1151
|
+
except WebexError as e:
|
|
1152
|
+
handle_rest_error(e)
|
|
1153
|
+
if output == "json":
|
|
1154
|
+
print_json(result)
|
|
1155
|
+
elif isinstance(result, dict) and "callId" in result:
|
|
1156
|
+
typer.echo(f"Created: {result['callId']}")
|
|
1157
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1158
|
+
typer.echo(f"Created: {result['id']}")
|
|
1159
|
+
elif not result or result == {}:
|
|
1160
|
+
typer.echo("Created.")
|
|
1161
|
+
else:
|
|
1162
|
+
print_json(result)
|
|
1163
|
+
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
@app.command("create-answer-me")
|
|
1167
|
+
def create_answer_me(
|
|
1168
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to be answered."),
|
|
1169
|
+
endpoint_id: str = typer.Option(None, "--endpoint-id", help="The ID of the device or application to answer the call on. T"),
|
|
1170
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
1171
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1172
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1173
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1174
|
+
):
|
|
1175
|
+
"""Answer."""
|
|
1176
|
+
api = get_api(debug=debug)
|
|
1177
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/me/answer"
|
|
1178
|
+
if json_body:
|
|
1179
|
+
body = json.loads(json_body)
|
|
1180
|
+
else:
|
|
1181
|
+
body = {}
|
|
1182
|
+
if call_id is not None:
|
|
1183
|
+
body["callId"] = call_id
|
|
1184
|
+
if endpoint_id is not None:
|
|
1185
|
+
body["endpointId"] = endpoint_id
|
|
1186
|
+
if line_owner_id is not None:
|
|
1187
|
+
body["lineOwnerId"] = line_owner_id
|
|
1188
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
1189
|
+
if _missing:
|
|
1190
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1191
|
+
raise typer.Exit(1)
|
|
1192
|
+
try:
|
|
1193
|
+
result = api.session.rest_post(url, json=body)
|
|
1194
|
+
except WebexError as e:
|
|
1195
|
+
handle_rest_error(e)
|
|
1196
|
+
if output == "json":
|
|
1197
|
+
print_json(result)
|
|
1198
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1199
|
+
typer.echo(f"Created: {result['id']}")
|
|
1200
|
+
elif not result or result == {}:
|
|
1201
|
+
typer.echo("Created.")
|
|
1202
|
+
else:
|
|
1203
|
+
print_json(result)
|
|
1204
|
+
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
@app.command("create-hangup-me")
|
|
1208
|
+
def create_hangup_me(
|
|
1209
|
+
call_id: str = typer.Option(None, "--call-id", help="(required) The call identifier of the call to hangup."),
|
|
1210
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
1211
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
1212
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
1213
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1214
|
+
):
|
|
1215
|
+
"""Hangup."""
|
|
1216
|
+
api = get_api(debug=debug)
|
|
1217
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/me/hangup"
|
|
1218
|
+
if json_body:
|
|
1219
|
+
body = json.loads(json_body)
|
|
1220
|
+
else:
|
|
1221
|
+
body = {}
|
|
1222
|
+
if call_id is not None:
|
|
1223
|
+
body["callId"] = call_id
|
|
1224
|
+
if line_owner_id is not None:
|
|
1225
|
+
body["lineOwnerId"] = line_owner_id
|
|
1226
|
+
_missing = [f for f in ['callId'] if f not in body or body[f] is None]
|
|
1227
|
+
if _missing:
|
|
1228
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
1229
|
+
raise typer.Exit(1)
|
|
1230
|
+
try:
|
|
1231
|
+
result = api.session.rest_post(url, json=body)
|
|
1232
|
+
except WebexError as e:
|
|
1233
|
+
handle_rest_error(e)
|
|
1234
|
+
if output == "json":
|
|
1235
|
+
print_json(result)
|
|
1236
|
+
elif isinstance(result, dict) and "id" in result:
|
|
1237
|
+
typer.echo(f"Created: {result['id']}")
|
|
1238
|
+
elif not result or result == {}:
|
|
1239
|
+
typer.echo("Created.")
|
|
1240
|
+
else:
|
|
1241
|
+
print_json(result)
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
@app.command("list-calls-me")
|
|
1246
|
+
def list_calls_me(
|
|
1247
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
1248
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
1249
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
1250
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
1251
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1252
|
+
):
|
|
1253
|
+
"""List Calls."""
|
|
1254
|
+
api = get_api(debug=debug)
|
|
1255
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/me/calls"
|
|
1256
|
+
params = {}
|
|
1257
|
+
if line_owner_id is not None:
|
|
1258
|
+
params["lineOwnerId"] = line_owner_id
|
|
1259
|
+
if limit > 0:
|
|
1260
|
+
params["max"] = limit
|
|
1261
|
+
if offset > 0:
|
|
1262
|
+
params["start"] = offset
|
|
1263
|
+
result = None
|
|
1264
|
+
try:
|
|
1265
|
+
result = api.session.rest_get(url, params=params)
|
|
1266
|
+
except WebexError as e:
|
|
1267
|
+
handle_rest_error(e)
|
|
1268
|
+
result = result or []
|
|
1269
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
1270
|
+
if output == "json":
|
|
1271
|
+
print_json(items)
|
|
1272
|
+
else:
|
|
1273
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
1274
|
+
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
@app.command("show-calls-me")
|
|
1278
|
+
def show_calls_me(
|
|
1279
|
+
call_id: str = typer.Argument(help="callId"),
|
|
1280
|
+
line_owner_id: str = typer.Option(None, "--line-owner-id", help="The ID of a user, workspace, or virtual line for which there"),
|
|
1281
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
1282
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
1283
|
+
):
|
|
1284
|
+
"""Get Call Details."""
|
|
1285
|
+
api = get_api(debug=debug)
|
|
1286
|
+
url = f"https://webexapis.com/v1/telephony/calls/members/me/calls/{call_id}"
|
|
1287
|
+
params = {}
|
|
1288
|
+
if line_owner_id is not None:
|
|
1289
|
+
params["lineOwnerId"] = line_owner_id
|
|
1290
|
+
try:
|
|
1291
|
+
result = api.session.rest_get(url, params=params)
|
|
1292
|
+
except WebexError as e:
|
|
1293
|
+
handle_rest_error(e)
|
|
1294
|
+
if output == "json":
|
|
1295
|
+
print_json(result)
|
|
1296
|
+
else:
|
|
1297
|
+
if isinstance(result, dict):
|
|
1298
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
1299
|
+
elif isinstance(result, list):
|
|
1300
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
1301
|
+
else:
|
|
1302
|
+
print_json(result)
|
|
1303
|
+
|
|
1304
|
+
|