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,519 @@
|
|
|
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 announcements.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
location_id: str = typer.Option(None, "--location-id", help="Choices: all, locations, Y2lzY29zcGFyazovL3VzL0xPQ0FUSU9OLzMxMTYx"),
|
|
15
|
+
order: str = typer.Option(None, "--order", help="Sort the list according to fileName or fileSize. The default"),
|
|
16
|
+
file_name: str = typer.Option(None, "--file-name", help="Return the list of announcements with the given fileName."),
|
|
17
|
+
file_type: str = typer.Option(None, "--file-type", help="Return the list of announcement files for this fileType."),
|
|
18
|
+
media_file_type: str = typer.Option(None, "--media-file-type", help="Return the list of announcement files for this mediaFileType"),
|
|
19
|
+
name: str = typer.Option(None, "--name", help="Return the list of announcement files for this announcement"),
|
|
20
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
21
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
22
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
23
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
24
|
+
):
|
|
25
|
+
"""Fetch list of announcement greetings on location and organization level."""
|
|
26
|
+
api = get_api(debug=debug)
|
|
27
|
+
url = f"https://webexapis.com/v1/telephony/config/announcements"
|
|
28
|
+
params = {}
|
|
29
|
+
if location_id is not None:
|
|
30
|
+
params["locationId"] = location_id
|
|
31
|
+
if order is not None:
|
|
32
|
+
params["order"] = order
|
|
33
|
+
if file_name is not None:
|
|
34
|
+
params["fileName"] = file_name
|
|
35
|
+
if file_type is not None:
|
|
36
|
+
params["fileType"] = file_type
|
|
37
|
+
if media_file_type is not None:
|
|
38
|
+
params["mediaFileType"] = media_file_type
|
|
39
|
+
if name is not None:
|
|
40
|
+
params["name"] = name
|
|
41
|
+
if limit > 0:
|
|
42
|
+
params["max"] = limit
|
|
43
|
+
if offset > 0:
|
|
44
|
+
params["start"] = offset
|
|
45
|
+
org_id = get_org_id()
|
|
46
|
+
if org_id is not None:
|
|
47
|
+
params["orgId"] = org_id
|
|
48
|
+
try:
|
|
49
|
+
if limit > 0:
|
|
50
|
+
result = api.session.rest_get(url, params=params)
|
|
51
|
+
result = result or {}
|
|
52
|
+
items = result.get("announcements", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
53
|
+
else:
|
|
54
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="announcements"))
|
|
55
|
+
except WebexError as e:
|
|
56
|
+
handle_rest_error(e)
|
|
57
|
+
if output == "json":
|
|
58
|
+
print_json(items)
|
|
59
|
+
else:
|
|
60
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@app.command("create")
|
|
65
|
+
def create(
|
|
66
|
+
name: str = typer.Option(None, "--name", help="(required) Name of the announcement."),
|
|
67
|
+
file_uri: str = typer.Option(None, "--file-uri", help="(required) URI of the announcement file."),
|
|
68
|
+
file_name: str = typer.Option(None, "--file-name", help="(required) File name of the announcement."),
|
|
69
|
+
is_text_to_speech: bool = typer.Option(None, "--is-text-to-speech/--no-is-text-to-speech", help="(required) Indicates whether the announcement is text-to-speech."),
|
|
70
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
71
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
72
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
73
|
+
):
|
|
74
|
+
"""Upload a binary announcement greeting at organization level."""
|
|
75
|
+
api = get_api(debug=debug)
|
|
76
|
+
url = f"https://webexapis.com/v1/telephony/config/announcements"
|
|
77
|
+
params = {}
|
|
78
|
+
org_id = get_org_id()
|
|
79
|
+
if org_id is not None:
|
|
80
|
+
params["orgId"] = org_id
|
|
81
|
+
if json_body:
|
|
82
|
+
body = json.loads(json_body)
|
|
83
|
+
else:
|
|
84
|
+
body = {}
|
|
85
|
+
if name is not None:
|
|
86
|
+
body["name"] = name
|
|
87
|
+
if file_uri is not None:
|
|
88
|
+
body["fileUri"] = file_uri
|
|
89
|
+
if file_name is not None:
|
|
90
|
+
body["fileName"] = file_name
|
|
91
|
+
if is_text_to_speech is not None:
|
|
92
|
+
body["isTextToSpeech"] = is_text_to_speech
|
|
93
|
+
_missing = [f for f in ['name', 'fileUri', 'fileName', 'isTextToSpeech'] if f not in body or body[f] is None]
|
|
94
|
+
if _missing:
|
|
95
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
96
|
+
raise typer.Exit(1)
|
|
97
|
+
try:
|
|
98
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
99
|
+
except WebexError as e:
|
|
100
|
+
handle_rest_error(e)
|
|
101
|
+
if output == "json":
|
|
102
|
+
print_json(result)
|
|
103
|
+
elif isinstance(result, dict) and "id" in result:
|
|
104
|
+
typer.echo(f"Created: {result['id']}")
|
|
105
|
+
elif not result or result == {}:
|
|
106
|
+
typer.echo("Created.")
|
|
107
|
+
else:
|
|
108
|
+
print_json(result)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@app.command("show")
|
|
113
|
+
def show(
|
|
114
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
115
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
116
|
+
):
|
|
117
|
+
"""Fetch repository usage for announcements for an organization."""
|
|
118
|
+
api = get_api(debug=debug)
|
|
119
|
+
url = f"https://webexapis.com/v1/telephony/config/announcements/usage"
|
|
120
|
+
params = {}
|
|
121
|
+
org_id = get_org_id()
|
|
122
|
+
if org_id is not None:
|
|
123
|
+
params["orgId"] = org_id
|
|
124
|
+
try:
|
|
125
|
+
result = api.session.rest_get(url, params=params)
|
|
126
|
+
except WebexError as e:
|
|
127
|
+
handle_rest_error(e)
|
|
128
|
+
if output == "json":
|
|
129
|
+
print_json(result)
|
|
130
|
+
else:
|
|
131
|
+
if isinstance(result, dict):
|
|
132
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
133
|
+
elif isinstance(result, list):
|
|
134
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
135
|
+
else:
|
|
136
|
+
print_json(result)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@app.command("show-announcements-config")
|
|
141
|
+
def show_announcements_config(
|
|
142
|
+
announcement_id: str = typer.Argument(help="announcementId"),
|
|
143
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
144
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
145
|
+
):
|
|
146
|
+
"""Fetch details of a binary announcement greeting at the organization level."""
|
|
147
|
+
api = get_api(debug=debug)
|
|
148
|
+
url = f"https://webexapis.com/v1/telephony/config/announcements/{announcement_id}"
|
|
149
|
+
params = {}
|
|
150
|
+
org_id = get_org_id()
|
|
151
|
+
if org_id is not None:
|
|
152
|
+
params["orgId"] = org_id
|
|
153
|
+
try:
|
|
154
|
+
result = api.session.rest_get(url, params=params)
|
|
155
|
+
except WebexError as e:
|
|
156
|
+
handle_rest_error(e)
|
|
157
|
+
if output == "json":
|
|
158
|
+
print_json(result)
|
|
159
|
+
else:
|
|
160
|
+
if isinstance(result, dict):
|
|
161
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
162
|
+
elif isinstance(result, list):
|
|
163
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
164
|
+
else:
|
|
165
|
+
print_json(result)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@app.command("update")
|
|
170
|
+
def update(
|
|
171
|
+
announcement_id: str = typer.Argument(help="announcementId"),
|
|
172
|
+
name: str = typer.Option(None, "--name", help="Name of the announcement."),
|
|
173
|
+
file_uri: str = typer.Option(None, "--file-uri", help="URI of the announcement file."),
|
|
174
|
+
file_name: str = typer.Option(None, "--file-name", help="File name of the announcement."),
|
|
175
|
+
is_text_to_speech: bool = typer.Option(None, "--is-text-to-speech/--no-is-text-to-speech", help="Indicates whether the announcement is text-to-speech."),
|
|
176
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
177
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
178
|
+
):
|
|
179
|
+
"""Modify a binary announcement greeting at organization level."""
|
|
180
|
+
api = get_api(debug=debug)
|
|
181
|
+
url = f"https://webexapis.com/v1/telephony/config/announcements/{announcement_id}"
|
|
182
|
+
params = {}
|
|
183
|
+
org_id = get_org_id()
|
|
184
|
+
if org_id is not None:
|
|
185
|
+
params["orgId"] = org_id
|
|
186
|
+
if json_body:
|
|
187
|
+
body = json.loads(json_body)
|
|
188
|
+
else:
|
|
189
|
+
body = {}
|
|
190
|
+
if name is not None:
|
|
191
|
+
body["name"] = name
|
|
192
|
+
if file_uri is not None:
|
|
193
|
+
body["fileUri"] = file_uri
|
|
194
|
+
if file_name is not None:
|
|
195
|
+
body["fileName"] = file_name
|
|
196
|
+
if is_text_to_speech is not None:
|
|
197
|
+
body["isTextToSpeech"] = is_text_to_speech
|
|
198
|
+
try:
|
|
199
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
200
|
+
except WebexError as e:
|
|
201
|
+
handle_rest_error(e)
|
|
202
|
+
typer.echo(f"Updated.")
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
@app.command("delete")
|
|
207
|
+
def delete(
|
|
208
|
+
announcement_id: str = typer.Argument(help="announcementId"),
|
|
209
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
210
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
211
|
+
):
|
|
212
|
+
"""Delete an announcement greeting of the organization."""
|
|
213
|
+
if not force:
|
|
214
|
+
typer.confirm(f"Delete {announcement_id}?", abort=True)
|
|
215
|
+
api = get_api(debug=debug)
|
|
216
|
+
url = f"https://webexapis.com/v1/telephony/config/announcements/{announcement_id}"
|
|
217
|
+
params = {}
|
|
218
|
+
org_id = get_org_id()
|
|
219
|
+
if org_id is not None:
|
|
220
|
+
params["orgId"] = org_id
|
|
221
|
+
try:
|
|
222
|
+
api.session.rest_delete(url, params=params)
|
|
223
|
+
except WebexError as e:
|
|
224
|
+
handle_rest_error(e)
|
|
225
|
+
typer.echo(f"Deleted: {announcement_id}")
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@app.command("create-announcements")
|
|
230
|
+
def create_announcements(
|
|
231
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
232
|
+
name: str = typer.Option(None, "--name", help="(required) Name of the announcement."),
|
|
233
|
+
file_uri: str = typer.Option(None, "--file-uri", help="(required) URI of the announcement file."),
|
|
234
|
+
file_name: str = typer.Option(None, "--file-name", help="(required) File name of the announcement."),
|
|
235
|
+
is_text_to_speech: bool = typer.Option(None, "--is-text-to-speech/--no-is-text-to-speech", help="(required) Indicates whether the announcement is text-to-speech."),
|
|
236
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
237
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
238
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
239
|
+
):
|
|
240
|
+
"""Upload a binary announcement greeting at the location level."""
|
|
241
|
+
api = get_api(debug=debug)
|
|
242
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/announcements"
|
|
243
|
+
params = {}
|
|
244
|
+
org_id = get_org_id()
|
|
245
|
+
if org_id is not None:
|
|
246
|
+
params["orgId"] = org_id
|
|
247
|
+
if json_body:
|
|
248
|
+
body = json.loads(json_body)
|
|
249
|
+
else:
|
|
250
|
+
body = {}
|
|
251
|
+
if name is not None:
|
|
252
|
+
body["name"] = name
|
|
253
|
+
if file_uri is not None:
|
|
254
|
+
body["fileUri"] = file_uri
|
|
255
|
+
if file_name is not None:
|
|
256
|
+
body["fileName"] = file_name
|
|
257
|
+
if is_text_to_speech is not None:
|
|
258
|
+
body["isTextToSpeech"] = is_text_to_speech
|
|
259
|
+
_missing = [f for f in ['name', 'fileUri', 'fileName', 'isTextToSpeech'] if f not in body or body[f] is None]
|
|
260
|
+
if _missing:
|
|
261
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
262
|
+
raise typer.Exit(1)
|
|
263
|
+
try:
|
|
264
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
265
|
+
except WebexError as e:
|
|
266
|
+
handle_rest_error(e)
|
|
267
|
+
if output == "json":
|
|
268
|
+
print_json(result)
|
|
269
|
+
elif isinstance(result, dict) and "id" in result:
|
|
270
|
+
typer.echo(f"Created: {result['id']}")
|
|
271
|
+
elif not result or result == {}:
|
|
272
|
+
typer.echo("Created.")
|
|
273
|
+
else:
|
|
274
|
+
print_json(result)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@app.command("show-usage-announcements")
|
|
279
|
+
def show_usage_announcements(
|
|
280
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
281
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
282
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
283
|
+
):
|
|
284
|
+
"""Fetch repository usage for announcements in a location."""
|
|
285
|
+
api = get_api(debug=debug)
|
|
286
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/announcements/usage"
|
|
287
|
+
params = {}
|
|
288
|
+
org_id = get_org_id()
|
|
289
|
+
if org_id is not None:
|
|
290
|
+
params["orgId"] = org_id
|
|
291
|
+
try:
|
|
292
|
+
result = api.session.rest_get(url, params=params)
|
|
293
|
+
except WebexError as e:
|
|
294
|
+
handle_rest_error(e)
|
|
295
|
+
if output == "json":
|
|
296
|
+
print_json(result)
|
|
297
|
+
else:
|
|
298
|
+
if isinstance(result, dict):
|
|
299
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
300
|
+
elif isinstance(result, list):
|
|
301
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
302
|
+
else:
|
|
303
|
+
print_json(result)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
@app.command("show-announcements-locations")
|
|
308
|
+
def show_announcements_locations(
|
|
309
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
310
|
+
announcement_id: str = typer.Argument(help="announcementId"),
|
|
311
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
312
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
313
|
+
):
|
|
314
|
+
"""Fetch details of a binary announcement greeting at location level."""
|
|
315
|
+
api = get_api(debug=debug)
|
|
316
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/announcements/{announcement_id}"
|
|
317
|
+
params = {}
|
|
318
|
+
org_id = get_org_id()
|
|
319
|
+
if org_id is not None:
|
|
320
|
+
params["orgId"] = org_id
|
|
321
|
+
try:
|
|
322
|
+
result = api.session.rest_get(url, params=params)
|
|
323
|
+
except WebexError as e:
|
|
324
|
+
handle_rest_error(e)
|
|
325
|
+
if output == "json":
|
|
326
|
+
print_json(result)
|
|
327
|
+
else:
|
|
328
|
+
if isinstance(result, dict):
|
|
329
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
330
|
+
elif isinstance(result, list):
|
|
331
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
332
|
+
else:
|
|
333
|
+
print_json(result)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
@app.command("update-announcements")
|
|
338
|
+
def update_announcements(
|
|
339
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
340
|
+
announcement_id: str = typer.Argument(help="announcementId"),
|
|
341
|
+
name: str = typer.Option(None, "--name", help="Name of the announcement."),
|
|
342
|
+
file_uri: str = typer.Option(None, "--file-uri", help="URI of the announcement file."),
|
|
343
|
+
file_name: str = typer.Option(None, "--file-name", help="File name of the announcement."),
|
|
344
|
+
is_text_to_speech: bool = typer.Option(None, "--is-text-to-speech/--no-is-text-to-speech", help="Indicates whether the announcement is text-to-speech."),
|
|
345
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
346
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
347
|
+
):
|
|
348
|
+
"""Modify a binary announcement greeting at location level."""
|
|
349
|
+
api = get_api(debug=debug)
|
|
350
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/announcements/{announcement_id}"
|
|
351
|
+
params = {}
|
|
352
|
+
org_id = get_org_id()
|
|
353
|
+
if org_id is not None:
|
|
354
|
+
params["orgId"] = org_id
|
|
355
|
+
if json_body:
|
|
356
|
+
body = json.loads(json_body)
|
|
357
|
+
else:
|
|
358
|
+
body = {}
|
|
359
|
+
if name is not None:
|
|
360
|
+
body["name"] = name
|
|
361
|
+
if file_uri is not None:
|
|
362
|
+
body["fileUri"] = file_uri
|
|
363
|
+
if file_name is not None:
|
|
364
|
+
body["fileName"] = file_name
|
|
365
|
+
if is_text_to_speech is not None:
|
|
366
|
+
body["isTextToSpeech"] = is_text_to_speech
|
|
367
|
+
try:
|
|
368
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
369
|
+
except WebexError as e:
|
|
370
|
+
handle_rest_error(e)
|
|
371
|
+
typer.echo(f"Updated.")
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
@app.command("delete-announcements")
|
|
376
|
+
def delete_announcements(
|
|
377
|
+
location_id: str = typer.Argument(help="locationId"),
|
|
378
|
+
announcement_id: str = typer.Argument(help="announcementId"),
|
|
379
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
380
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
381
|
+
):
|
|
382
|
+
"""Delete an announcement greeting in a location."""
|
|
383
|
+
if not force:
|
|
384
|
+
typer.confirm(f"Delete {announcement_id}?", abort=True)
|
|
385
|
+
api = get_api(debug=debug)
|
|
386
|
+
url = f"https://webexapis.com/v1/telephony/config/locations/{location_id}/announcements/{announcement_id}"
|
|
387
|
+
params = {}
|
|
388
|
+
org_id = get_org_id()
|
|
389
|
+
if org_id is not None:
|
|
390
|
+
params["orgId"] = org_id
|
|
391
|
+
try:
|
|
392
|
+
api.session.rest_delete(url, params=params)
|
|
393
|
+
except WebexError as e:
|
|
394
|
+
handle_rest_error(e)
|
|
395
|
+
typer.echo(f"Deleted: {announcement_id}")
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@app.command("tts-generate")
|
|
400
|
+
def tts_generate(
|
|
401
|
+
voice: str = typer.Option(None, "--voice", help="The voice ID used to generate the audio prompt. Use the List"),
|
|
402
|
+
text: str = typer.Option(None, "--text", help="The text to convert to speech."),
|
|
403
|
+
language_code: str = typer.Option(None, "--language-code", help="The language code used to generate the audio prompt. Use the"),
|
|
404
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
405
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
406
|
+
):
|
|
407
|
+
"""Generate a Text-to-Speech Prompt."""
|
|
408
|
+
api = get_api(debug=debug)
|
|
409
|
+
url = f"https://webexapis.com/v1/telephony/config/textToSpeech/actions/generate/invoke"
|
|
410
|
+
params = {}
|
|
411
|
+
org_id = get_org_id()
|
|
412
|
+
if org_id is not None:
|
|
413
|
+
params["orgId"] = org_id
|
|
414
|
+
if json_body:
|
|
415
|
+
body = json.loads(json_body)
|
|
416
|
+
else:
|
|
417
|
+
body = {}
|
|
418
|
+
if voice is not None:
|
|
419
|
+
body["voice"] = voice
|
|
420
|
+
if text is not None:
|
|
421
|
+
body["text"] = text
|
|
422
|
+
if language_code is not None:
|
|
423
|
+
body["languageCode"] = language_code
|
|
424
|
+
try:
|
|
425
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
426
|
+
except WebexError as e:
|
|
427
|
+
handle_rest_error(e)
|
|
428
|
+
print_json(result)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
@app.command("tts-usage")
|
|
433
|
+
def tts_usage(
|
|
434
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
435
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
436
|
+
):
|
|
437
|
+
"""Get Text-to-Speech Usage."""
|
|
438
|
+
api = get_api(debug=debug)
|
|
439
|
+
url = f"https://webexapis.com/v1/telephony/config/textToSpeech/usage"
|
|
440
|
+
params = {}
|
|
441
|
+
org_id = get_org_id()
|
|
442
|
+
if org_id is not None:
|
|
443
|
+
params["orgId"] = org_id
|
|
444
|
+
try:
|
|
445
|
+
result = api.session.rest_get(url, params=params)
|
|
446
|
+
except WebexError as e:
|
|
447
|
+
handle_rest_error(e)
|
|
448
|
+
if output == "json":
|
|
449
|
+
print_json(result)
|
|
450
|
+
else:
|
|
451
|
+
if isinstance(result, dict):
|
|
452
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
453
|
+
elif isinstance(result, list):
|
|
454
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
455
|
+
else:
|
|
456
|
+
print_json(result)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
@app.command("tts-status")
|
|
461
|
+
def tts_status(
|
|
462
|
+
tts_id: str = typer.Argument(help="ttsId"),
|
|
463
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
464
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
465
|
+
):
|
|
466
|
+
"""Get Text-to-Speech Generation Status."""
|
|
467
|
+
api = get_api(debug=debug)
|
|
468
|
+
url = f"https://webexapis.com/v1/telephony/config/textToSpeech/{tts_id}"
|
|
469
|
+
params = {}
|
|
470
|
+
org_id = get_org_id()
|
|
471
|
+
if org_id is not None:
|
|
472
|
+
params["orgId"] = org_id
|
|
473
|
+
try:
|
|
474
|
+
result = api.session.rest_get(url, params=params)
|
|
475
|
+
except WebexError as e:
|
|
476
|
+
handle_rest_error(e)
|
|
477
|
+
if output == "json":
|
|
478
|
+
print_json(result)
|
|
479
|
+
else:
|
|
480
|
+
if isinstance(result, dict):
|
|
481
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
482
|
+
elif isinstance(result, list):
|
|
483
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
484
|
+
else:
|
|
485
|
+
print_json(result)
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
@app.command("tts-voices")
|
|
490
|
+
def tts_voices(
|
|
491
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
492
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
493
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
494
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
495
|
+
):
|
|
496
|
+
"""List Text-to-Speech Voices."""
|
|
497
|
+
api = get_api(debug=debug)
|
|
498
|
+
url = f"https://webexapis.com/v1/telephony/config/textToSpeech/voices"
|
|
499
|
+
params = {}
|
|
500
|
+
if limit > 0:
|
|
501
|
+
params["max"] = limit
|
|
502
|
+
if offset > 0:
|
|
503
|
+
params["start"] = offset
|
|
504
|
+
org_id = get_org_id()
|
|
505
|
+
if org_id is not None:
|
|
506
|
+
params["orgId"] = org_id
|
|
507
|
+
result = None
|
|
508
|
+
try:
|
|
509
|
+
result = api.session.rest_get(url, params=params)
|
|
510
|
+
except WebexError as e:
|
|
511
|
+
handle_rest_error(e)
|
|
512
|
+
result = result or []
|
|
513
|
+
items = result.get("voices", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
514
|
+
if output == "json":
|
|
515
|
+
print_json(items)
|
|
516
|
+
else:
|
|
517
|
+
print_table(items, columns=[('ID', 'id'), ('Label', 'label')], limit=limit)
|
|
518
|
+
|
|
519
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
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 resolve_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling archive-users.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("show")
|
|
13
|
+
def show(
|
|
14
|
+
useruuid: str = typer.Argument(help="useruuid"),
|
|
15
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
16
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
17
|
+
):
|
|
18
|
+
"""Get Archive User."""
|
|
19
|
+
api = get_api(debug=debug)
|
|
20
|
+
org_id = resolve_org_id(api.session)
|
|
21
|
+
url = f"https://webexapis.com/identity/organizations/{org_id}/v1/ArchivedUser/{useruuid}"
|
|
22
|
+
try:
|
|
23
|
+
result = api.session.rest_get(url)
|
|
24
|
+
except WebexError as e:
|
|
25
|
+
handle_rest_error(e)
|
|
26
|
+
if output == "json":
|
|
27
|
+
print_json(result)
|
|
28
|
+
else:
|
|
29
|
+
if isinstance(result, dict):
|
|
30
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
31
|
+
elif isinstance(result, list):
|
|
32
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
33
|
+
else:
|
|
34
|
+
print_json(result)
|
|
35
|
+
|
|
36
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
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 attachment-actions.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("create-an-attachment")
|
|
12
|
+
def create_an_attachment(
|
|
13
|
+
type_param: str = typer.Option(None, "--type", help="Choices: submit"),
|
|
14
|
+
message_id: str = typer.Option(None, "--message-id", help="The ID of the message which contains the attachment."),
|
|
15
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body"),
|
|
16
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
17
|
+
):
|
|
18
|
+
"""Create an Attachment Action\n\nExample --json-body:\n '{"type":"submit","messageId":"...","inputs":{"Name":"...","Url":"...","Email":"...","Tel":"..."}}'."""
|
|
19
|
+
api = get_api(debug=debug)
|
|
20
|
+
url = f"https://webexapis.com/v1/attachment/actions"
|
|
21
|
+
if json_body:
|
|
22
|
+
body = json.loads(json_body)
|
|
23
|
+
else:
|
|
24
|
+
body = {}
|
|
25
|
+
if type_param is not None:
|
|
26
|
+
body["type"] = type_param
|
|
27
|
+
if message_id is not None:
|
|
28
|
+
body["messageId"] = message_id
|
|
29
|
+
try:
|
|
30
|
+
result = api.session.rest_post(url, json=body)
|
|
31
|
+
except WebexError as e:
|
|
32
|
+
handle_rest_error(e)
|
|
33
|
+
print_json(result)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@app.command("show")
|
|
38
|
+
def show(
|
|
39
|
+
id: str = typer.Argument(help="id"),
|
|
40
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
41
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
42
|
+
):
|
|
43
|
+
"""Get Attachment Action Details."""
|
|
44
|
+
api = get_api(debug=debug)
|
|
45
|
+
url = f"https://webexapis.com/v1/attachment/actions/{id}"
|
|
46
|
+
try:
|
|
47
|
+
result = api.session.rest_get(url)
|
|
48
|
+
except WebexError as e:
|
|
49
|
+
handle_rest_error(e)
|
|
50
|
+
if output == "json":
|
|
51
|
+
print_json(result)
|
|
52
|
+
else:
|
|
53
|
+
if isinstance(result, dict):
|
|
54
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
55
|
+
elif isinstance(result, list):
|
|
56
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
57
|
+
else:
|
|
58
|
+
print_json(result)
|
|
59
|
+
|
|
60
|
+
|