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,234 @@
|
|
|
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 Meetings meeting-invitees.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
meeting_id: str = typer.Option(..., "--meeting-id", help="Unique identifier for the meeting for which invitees are bei"),
|
|
14
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
15
|
+
panelist: str = typer.Option(None, "--panelist", help="Filter invitees or attendees for webinars only. If `true`, r"),
|
|
16
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
17
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
18
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
19
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
20
|
+
):
|
|
21
|
+
"""List Meeting Invitees."""
|
|
22
|
+
api = get_api(debug=debug)
|
|
23
|
+
url = f"https://webexapis.com/v1/meetingInvitees"
|
|
24
|
+
params = {}
|
|
25
|
+
if meeting_id is not None:
|
|
26
|
+
params["meetingId"] = meeting_id
|
|
27
|
+
if host_email is not None:
|
|
28
|
+
params["hostEmail"] = host_email
|
|
29
|
+
if panelist is not None:
|
|
30
|
+
params["panelist"] = panelist
|
|
31
|
+
if limit > 0:
|
|
32
|
+
params["max"] = limit
|
|
33
|
+
if offset > 0:
|
|
34
|
+
params["start"] = offset
|
|
35
|
+
try:
|
|
36
|
+
if limit > 0:
|
|
37
|
+
result = api.session.rest_get(url, params=params)
|
|
38
|
+
result = result or {}
|
|
39
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
40
|
+
else:
|
|
41
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
42
|
+
except WebexError as e:
|
|
43
|
+
handle_rest_error(e)
|
|
44
|
+
if output == "json":
|
|
45
|
+
print_json(items)
|
|
46
|
+
else:
|
|
47
|
+
print_table(items, columns=[('ID', 'id'), ('Display Name', 'displayName'), ('Email', 'email')], limit=limit)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@app.command("create")
|
|
52
|
+
def create(
|
|
53
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="(required) Unique identifier for the meeting to which a person is being"),
|
|
54
|
+
email: str = typer.Option(None, "--email", help="(required) Email address for meeting invitee."),
|
|
55
|
+
display_name: str = typer.Option(None, "--display-name", help="Display name for meeting invitee. The maximum length of `dis"),
|
|
56
|
+
co_host: bool = typer.Option(None, "--co-host/--no-co-host", help="Whether or not the invitee is a designated alternate host fo"),
|
|
57
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This attribute should on"),
|
|
58
|
+
send_email: bool = typer.Option(None, "--send-email/--no-send-email", help="If `true`, send an email to the invitee."),
|
|
59
|
+
panelist: bool = typer.Option(None, "--panelist/--no-panelist", help="If `true`, the invitee is a designated panelist for the even"),
|
|
60
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
61
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
62
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
63
|
+
):
|
|
64
|
+
"""Create a Meeting Invitee."""
|
|
65
|
+
api = get_api(debug=debug)
|
|
66
|
+
url = f"https://webexapis.com/v1/meetingInvitees"
|
|
67
|
+
if json_body:
|
|
68
|
+
body = json.loads(json_body)
|
|
69
|
+
else:
|
|
70
|
+
body = {}
|
|
71
|
+
if meeting_id is not None:
|
|
72
|
+
body["meetingId"] = meeting_id
|
|
73
|
+
if email is not None:
|
|
74
|
+
body["email"] = email
|
|
75
|
+
if display_name is not None:
|
|
76
|
+
body["displayName"] = display_name
|
|
77
|
+
if co_host is not None:
|
|
78
|
+
body["coHost"] = co_host
|
|
79
|
+
if host_email is not None:
|
|
80
|
+
body["hostEmail"] = host_email
|
|
81
|
+
if send_email is not None:
|
|
82
|
+
body["sendEmail"] = send_email
|
|
83
|
+
if panelist is not None:
|
|
84
|
+
body["panelist"] = panelist
|
|
85
|
+
_missing = [f for f in ['meetingId', 'email'] if f not in body or body[f] is None]
|
|
86
|
+
if _missing:
|
|
87
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
88
|
+
raise typer.Exit(1)
|
|
89
|
+
try:
|
|
90
|
+
result = api.session.rest_post(url, json=body)
|
|
91
|
+
except WebexError as e:
|
|
92
|
+
handle_rest_error(e)
|
|
93
|
+
if output == "json":
|
|
94
|
+
print_json(result)
|
|
95
|
+
elif isinstance(result, dict) and "id" in result:
|
|
96
|
+
typer.echo(f"Created: {result['id']}")
|
|
97
|
+
elif not result or result == {}:
|
|
98
|
+
typer.echo("Created.")
|
|
99
|
+
else:
|
|
100
|
+
print_json(result)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@app.command("create-bulk-insert")
|
|
105
|
+
def create_bulk_insert(
|
|
106
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="(required) Unique identifier for the meeting to which the people are be"),
|
|
107
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This attribute should on"),
|
|
108
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
109
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
110
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
111
|
+
):
|
|
112
|
+
"""Create Meeting Invitees\n\nExample --json-body:\n '{"meetingId":"...","hostEmail":"...","items":[{"email":"...","displayName":"...","coHost":"...","sendEmail":"...","panelist":"..."}]}'."""
|
|
113
|
+
api = get_api(debug=debug)
|
|
114
|
+
url = f"https://webexapis.com/v1/meetingInvitees/bulkInsert"
|
|
115
|
+
if json_body:
|
|
116
|
+
body = json.loads(json_body)
|
|
117
|
+
else:
|
|
118
|
+
body = {}
|
|
119
|
+
if meeting_id is not None:
|
|
120
|
+
body["meetingId"] = meeting_id
|
|
121
|
+
if host_email is not None:
|
|
122
|
+
body["hostEmail"] = host_email
|
|
123
|
+
_missing = [f for f in ['meetingId'] if f not in body or body[f] is None]
|
|
124
|
+
if _missing:
|
|
125
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
126
|
+
raise typer.Exit(1)
|
|
127
|
+
try:
|
|
128
|
+
result = api.session.rest_post(url, json=body)
|
|
129
|
+
except WebexError as e:
|
|
130
|
+
handle_rest_error(e)
|
|
131
|
+
if output == "json":
|
|
132
|
+
print_json(result)
|
|
133
|
+
elif isinstance(result, dict) and "id" in result:
|
|
134
|
+
typer.echo(f"Created: {result['id']}")
|
|
135
|
+
elif not result or result == {}:
|
|
136
|
+
typer.echo("Created.")
|
|
137
|
+
else:
|
|
138
|
+
print_json(result)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@app.command("show")
|
|
143
|
+
def show(
|
|
144
|
+
meeting_invitee_id: str = typer.Argument(help="meetingInviteeId"),
|
|
145
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
146
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
147
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
148
|
+
):
|
|
149
|
+
"""Get a Meeting Invitee."""
|
|
150
|
+
api = get_api(debug=debug)
|
|
151
|
+
url = f"https://webexapis.com/v1/meetingInvitees/{meeting_invitee_id}"
|
|
152
|
+
params = {}
|
|
153
|
+
if host_email is not None:
|
|
154
|
+
params["hostEmail"] = host_email
|
|
155
|
+
try:
|
|
156
|
+
result = api.session.rest_get(url, params=params)
|
|
157
|
+
except WebexError as e:
|
|
158
|
+
handle_rest_error(e)
|
|
159
|
+
if output == "json":
|
|
160
|
+
print_json(result)
|
|
161
|
+
else:
|
|
162
|
+
if isinstance(result, dict):
|
|
163
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
164
|
+
elif isinstance(result, list):
|
|
165
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
166
|
+
else:
|
|
167
|
+
print_json(result)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@app.command("update")
|
|
172
|
+
def update(
|
|
173
|
+
meeting_invitee_id: str = typer.Argument(help="meetingInviteeId"),
|
|
174
|
+
email: str = typer.Option(None, "--email", help="Email address for meeting invitee."),
|
|
175
|
+
display_name: str = typer.Option(None, "--display-name", help="Display name for meeting invitee. The maximum length of `dis"),
|
|
176
|
+
co_host: bool = typer.Option(None, "--co-host/--no-co-host", help="Whether or not the invitee is a designated alternate host fo"),
|
|
177
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This attribute should on"),
|
|
178
|
+
send_email: bool = typer.Option(None, "--send-email/--no-send-email", help="If `true`, send an email to the invitee."),
|
|
179
|
+
panelist: bool = typer.Option(None, "--panelist/--no-panelist", help="If `true`, the invitee is a designated panelist for the even"),
|
|
180
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
181
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
182
|
+
):
|
|
183
|
+
"""Update a Meeting Invitee."""
|
|
184
|
+
api = get_api(debug=debug)
|
|
185
|
+
url = f"https://webexapis.com/v1/meetingInvitees/{meeting_invitee_id}"
|
|
186
|
+
if json_body:
|
|
187
|
+
body = json.loads(json_body)
|
|
188
|
+
else:
|
|
189
|
+
body = {}
|
|
190
|
+
if email is not None:
|
|
191
|
+
body["email"] = email
|
|
192
|
+
if display_name is not None:
|
|
193
|
+
body["displayName"] = display_name
|
|
194
|
+
if co_host is not None:
|
|
195
|
+
body["coHost"] = co_host
|
|
196
|
+
if host_email is not None:
|
|
197
|
+
body["hostEmail"] = host_email
|
|
198
|
+
if send_email is not None:
|
|
199
|
+
body["sendEmail"] = send_email
|
|
200
|
+
if panelist is not None:
|
|
201
|
+
body["panelist"] = panelist
|
|
202
|
+
try:
|
|
203
|
+
result = api.session.rest_put(url, json=body)
|
|
204
|
+
except WebexError as e:
|
|
205
|
+
handle_rest_error(e)
|
|
206
|
+
typer.echo(f"Updated.")
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@app.command("delete")
|
|
211
|
+
def delete(
|
|
212
|
+
meeting_invitee_id: str = typer.Argument(help="meetingInviteeId"),
|
|
213
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
214
|
+
send_email: str = typer.Option(None, "--send-email", help="If `true`, send an email to the invitee."),
|
|
215
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
216
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
217
|
+
):
|
|
218
|
+
"""Delete a Meeting Invitee."""
|
|
219
|
+
if not force:
|
|
220
|
+
typer.confirm(f"Delete {meeting_invitee_id}?", abort=True)
|
|
221
|
+
api = get_api(debug=debug)
|
|
222
|
+
url = f"https://webexapis.com/v1/meetingInvitees/{meeting_invitee_id}"
|
|
223
|
+
params = {}
|
|
224
|
+
if host_email is not None:
|
|
225
|
+
params["hostEmail"] = host_email
|
|
226
|
+
if send_email is not None:
|
|
227
|
+
params["sendEmail"] = send_email
|
|
228
|
+
try:
|
|
229
|
+
api.session.rest_delete(url, params=params)
|
|
230
|
+
except WebexError as e:
|
|
231
|
+
handle_rest_error(e)
|
|
232
|
+
typer.echo(f"Deleted: {meeting_invitee_id}")
|
|
233
|
+
|
|
234
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
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 Meetings meeting-messages.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("delete")
|
|
12
|
+
def delete(
|
|
13
|
+
meeting_message_id: str = typer.Argument(help="meetingMessageId"),
|
|
14
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
15
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
16
|
+
):
|
|
17
|
+
"""Delete a Meeting Message."""
|
|
18
|
+
if not force:
|
|
19
|
+
typer.confirm(f"Delete {meeting_message_id}?", abort=True)
|
|
20
|
+
api = get_api(debug=debug)
|
|
21
|
+
url = f"https://webexapis.com/v1/meeting/messages/{meeting_message_id}"
|
|
22
|
+
try:
|
|
23
|
+
api.session.rest_delete(url)
|
|
24
|
+
except WebexError as e:
|
|
25
|
+
handle_rest_error(e)
|
|
26
|
+
typer.echo(f"Deleted: {meeting_message_id}")
|
|
27
|
+
|
|
28
|
+
|
|
@@ -0,0 +1,278 @@
|
|
|
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 Meetings meeting-participants.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
meeting_id: str = typer.Option(..., "--meeting-id", help="The unique identifier for the meeting. Please note that curr"),
|
|
14
|
+
breakout_session_id: str = typer.Option(None, "--breakout-session-id", help="The unique identifier for a breakout session which happened"),
|
|
15
|
+
meeting_start_time_from: str = typer.Option(None, "--meeting-start-time-from", help="Meetings start from the specified date and time(exclusive) i"),
|
|
16
|
+
meeting_start_time_to: str = typer.Option(None, "--meeting-start-time-to", help="Meetings start before the specified date and time(exclusive)"),
|
|
17
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
18
|
+
join_time_from: str = typer.Option(None, "--join-time-from", help="The time participants join a meeting starts from the specifi"),
|
|
19
|
+
join_time_to: str = typer.Option(None, "--join-time-to", help="The time participants join a meeting before the specified da"),
|
|
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
|
+
"""List Meeting Participants."""
|
|
26
|
+
api = get_api(debug=debug)
|
|
27
|
+
url = f"https://webexapis.com/v1/meetingParticipants"
|
|
28
|
+
params = {}
|
|
29
|
+
if meeting_id is not None:
|
|
30
|
+
params["meetingId"] = meeting_id
|
|
31
|
+
if breakout_session_id is not None:
|
|
32
|
+
params["breakoutSessionId"] = breakout_session_id
|
|
33
|
+
if meeting_start_time_from is not None:
|
|
34
|
+
params["meetingStartTimeFrom"] = meeting_start_time_from
|
|
35
|
+
if meeting_start_time_to is not None:
|
|
36
|
+
params["meetingStartTimeTo"] = meeting_start_time_to
|
|
37
|
+
if host_email is not None:
|
|
38
|
+
params["hostEmail"] = host_email
|
|
39
|
+
if join_time_from is not None:
|
|
40
|
+
params["joinTimeFrom"] = join_time_from
|
|
41
|
+
if join_time_to is not None:
|
|
42
|
+
params["joinTimeTo"] = join_time_to
|
|
43
|
+
if limit > 0:
|
|
44
|
+
params["max"] = limit
|
|
45
|
+
if offset > 0:
|
|
46
|
+
params["start"] = offset
|
|
47
|
+
result = None
|
|
48
|
+
try:
|
|
49
|
+
result = api.session.rest_get(url, params=params)
|
|
50
|
+
except WebexError as e:
|
|
51
|
+
handle_rest_error(e)
|
|
52
|
+
result = result or []
|
|
53
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
54
|
+
if output == "json":
|
|
55
|
+
print_json(items)
|
|
56
|
+
else:
|
|
57
|
+
print_table(items, columns=[('ID', 'id'), ('Display Name', 'displayName'), ('Email', 'email'), ('Joined', 'joinedTime'), ('State', 'state')], limit=limit)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@app.command("create")
|
|
62
|
+
def create(
|
|
63
|
+
meeting_id: str = typer.Option(..., "--meeting-id", help="The unique identifier for the meeting."),
|
|
64
|
+
meeting_start_time_from: str = typer.Option(None, "--meeting-start-time-from", help="Meetings start from the specified date and time(exclusive) i"),
|
|
65
|
+
meeting_start_time_to: str = typer.Option(None, "--meeting-start-time-to", help="Meetings start before the specified date and time(exclusive)"),
|
|
66
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
67
|
+
join_time_from: str = typer.Option(None, "--join-time-from", help="The time participants join a meeting starts from the specifi"),
|
|
68
|
+
join_time_to: str = typer.Option(None, "--join-time-to", help="The time participants join a meeting before the specified da"),
|
|
69
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
70
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
71
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
72
|
+
):
|
|
73
|
+
"""Query Meeting Participants with Email\n\nExample --json-body:\n '{"emails":["..."],"joinTimeFrom":"...","joinTimeTo":"..."}'."""
|
|
74
|
+
api = get_api(debug=debug)
|
|
75
|
+
url = f"https://webexapis.com/v1/meetingParticipants/query"
|
|
76
|
+
params = {}
|
|
77
|
+
if meeting_id is not None:
|
|
78
|
+
params["meetingId"] = meeting_id
|
|
79
|
+
if meeting_start_time_from is not None:
|
|
80
|
+
params["meetingStartTimeFrom"] = meeting_start_time_from
|
|
81
|
+
if meeting_start_time_to is not None:
|
|
82
|
+
params["meetingStartTimeTo"] = meeting_start_time_to
|
|
83
|
+
if host_email is not None:
|
|
84
|
+
params["hostEmail"] = host_email
|
|
85
|
+
if json_body:
|
|
86
|
+
body = json.loads(json_body)
|
|
87
|
+
else:
|
|
88
|
+
body = {}
|
|
89
|
+
if join_time_from is not None:
|
|
90
|
+
body["joinTimeFrom"] = join_time_from
|
|
91
|
+
if join_time_to is not None:
|
|
92
|
+
body["joinTimeTo"] = join_time_to
|
|
93
|
+
try:
|
|
94
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
95
|
+
except WebexError as e:
|
|
96
|
+
handle_rest_error(e)
|
|
97
|
+
if output == "json":
|
|
98
|
+
print_json(result)
|
|
99
|
+
elif isinstance(result, dict) and "id" in result:
|
|
100
|
+
typer.echo(f"Created: {result['id']}")
|
|
101
|
+
elif not result or result == {}:
|
|
102
|
+
typer.echo("Created.")
|
|
103
|
+
else:
|
|
104
|
+
print_json(result)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@app.command("show")
|
|
109
|
+
def show(
|
|
110
|
+
participant_id: str = typer.Argument(help="participantId"),
|
|
111
|
+
host_email: str = typer.Option(None, "--host-email", help="Email address for the meeting host. This parameter is only u"),
|
|
112
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
113
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
114
|
+
):
|
|
115
|
+
"""Get Meeting Participant Details."""
|
|
116
|
+
api = get_api(debug=debug)
|
|
117
|
+
url = f"https://webexapis.com/v1/meetingParticipants/{participant_id}"
|
|
118
|
+
params = {}
|
|
119
|
+
if host_email is not None:
|
|
120
|
+
params["hostEmail"] = host_email
|
|
121
|
+
try:
|
|
122
|
+
result = api.session.rest_get(url, params=params)
|
|
123
|
+
except WebexError as e:
|
|
124
|
+
handle_rest_error(e)
|
|
125
|
+
if output == "json":
|
|
126
|
+
print_json(result)
|
|
127
|
+
else:
|
|
128
|
+
if isinstance(result, dict):
|
|
129
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
130
|
+
elif isinstance(result, list):
|
|
131
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
132
|
+
else:
|
|
133
|
+
print_json(result)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@app.command("update")
|
|
138
|
+
def update(
|
|
139
|
+
participant_id: str = typer.Argument(help="participantId"),
|
|
140
|
+
muted: bool = typer.Option(None, "--muted/--no-muted", help="If `true`, participant is muted."),
|
|
141
|
+
admit: bool = typer.Option(None, "--admit/--no-admit", help="If `true` the participant admit a participant in the lobby t"),
|
|
142
|
+
expel: bool = typer.Option(None, "--expel/--no-expel", help="If `true` the participant is expelled from the meeting."),
|
|
143
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
144
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
145
|
+
):
|
|
146
|
+
"""Update a Participant."""
|
|
147
|
+
api = get_api(debug=debug)
|
|
148
|
+
url = f"https://webexapis.com/v1/meetingParticipants/{participant_id}"
|
|
149
|
+
if json_body:
|
|
150
|
+
body = json.loads(json_body)
|
|
151
|
+
else:
|
|
152
|
+
body = {}
|
|
153
|
+
if muted is not None:
|
|
154
|
+
body["muted"] = muted
|
|
155
|
+
if admit is not None:
|
|
156
|
+
body["admit"] = admit
|
|
157
|
+
if expel is not None:
|
|
158
|
+
body["expel"] = expel
|
|
159
|
+
try:
|
|
160
|
+
result = api.session.rest_put(url, json=body)
|
|
161
|
+
except WebexError as e:
|
|
162
|
+
handle_rest_error(e)
|
|
163
|
+
typer.echo(f"Updated.")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@app.command("create-admit")
|
|
168
|
+
def create_admit(
|
|
169
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
170
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
171
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
172
|
+
):
|
|
173
|
+
"""Admit Participants\n\nExample --json-body:\n '{"items":[{"participantId":"...","breakoutSessionId":"..."}]}'."""
|
|
174
|
+
api = get_api(debug=debug)
|
|
175
|
+
url = f"https://webexapis.com/v1/meetingParticipants/admit"
|
|
176
|
+
if json_body:
|
|
177
|
+
body = json.loads(json_body)
|
|
178
|
+
else:
|
|
179
|
+
body = {}
|
|
180
|
+
try:
|
|
181
|
+
result = api.session.rest_post(url, json=body)
|
|
182
|
+
except WebexError as e:
|
|
183
|
+
handle_rest_error(e)
|
|
184
|
+
if output == "json":
|
|
185
|
+
print_json(result)
|
|
186
|
+
elif isinstance(result, dict) and "id" in result:
|
|
187
|
+
typer.echo(f"Created: {result['id']}")
|
|
188
|
+
elif not result or result == {}:
|
|
189
|
+
typer.echo("Created.")
|
|
190
|
+
else:
|
|
191
|
+
print_json(result)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@app.command("create-callout")
|
|
196
|
+
def create_callout(
|
|
197
|
+
meeting_id: str = typer.Option(None, "--meeting-id", help="Unique identifier of the meeting to which the SIP participan"),
|
|
198
|
+
meeting_number: str = typer.Option(None, "--meeting-number", help="Number of the meeting to which the SIP participant is to be"),
|
|
199
|
+
address: str = typer.Option(None, "--address", help="(required) SIP address of the invited SIP participant."),
|
|
200
|
+
address_type: str = typer.Option(None, "--address-type", help="Choices: sipAddress"),
|
|
201
|
+
invitation_correlation_id: str = typer.Option(None, "--invitation-correlation-id", help="An internal ID that is associated with the call-out invitati"),
|
|
202
|
+
display_name: str = typer.Option(None, "--display-name", help="(required) The display name of the invited SIP participant. The maximum"),
|
|
203
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
204
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
205
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
206
|
+
):
|
|
207
|
+
"""Call Out a SIP Participant."""
|
|
208
|
+
api = get_api(debug=debug)
|
|
209
|
+
url = f"https://webexapis.com/v1/meetingParticipants/callout"
|
|
210
|
+
if json_body:
|
|
211
|
+
body = json.loads(json_body)
|
|
212
|
+
else:
|
|
213
|
+
body = {}
|
|
214
|
+
if meeting_id is not None:
|
|
215
|
+
body["meetingId"] = meeting_id
|
|
216
|
+
if meeting_number is not None:
|
|
217
|
+
body["meetingNumber"] = meeting_number
|
|
218
|
+
if address is not None:
|
|
219
|
+
body["address"] = address
|
|
220
|
+
if address_type is not None:
|
|
221
|
+
body["addressType"] = address_type
|
|
222
|
+
if invitation_correlation_id is not None:
|
|
223
|
+
body["invitationCorrelationId"] = invitation_correlation_id
|
|
224
|
+
if display_name is not None:
|
|
225
|
+
body["displayName"] = display_name
|
|
226
|
+
_missing = [f for f in ['address', 'displayName'] if f not in body or body[f] is None]
|
|
227
|
+
if _missing:
|
|
228
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
229
|
+
raise typer.Exit(1)
|
|
230
|
+
try:
|
|
231
|
+
result = api.session.rest_post(url, json=body)
|
|
232
|
+
except WebexError as e:
|
|
233
|
+
handle_rest_error(e)
|
|
234
|
+
if output == "json":
|
|
235
|
+
print_json(result)
|
|
236
|
+
elif isinstance(result, dict) and "id" in result:
|
|
237
|
+
typer.echo(f"Created: {result['id']}")
|
|
238
|
+
elif not result or result == {}:
|
|
239
|
+
typer.echo("Created.")
|
|
240
|
+
else:
|
|
241
|
+
print_json(result)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@app.command("create-cancel-callout")
|
|
246
|
+
def create_cancel_callout(
|
|
247
|
+
participant_id: str = typer.Option(None, "--participant-id", help="(required) ID of the SIP participant on whom the callout is to be cance"),
|
|
248
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
249
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
250
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
251
|
+
):
|
|
252
|
+
"""Cancel Calling Out a SIP Participant."""
|
|
253
|
+
api = get_api(debug=debug)
|
|
254
|
+
url = f"https://webexapis.com/v1/meetingParticipants/cancelCallout"
|
|
255
|
+
if json_body:
|
|
256
|
+
body = json.loads(json_body)
|
|
257
|
+
else:
|
|
258
|
+
body = {}
|
|
259
|
+
if participant_id is not None:
|
|
260
|
+
body["participantId"] = participant_id
|
|
261
|
+
_missing = [f for f in ['participantId'] if f not in body or body[f] is None]
|
|
262
|
+
if _missing:
|
|
263
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
264
|
+
raise typer.Exit(1)
|
|
265
|
+
try:
|
|
266
|
+
result = api.session.rest_post(url, json=body)
|
|
267
|
+
except WebexError as e:
|
|
268
|
+
handle_rest_error(e)
|
|
269
|
+
if output == "json":
|
|
270
|
+
print_json(result)
|
|
271
|
+
elif isinstance(result, dict) and "id" in result:
|
|
272
|
+
typer.echo(f"Created: {result['id']}")
|
|
273
|
+
elif not result or result == {}:
|
|
274
|
+
typer.echo("Created.")
|
|
275
|
+
else:
|
|
276
|
+
print_json(result)
|
|
277
|
+
|
|
278
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
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 Meetings meeting-polls.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
meeting_id: str = typer.Option(..., "--meeting-id", help="A unique identifier for the [meeting instance](/docs/meeting"),
|
|
14
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
15
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
16
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
17
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
18
|
+
):
|
|
19
|
+
"""List Meeting Polls."""
|
|
20
|
+
api = get_api(debug=debug)
|
|
21
|
+
url = f"https://webexapis.com/v1/meetings/polls"
|
|
22
|
+
params = {}
|
|
23
|
+
if meeting_id is not None:
|
|
24
|
+
params["meetingId"] = meeting_id
|
|
25
|
+
if limit > 0:
|
|
26
|
+
params["max"] = limit
|
|
27
|
+
if offset > 0:
|
|
28
|
+
params["start"] = offset
|
|
29
|
+
result = None
|
|
30
|
+
try:
|
|
31
|
+
result = api.session.rest_get(url, params=params)
|
|
32
|
+
except WebexError as e:
|
|
33
|
+
handle_rest_error(e)
|
|
34
|
+
result = result or []
|
|
35
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
36
|
+
if output == "json":
|
|
37
|
+
print_json(items)
|
|
38
|
+
else:
|
|
39
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.command("list-poll-results")
|
|
44
|
+
def list_poll_results(
|
|
45
|
+
meeting_id: str = typer.Option(..., "--meeting-id", help="A unique identifier for the [meeting instance](/docs/meeting"),
|
|
46
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
47
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
48
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
49
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
50
|
+
):
|
|
51
|
+
"""Get Meeting PollResults."""
|
|
52
|
+
api = get_api(debug=debug)
|
|
53
|
+
url = f"https://webexapis.com/v1/meetings/pollResults"
|
|
54
|
+
params = {}
|
|
55
|
+
if meeting_id is not None:
|
|
56
|
+
params["meetingId"] = meeting_id
|
|
57
|
+
if limit > 0:
|
|
58
|
+
params["max"] = limit
|
|
59
|
+
if offset > 0:
|
|
60
|
+
params["start"] = offset
|
|
61
|
+
try:
|
|
62
|
+
if limit > 0:
|
|
63
|
+
result = api.session.rest_get(url, params=params)
|
|
64
|
+
result = result or {}
|
|
65
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
66
|
+
else:
|
|
67
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
68
|
+
except WebexError as e:
|
|
69
|
+
handle_rest_error(e)
|
|
70
|
+
if output == "json":
|
|
71
|
+
print_json(items)
|
|
72
|
+
else:
|
|
73
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@app.command("list-respondents")
|
|
78
|
+
def list_respondents(
|
|
79
|
+
poll_id: str = typer.Argument(help="pollId"),
|
|
80
|
+
question_id: str = typer.Argument(help="questionId"),
|
|
81
|
+
meeting_id: str = typer.Option(..., "--meeting-id", help="A unique identifier for the [meeting instance](/docs/meeting"),
|
|
82
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
83
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
84
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
85
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
86
|
+
):
|
|
87
|
+
"""List Respondents of a Question."""
|
|
88
|
+
api = get_api(debug=debug)
|
|
89
|
+
url = f"https://webexapis.com/v1/meetings/polls/{poll_id}/questions/{question_id}/respondents"
|
|
90
|
+
params = {}
|
|
91
|
+
if meeting_id is not None:
|
|
92
|
+
params["meetingId"] = meeting_id
|
|
93
|
+
if limit > 0:
|
|
94
|
+
params["max"] = limit
|
|
95
|
+
if offset > 0:
|
|
96
|
+
params["start"] = offset
|
|
97
|
+
try:
|
|
98
|
+
if limit > 0:
|
|
99
|
+
result = api.session.rest_get(url, params=params)
|
|
100
|
+
result = result or {}
|
|
101
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
102
|
+
else:
|
|
103
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
104
|
+
except WebexError as e:
|
|
105
|
+
handle_rest_error(e)
|
|
106
|
+
if output == "json":
|
|
107
|
+
print_json(items)
|
|
108
|
+
else:
|
|
109
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
110
|
+
|
|
111
|
+
|