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,585 @@
|
|
|
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 admin-recordings.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
from_param: str = typer.Option(None, "--from", help="Starting date and time (inclusive) for recordings to return,"),
|
|
14
|
+
to: str = typer.Option(None, "--to", help="Ending date and time (exclusive) for List recordings to retu"),
|
|
15
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier for the parent meeting series, scheduled m"),
|
|
16
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
17
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site from which the API lists recordings. I"),
|
|
18
|
+
integration_tag: str = typer.Option(None, "--integration-tag", help="External key of the parent meeting created by an integration"),
|
|
19
|
+
topic: str = typer.Option(None, "--topic", help="Recording's topic. If specified, the API filters recordings"),
|
|
20
|
+
format_param: str = typer.Option(None, "--format", help="Choices: MP4, ARF"),
|
|
21
|
+
service_type: str = typer.Option(None, "--service-type", help="Choices: MeetingCenter, EventCenter, SupportCenter, TrainingCenter"),
|
|
22
|
+
status: str = typer.Option(None, "--status", help="Choices: available, deleted, purged"),
|
|
23
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
24
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
25
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
26
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
27
|
+
):
|
|
28
|
+
"""List Recordings."""
|
|
29
|
+
api = get_api(debug=debug)
|
|
30
|
+
url = f"https://webexapis.com/v1/recordings"
|
|
31
|
+
params = {}
|
|
32
|
+
if from_param is not None:
|
|
33
|
+
params["from"] = from_param
|
|
34
|
+
if to is not None:
|
|
35
|
+
params["to"] = to
|
|
36
|
+
if meeting_id is not None:
|
|
37
|
+
params["meetingId"] = meeting_id
|
|
38
|
+
if host_email is not None:
|
|
39
|
+
params["hostEmail"] = host_email
|
|
40
|
+
if site_url is not None:
|
|
41
|
+
params["siteUrl"] = site_url
|
|
42
|
+
if integration_tag is not None:
|
|
43
|
+
params["integrationTag"] = integration_tag
|
|
44
|
+
if topic is not None:
|
|
45
|
+
params["topic"] = topic
|
|
46
|
+
if format_param is not None:
|
|
47
|
+
params["format"] = format_param
|
|
48
|
+
if service_type is not None:
|
|
49
|
+
params["serviceType"] = service_type
|
|
50
|
+
if status is not None:
|
|
51
|
+
params["status"] = status
|
|
52
|
+
if limit > 0:
|
|
53
|
+
params["max"] = limit
|
|
54
|
+
if offset > 0:
|
|
55
|
+
params["start"] = offset
|
|
56
|
+
try:
|
|
57
|
+
if limit > 0:
|
|
58
|
+
result = api.session.rest_get(url, params=params)
|
|
59
|
+
result = result or {}
|
|
60
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
61
|
+
else:
|
|
62
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
63
|
+
except WebexError as e:
|
|
64
|
+
handle_rest_error(e)
|
|
65
|
+
if output == "json":
|
|
66
|
+
print_json(items)
|
|
67
|
+
else:
|
|
68
|
+
print_table(items, columns=[('ID', 'id'), ('Topic', 'topic'), ('Format', 'format'), ('Created', 'timeRecorded')], limit=limit)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@app.command("create")
|
|
73
|
+
def create(
|
|
74
|
+
max: str = typer.Option(None, "--max", help="Maximum number of recordings to return in a single page. `ma"),
|
|
75
|
+
from_param: str = typer.Option(None, "--from", help="Starting date and time (inclusive) for recordings to return,"),
|
|
76
|
+
to: str = typer.Option(None, "--to", help="Ending date and time (exclusive) for query recordings to ret"),
|
|
77
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier for the parent meeting series, scheduled m"),
|
|
78
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site from which the API lists recordings. I"),
|
|
79
|
+
integration_tag: str = typer.Option(None, "--integration-tag", help="External key of the parent meeting created by an integration"),
|
|
80
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This property is only us"),
|
|
81
|
+
topic: str = typer.Option(None, "--topic", help="Recording's topic. If specified, the API filters recordings"),
|
|
82
|
+
format_param: str = typer.Option(None, "--format", help="Choices: MP4, ARF"),
|
|
83
|
+
service_type: str = typer.Option(None, "--service-type", help="Choices: MeetingCenter, EventCenter, SupportCenter, TrainingCenter"),
|
|
84
|
+
status: str = typer.Option(None, "--status", help="Choices: available, deleted, purged"),
|
|
85
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
86
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
87
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
88
|
+
):
|
|
89
|
+
"""Query Recordings."""
|
|
90
|
+
api = get_api(debug=debug)
|
|
91
|
+
url = f"https://webexapis.com/v1/recordings/query"
|
|
92
|
+
if json_body:
|
|
93
|
+
body = json.loads(json_body)
|
|
94
|
+
else:
|
|
95
|
+
body = {}
|
|
96
|
+
if max is not None:
|
|
97
|
+
body["max"] = max
|
|
98
|
+
if from_param is not None:
|
|
99
|
+
body["from"] = from_param
|
|
100
|
+
if to is not None:
|
|
101
|
+
body["to"] = to
|
|
102
|
+
if meeting_id is not None:
|
|
103
|
+
body["meetingId"] = meeting_id
|
|
104
|
+
if site_url is not None:
|
|
105
|
+
body["siteUrl"] = site_url
|
|
106
|
+
if integration_tag is not None:
|
|
107
|
+
body["integrationTag"] = integration_tag
|
|
108
|
+
if host_email is not None:
|
|
109
|
+
body["hostEmail"] = host_email
|
|
110
|
+
if topic is not None:
|
|
111
|
+
body["topic"] = topic
|
|
112
|
+
if format_param is not None:
|
|
113
|
+
body["format"] = format_param
|
|
114
|
+
if service_type is not None:
|
|
115
|
+
body["serviceType"] = service_type
|
|
116
|
+
if status is not None:
|
|
117
|
+
body["status"] = status
|
|
118
|
+
try:
|
|
119
|
+
result = api.session.rest_post(url, json=body)
|
|
120
|
+
except WebexError as e:
|
|
121
|
+
handle_rest_error(e)
|
|
122
|
+
if output == "json":
|
|
123
|
+
print_json(result)
|
|
124
|
+
elif isinstance(result, dict) and "id" in result:
|
|
125
|
+
typer.echo(f"Created: {result['id']}")
|
|
126
|
+
elif not result or result == {}:
|
|
127
|
+
typer.echo("Created.")
|
|
128
|
+
else:
|
|
129
|
+
print_json(result)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@app.command("list-recordings-admin")
|
|
134
|
+
def list_recordings_admin(
|
|
135
|
+
from_param: str = typer.Option(None, "--from", help="Starting date and time (inclusive) for recordings to return,"),
|
|
136
|
+
to: str = typer.Option(None, "--to", help="Ending date and time (exclusive) for List recordings to retu"),
|
|
137
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier for the parent meeting series, scheduled m"),
|
|
138
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site which the API lists recordings from. I"),
|
|
139
|
+
integration_tag: str = typer.Option(None, "--integration-tag", help="External key of the parent meeting created by an integration"),
|
|
140
|
+
topic: str = typer.Option(None, "--topic", help="Recording topic. If specified, the API filters recordings by"),
|
|
141
|
+
format_param: str = typer.Option(None, "--format", help="Choices: MP4, ARF"),
|
|
142
|
+
service_type: str = typer.Option(None, "--service-type", help="Choices: MeetingCenter, EventCenter, SupportCenter, TrainingCenter"),
|
|
143
|
+
status: str = typer.Option(None, "--status", help="Choices: available, deleted, purged"),
|
|
144
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
145
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
146
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
147
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
148
|
+
):
|
|
149
|
+
"""List Recordings For an Admin or Compliance Officer."""
|
|
150
|
+
api = get_api(debug=debug)
|
|
151
|
+
url = f"https://webexapis.com/v1/admin/recordings"
|
|
152
|
+
params = {}
|
|
153
|
+
if from_param is not None:
|
|
154
|
+
params["from"] = from_param
|
|
155
|
+
if to is not None:
|
|
156
|
+
params["to"] = to
|
|
157
|
+
if meeting_id is not None:
|
|
158
|
+
params["meetingId"] = meeting_id
|
|
159
|
+
if site_url is not None:
|
|
160
|
+
params["siteUrl"] = site_url
|
|
161
|
+
if integration_tag is not None:
|
|
162
|
+
params["integrationTag"] = integration_tag
|
|
163
|
+
if topic is not None:
|
|
164
|
+
params["topic"] = topic
|
|
165
|
+
if format_param is not None:
|
|
166
|
+
params["format"] = format_param
|
|
167
|
+
if service_type is not None:
|
|
168
|
+
params["serviceType"] = service_type
|
|
169
|
+
if status is not None:
|
|
170
|
+
params["status"] = status
|
|
171
|
+
if limit > 0:
|
|
172
|
+
params["max"] = limit
|
|
173
|
+
if offset > 0:
|
|
174
|
+
params["start"] = offset
|
|
175
|
+
try:
|
|
176
|
+
if limit > 0:
|
|
177
|
+
result = api.session.rest_get(url, params=params)
|
|
178
|
+
result = result or {}
|
|
179
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
180
|
+
else:
|
|
181
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
182
|
+
except WebexError as e:
|
|
183
|
+
handle_rest_error(e)
|
|
184
|
+
if output == "json":
|
|
185
|
+
print_json(items)
|
|
186
|
+
else:
|
|
187
|
+
print_table(items, columns=[('ID', 'id'), ('Topic', 'topic'), ('Format', 'format'), ('Created', 'timeRecorded')], limit=limit)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
@app.command("create-query")
|
|
192
|
+
def create_query(
|
|
193
|
+
max: str = typer.Option(None, "--max", help="Maximum number of recordings to return in a single page. `ma"),
|
|
194
|
+
from_param: str = typer.Option(None, "--from", help="Starting date and time (inclusive) for recordings to return,"),
|
|
195
|
+
to: str = typer.Option(None, "--to", help="Ending date and time (exclusive) for query recordings to ret"),
|
|
196
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier for the parent meeting series, scheduled m"),
|
|
197
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site which the API lists recordings from. I"),
|
|
198
|
+
integration_tag: str = typer.Option(None, "--integration-tag", help="External key of the parent meeting created by an integration"),
|
|
199
|
+
topic: str = typer.Option(None, "--topic", help="Recording topic. If specified, the API filters recordings by"),
|
|
200
|
+
format_param: str = typer.Option(None, "--format", help="Choices: MP4, ARF"),
|
|
201
|
+
service_type: str = typer.Option(None, "--service-type", help="Choices: MeetingCenter, EventCenter, SupportCenter, TrainingCenter"),
|
|
202
|
+
status: str = typer.Option(None, "--status", help="Choices: available, deleted, purged"),
|
|
203
|
+
timezone: str = typer.Option(None, "--timezone", help="Optional timezone override for the request (if not provided,"),
|
|
204
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
205
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
206
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
207
|
+
):
|
|
208
|
+
"""Query Recordings For an Admin or Compliance Officer."""
|
|
209
|
+
api = get_api(debug=debug)
|
|
210
|
+
url = f"https://webexapis.com/v1/admin/recordings/query"
|
|
211
|
+
if json_body:
|
|
212
|
+
body = json.loads(json_body)
|
|
213
|
+
else:
|
|
214
|
+
body = {}
|
|
215
|
+
if max is not None:
|
|
216
|
+
body["max"] = max
|
|
217
|
+
if from_param is not None:
|
|
218
|
+
body["from"] = from_param
|
|
219
|
+
if to is not None:
|
|
220
|
+
body["to"] = to
|
|
221
|
+
if meeting_id is not None:
|
|
222
|
+
body["meetingId"] = meeting_id
|
|
223
|
+
if site_url is not None:
|
|
224
|
+
body["siteUrl"] = site_url
|
|
225
|
+
if integration_tag is not None:
|
|
226
|
+
body["integrationTag"] = integration_tag
|
|
227
|
+
if topic is not None:
|
|
228
|
+
body["topic"] = topic
|
|
229
|
+
if format_param is not None:
|
|
230
|
+
body["format"] = format_param
|
|
231
|
+
if service_type is not None:
|
|
232
|
+
body["serviceType"] = service_type
|
|
233
|
+
if status is not None:
|
|
234
|
+
body["status"] = status
|
|
235
|
+
if timezone is not None:
|
|
236
|
+
body["timezone"] = timezone
|
|
237
|
+
try:
|
|
238
|
+
result = api.session.rest_post(url, json=body)
|
|
239
|
+
except WebexError as e:
|
|
240
|
+
handle_rest_error(e)
|
|
241
|
+
if output == "json":
|
|
242
|
+
print_json(result)
|
|
243
|
+
elif isinstance(result, dict) and "id" in result:
|
|
244
|
+
typer.echo(f"Created: {result['id']}")
|
|
245
|
+
elif not result or result == {}:
|
|
246
|
+
typer.echo("Created.")
|
|
247
|
+
else:
|
|
248
|
+
print_json(result)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@app.command("delete")
|
|
253
|
+
def delete(
|
|
254
|
+
recording_id: str = typer.Argument(help="recordingId"),
|
|
255
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
256
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
257
|
+
):
|
|
258
|
+
"""Delete a Recording By an Admin."""
|
|
259
|
+
if not force:
|
|
260
|
+
typer.confirm(f"Delete {recording_id}?", abort=True)
|
|
261
|
+
api = get_api(debug=debug)
|
|
262
|
+
url = f"https://webexapis.com/v1/admin/recordings/{recording_id}"
|
|
263
|
+
try:
|
|
264
|
+
api.session.rest_delete(url)
|
|
265
|
+
except WebexError as e:
|
|
266
|
+
handle_rest_error(e)
|
|
267
|
+
typer.echo(f"Deleted: {recording_id}")
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@app.command("show")
|
|
272
|
+
def show(
|
|
273
|
+
recording_id: str = typer.Argument(help="recordingId"),
|
|
274
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. Only used if the user or"),
|
|
275
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
276
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
277
|
+
):
|
|
278
|
+
"""Get Recording Details."""
|
|
279
|
+
api = get_api(debug=debug)
|
|
280
|
+
url = f"https://webexapis.com/v1/recordings/{recording_id}"
|
|
281
|
+
params = {}
|
|
282
|
+
if host_email is not None:
|
|
283
|
+
params["hostEmail"] = host_email
|
|
284
|
+
try:
|
|
285
|
+
result = api.session.rest_get(url, params=params)
|
|
286
|
+
except WebexError as e:
|
|
287
|
+
handle_rest_error(e)
|
|
288
|
+
if output == "json":
|
|
289
|
+
print_json(result)
|
|
290
|
+
else:
|
|
291
|
+
if isinstance(result, dict):
|
|
292
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
293
|
+
elif isinstance(result, list):
|
|
294
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
295
|
+
else:
|
|
296
|
+
print_json(result)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
@app.command("delete-recordings")
|
|
301
|
+
def delete_recordings(
|
|
302
|
+
recording_id: str = typer.Argument(help="recordingId"),
|
|
303
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. Only used if the user or"),
|
|
304
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
305
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
306
|
+
):
|
|
307
|
+
"""Delete a Recording."""
|
|
308
|
+
if not force:
|
|
309
|
+
typer.confirm(f"Delete {recording_id}?", abort=True)
|
|
310
|
+
api = get_api(debug=debug)
|
|
311
|
+
url = f"https://webexapis.com/v1/recordings/{recording_id}"
|
|
312
|
+
params = {}
|
|
313
|
+
if host_email is not None:
|
|
314
|
+
params["hostEmail"] = host_email
|
|
315
|
+
try:
|
|
316
|
+
api.session.rest_delete(url, params=params)
|
|
317
|
+
except WebexError as e:
|
|
318
|
+
handle_rest_error(e)
|
|
319
|
+
typer.echo(f"Deleted: {recording_id}")
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@app.command("create-soft-delete")
|
|
324
|
+
def create_soft_delete(
|
|
325
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. Only used if the user or"),
|
|
326
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site from which the API deletes recordings."),
|
|
327
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
328
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
329
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
330
|
+
):
|
|
331
|
+
"""Move Recordings into the Recycle Bin\n\nExample --json-body:\n '{"recordingIds":["..."],"siteUrl":"..."}'."""
|
|
332
|
+
api = get_api(debug=debug)
|
|
333
|
+
url = f"https://webexapis.com/v1/recordings/softDelete"
|
|
334
|
+
params = {}
|
|
335
|
+
if host_email is not None:
|
|
336
|
+
params["hostEmail"] = host_email
|
|
337
|
+
if json_body:
|
|
338
|
+
body = json.loads(json_body)
|
|
339
|
+
else:
|
|
340
|
+
body = {}
|
|
341
|
+
if site_url is not None:
|
|
342
|
+
body["siteUrl"] = site_url
|
|
343
|
+
try:
|
|
344
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
345
|
+
except WebexError as e:
|
|
346
|
+
handle_rest_error(e)
|
|
347
|
+
if output == "json":
|
|
348
|
+
print_json(result)
|
|
349
|
+
elif isinstance(result, dict) and "id" in result:
|
|
350
|
+
typer.echo(f"Created: {result['id']}")
|
|
351
|
+
elif not result or result == {}:
|
|
352
|
+
typer.echo("Created.")
|
|
353
|
+
else:
|
|
354
|
+
print_json(result)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
@app.command("create-restore")
|
|
359
|
+
def create_restore(
|
|
360
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
361
|
+
restore_all: bool = typer.Option(None, "--restore-all/--no-restore-all", help="If not specified or `false`, restores the recordings specifi"),
|
|
362
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site from which the API restores recordings"),
|
|
363
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
364
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
365
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
366
|
+
):
|
|
367
|
+
"""Restore Recordings from Recycle Bin\n\nExample --json-body:\n '{"restoreAll":true,"recordingIds":["..."],"siteUrl":"..."}'."""
|
|
368
|
+
api = get_api(debug=debug)
|
|
369
|
+
url = f"https://webexapis.com/v1/recordings/restore"
|
|
370
|
+
params = {}
|
|
371
|
+
if host_email is not None:
|
|
372
|
+
params["hostEmail"] = host_email
|
|
373
|
+
if json_body:
|
|
374
|
+
body = json.loads(json_body)
|
|
375
|
+
else:
|
|
376
|
+
body = {}
|
|
377
|
+
if restore_all is not None:
|
|
378
|
+
body["restoreAll"] = restore_all
|
|
379
|
+
if site_url is not None:
|
|
380
|
+
body["siteUrl"] = site_url
|
|
381
|
+
try:
|
|
382
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
383
|
+
except WebexError as e:
|
|
384
|
+
handle_rest_error(e)
|
|
385
|
+
if output == "json":
|
|
386
|
+
print_json(result)
|
|
387
|
+
elif isinstance(result, dict) and "id" in result:
|
|
388
|
+
typer.echo(f"Created: {result['id']}")
|
|
389
|
+
elif not result or result == {}:
|
|
390
|
+
typer.echo("Created.")
|
|
391
|
+
else:
|
|
392
|
+
print_json(result)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
@app.command("create-purge")
|
|
397
|
+
def create_purge(
|
|
398
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. Only used if the user or"),
|
|
399
|
+
purge_all: bool = typer.Option(None, "--purge-all/--no-purge-all", help="If not specified or `false`, purges the recordings specified"),
|
|
400
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site from which the API purges recordings."),
|
|
401
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
402
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
403
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
404
|
+
):
|
|
405
|
+
"""Purge Recordings from Recycle Bin\n\nExample --json-body:\n '{"purgeAll":true,"recordingIds":["..."],"siteUrl":"..."}'."""
|
|
406
|
+
api = get_api(debug=debug)
|
|
407
|
+
url = f"https://webexapis.com/v1/recordings/purge"
|
|
408
|
+
params = {}
|
|
409
|
+
if host_email is not None:
|
|
410
|
+
params["hostEmail"] = host_email
|
|
411
|
+
if json_body:
|
|
412
|
+
body = json.loads(json_body)
|
|
413
|
+
else:
|
|
414
|
+
body = {}
|
|
415
|
+
if purge_all is not None:
|
|
416
|
+
body["purgeAll"] = purge_all
|
|
417
|
+
if site_url is not None:
|
|
418
|
+
body["siteUrl"] = site_url
|
|
419
|
+
try:
|
|
420
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
421
|
+
except WebexError as e:
|
|
422
|
+
handle_rest_error(e)
|
|
423
|
+
if output == "json":
|
|
424
|
+
print_json(result)
|
|
425
|
+
elif isinstance(result, dict) and "id" in result:
|
|
426
|
+
typer.echo(f"Created: {result['id']}")
|
|
427
|
+
elif not result or result == {}:
|
|
428
|
+
typer.echo("Created.")
|
|
429
|
+
else:
|
|
430
|
+
print_json(result)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
@app.command("create-access-list-recordings")
|
|
435
|
+
def create_access_list_recordings(
|
|
436
|
+
recording_id: str = typer.Argument(help="recordingId"),
|
|
437
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This attribute should on"),
|
|
438
|
+
send_email: bool = typer.Option(None, "--send-email/--no-send-email", help="Whether to send email notifications to the users being share"),
|
|
439
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
440
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
441
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
442
|
+
):
|
|
443
|
+
"""Share a Recording\n\nExample --json-body:\n '{"hostEmail":"...","addEmails":["..."],"removeEmails":["..."],"sendEmail":true}'."""
|
|
444
|
+
api = get_api(debug=debug)
|
|
445
|
+
url = f"https://webexapis.com/v1/recordings/{recording_id}/accessList"
|
|
446
|
+
if json_body:
|
|
447
|
+
body = json.loads(json_body)
|
|
448
|
+
else:
|
|
449
|
+
body = {}
|
|
450
|
+
if host_email is not None:
|
|
451
|
+
body["hostEmail"] = host_email
|
|
452
|
+
if send_email is not None:
|
|
453
|
+
body["sendEmail"] = send_email
|
|
454
|
+
try:
|
|
455
|
+
result = api.session.rest_post(url, json=body)
|
|
456
|
+
except WebexError as e:
|
|
457
|
+
handle_rest_error(e)
|
|
458
|
+
if output == "json":
|
|
459
|
+
print_json(result)
|
|
460
|
+
elif isinstance(result, dict) and "id" in result:
|
|
461
|
+
typer.echo(f"Created: {result['id']}")
|
|
462
|
+
elif not result or result == {}:
|
|
463
|
+
typer.echo("Created.")
|
|
464
|
+
else:
|
|
465
|
+
print_json(result)
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
@app.command("create-access-list-recordings-1")
|
|
470
|
+
def create_access_list_recordings_1(
|
|
471
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This attribute should on"),
|
|
472
|
+
web_share_link: str = typer.Option(None, "--web-share-link", help="The link for the recording to be shared or unshared."),
|
|
473
|
+
send_email: bool = typer.Option(None, "--send-email/--no-send-email", help="Whether to send email notifications to the users being share"),
|
|
474
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
475
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
476
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
477
|
+
):
|
|
478
|
+
"""Share a Recording Link\n\nExample --json-body:\n '{"hostEmail":"...","webShareLink":"...","addEmails":["..."],"removeEmails":["..."],"sendEmail":true}'."""
|
|
479
|
+
api = get_api(debug=debug)
|
|
480
|
+
url = f"https://webexapis.com/v1/recordings/accessList"
|
|
481
|
+
if json_body:
|
|
482
|
+
body = json.loads(json_body)
|
|
483
|
+
else:
|
|
484
|
+
body = {}
|
|
485
|
+
if host_email is not None:
|
|
486
|
+
body["hostEmail"] = host_email
|
|
487
|
+
if web_share_link is not None:
|
|
488
|
+
body["webShareLink"] = web_share_link
|
|
489
|
+
if send_email is not None:
|
|
490
|
+
body["sendEmail"] = send_email
|
|
491
|
+
try:
|
|
492
|
+
result = api.session.rest_post(url, json=body)
|
|
493
|
+
except WebexError as e:
|
|
494
|
+
handle_rest_error(e)
|
|
495
|
+
if output == "json":
|
|
496
|
+
print_json(result)
|
|
497
|
+
elif isinstance(result, dict) and "id" in result:
|
|
498
|
+
typer.echo(f"Created: {result['id']}")
|
|
499
|
+
elif not result or result == {}:
|
|
500
|
+
typer.echo("Created.")
|
|
501
|
+
else:
|
|
502
|
+
print_json(result)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
@app.command("list-recordings-group")
|
|
507
|
+
def list_recordings_group(
|
|
508
|
+
person_id: str = typer.Option(None, "--person-id", help="Person ID of the user whose recordings will be retrieved. Th"),
|
|
509
|
+
from_param: str = typer.Option(None, "--from", help="Starting date and time (inclusive) for recordings to return,"),
|
|
510
|
+
to: str = typer.Option(None, "--to", help="Ending date and time (exclusive) for List recordings to retu"),
|
|
511
|
+
site_url: str = typer.Option(None, "--site-url", help="URL of the Webex site which the API lists recordings from. I"),
|
|
512
|
+
integration_tag: str = typer.Option(None, "--integration-tag", help="External key of the parent meeting created by an integration"),
|
|
513
|
+
format_param: str = typer.Option(None, "--format", help="Choices: MP4, ARF"),
|
|
514
|
+
service_type: str = typer.Option(None, "--service-type", help="Choices: MeetingCenter, EventCenter, SupportCenter, TrainingCenter"),
|
|
515
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
516
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
517
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
518
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
519
|
+
):
|
|
520
|
+
"""List Group Recordings."""
|
|
521
|
+
api = get_api(debug=debug)
|
|
522
|
+
url = f"https://webexapis.com/v1/group/recordings"
|
|
523
|
+
params = {}
|
|
524
|
+
if person_id is not None:
|
|
525
|
+
params["personId"] = person_id
|
|
526
|
+
if from_param is not None:
|
|
527
|
+
params["from"] = from_param
|
|
528
|
+
if to is not None:
|
|
529
|
+
params["to"] = to
|
|
530
|
+
if site_url is not None:
|
|
531
|
+
params["siteUrl"] = site_url
|
|
532
|
+
if integration_tag is not None:
|
|
533
|
+
params["integrationTag"] = integration_tag
|
|
534
|
+
if format_param is not None:
|
|
535
|
+
params["format"] = format_param
|
|
536
|
+
if service_type is not None:
|
|
537
|
+
params["serviceType"] = service_type
|
|
538
|
+
if limit > 0:
|
|
539
|
+
params["max"] = limit
|
|
540
|
+
if offset > 0:
|
|
541
|
+
params["start"] = offset
|
|
542
|
+
try:
|
|
543
|
+
if limit > 0:
|
|
544
|
+
result = api.session.rest_get(url, params=params)
|
|
545
|
+
result = result or {}
|
|
546
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
547
|
+
else:
|
|
548
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
549
|
+
except WebexError as e:
|
|
550
|
+
handle_rest_error(e)
|
|
551
|
+
if output == "json":
|
|
552
|
+
print_json(items)
|
|
553
|
+
else:
|
|
554
|
+
print_table(items, columns=[('ID', 'id'), ('Topic', 'topic'), ('Format', 'format'), ('Created', 'timeRecorded')], limit=limit)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
@app.command("show-recordings")
|
|
559
|
+
def show_recordings(
|
|
560
|
+
recording_id: str = typer.Argument(help="recordingId"),
|
|
561
|
+
person_id: str = typer.Option(None, "--person-id", help="Person ID of the user whose recordings will be retrieved. Th"),
|
|
562
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
563
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
564
|
+
):
|
|
565
|
+
"""Get Group Recording Details."""
|
|
566
|
+
api = get_api(debug=debug)
|
|
567
|
+
url = f"https://webexapis.com/v1/group/recordings/{recording_id}"
|
|
568
|
+
params = {}
|
|
569
|
+
if person_id is not None:
|
|
570
|
+
params["personId"] = person_id
|
|
571
|
+
try:
|
|
572
|
+
result = api.session.rest_get(url, params=params)
|
|
573
|
+
except WebexError as e:
|
|
574
|
+
handle_rest_error(e)
|
|
575
|
+
if output == "json":
|
|
576
|
+
print_json(result)
|
|
577
|
+
else:
|
|
578
|
+
if isinstance(result, dict):
|
|
579
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
580
|
+
elif isinstance(result, list):
|
|
581
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
582
|
+
else:
|
|
583
|
+
print_json(result)
|
|
584
|
+
|
|
585
|
+
|