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,216 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
from wxcli.config import resolve_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling partner-tags.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
type_param: str = typer.Option(..., "--type", help="List tags associated with an organization."),
|
|
15
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
16
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
17
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
18
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
19
|
+
):
|
|
20
|
+
"""Retrieve all customer tags."""
|
|
21
|
+
api = get_api(debug=debug)
|
|
22
|
+
url = f"https://webexapis.com/v1/partner/tags"
|
|
23
|
+
params = {}
|
|
24
|
+
if type_param is not None:
|
|
25
|
+
params["type"] = type_param
|
|
26
|
+
if limit > 0:
|
|
27
|
+
params["max"] = limit
|
|
28
|
+
if offset > 0:
|
|
29
|
+
params["start"] = offset
|
|
30
|
+
result = None
|
|
31
|
+
try:
|
|
32
|
+
result = api.session.rest_get(url, params=params)
|
|
33
|
+
except WebexError as e:
|
|
34
|
+
handle_rest_error(e)
|
|
35
|
+
result = result or []
|
|
36
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
37
|
+
if output == "json":
|
|
38
|
+
print_json(items)
|
|
39
|
+
else:
|
|
40
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@app.command("create")
|
|
45
|
+
def create(
|
|
46
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
47
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
48
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
49
|
+
):
|
|
50
|
+
"""Create or Replace existing customer tags with the provided ones\n\nExample --json-body:\n '{"tags":[{"name":"...","description":"..."}]}'."""
|
|
51
|
+
api = get_api(debug=debug)
|
|
52
|
+
org_id = resolve_org_id(api.session)
|
|
53
|
+
url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}/assignTags"
|
|
54
|
+
if json_body:
|
|
55
|
+
body = json.loads(json_body)
|
|
56
|
+
else:
|
|
57
|
+
body = {}
|
|
58
|
+
try:
|
|
59
|
+
result = api.session.rest_post(url, json=body)
|
|
60
|
+
except WebexError as e:
|
|
61
|
+
handle_rest_error(e)
|
|
62
|
+
if output == "json":
|
|
63
|
+
print_json(result)
|
|
64
|
+
elif isinstance(result, dict) and "id" in result:
|
|
65
|
+
typer.echo(f"Created: {result['id']}")
|
|
66
|
+
elif not result or result == {}:
|
|
67
|
+
typer.echo("Created.")
|
|
68
|
+
else:
|
|
69
|
+
print_json(result)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@app.command("show")
|
|
74
|
+
def show(
|
|
75
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
76
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
77
|
+
):
|
|
78
|
+
"""Get customer organization's tags."""
|
|
79
|
+
api = get_api(debug=debug)
|
|
80
|
+
org_id = resolve_org_id(api.session)
|
|
81
|
+
url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}"
|
|
82
|
+
try:
|
|
83
|
+
result = api.session.rest_get(url)
|
|
84
|
+
except WebexError as e:
|
|
85
|
+
handle_rest_error(e)
|
|
86
|
+
if output == "json":
|
|
87
|
+
print_json(result)
|
|
88
|
+
else:
|
|
89
|
+
if isinstance(result, dict):
|
|
90
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
91
|
+
elif isinstance(result, list):
|
|
92
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
93
|
+
else:
|
|
94
|
+
print_json(result)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@app.command("list-organizations")
|
|
99
|
+
def list_organizations(
|
|
100
|
+
tags: str = typer.Option(..., "--tags", help="A comma separated list of tags to filter by."),
|
|
101
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
102
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
103
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
104
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
105
|
+
):
|
|
106
|
+
"""Fetch all customers for a given set of tags."""
|
|
107
|
+
api = get_api(debug=debug)
|
|
108
|
+
url = f"https://webexapis.com/v1/partner/tags/organizations"
|
|
109
|
+
params = {}
|
|
110
|
+
if tags is not None:
|
|
111
|
+
params["tags"] = tags
|
|
112
|
+
if limit > 0:
|
|
113
|
+
params["max"] = limit
|
|
114
|
+
if offset > 0:
|
|
115
|
+
params["start"] = offset
|
|
116
|
+
result = None
|
|
117
|
+
try:
|
|
118
|
+
result = api.session.rest_get(url, params=params)
|
|
119
|
+
except WebexError as e:
|
|
120
|
+
handle_rest_error(e)
|
|
121
|
+
result = result or []
|
|
122
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
123
|
+
if output == "json":
|
|
124
|
+
print_json(items)
|
|
125
|
+
else:
|
|
126
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@app.command("create-assign-tags")
|
|
131
|
+
def create_assign_tags(
|
|
132
|
+
subscription_id: str = typer.Argument(help="subscriptionId"),
|
|
133
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
134
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
135
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
136
|
+
):
|
|
137
|
+
"""Create or Replace existing subscription tags with the provided ones\n\nExample --json-body:\n '{"tags":[{"name":"...","description":"..."}]}'."""
|
|
138
|
+
api = get_api(debug=debug)
|
|
139
|
+
org_id = resolve_org_id(api.session)
|
|
140
|
+
url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}/subscriptions/{subscription_id}/assignTags"
|
|
141
|
+
if json_body:
|
|
142
|
+
body = json.loads(json_body)
|
|
143
|
+
else:
|
|
144
|
+
body = {}
|
|
145
|
+
try:
|
|
146
|
+
result = api.session.rest_post(url, json=body)
|
|
147
|
+
except WebexError as e:
|
|
148
|
+
handle_rest_error(e)
|
|
149
|
+
if output == "json":
|
|
150
|
+
print_json(result)
|
|
151
|
+
elif isinstance(result, dict) and "id" in result:
|
|
152
|
+
typer.echo(f"Created: {result['id']}")
|
|
153
|
+
elif not result or result == {}:
|
|
154
|
+
typer.echo("Created.")
|
|
155
|
+
else:
|
|
156
|
+
print_json(result)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@app.command("list-subscriptions")
|
|
161
|
+
def list_subscriptions(
|
|
162
|
+
tags: str = typer.Option(..., "--tags", help="A comma separated list of tags to filter by."),
|
|
163
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
164
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
165
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
166
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
167
|
+
):
|
|
168
|
+
"""Subscription List on a given tag name or a set of tags."""
|
|
169
|
+
api = get_api(debug=debug)
|
|
170
|
+
url = f"https://webexapis.com/v1/partner/tags/subscriptions"
|
|
171
|
+
params = {}
|
|
172
|
+
if tags is not None:
|
|
173
|
+
params["tags"] = tags
|
|
174
|
+
if limit > 0:
|
|
175
|
+
params["max"] = limit
|
|
176
|
+
if offset > 0:
|
|
177
|
+
params["start"] = offset
|
|
178
|
+
result = None
|
|
179
|
+
try:
|
|
180
|
+
result = api.session.rest_get(url, params=params)
|
|
181
|
+
except WebexError as e:
|
|
182
|
+
handle_rest_error(e)
|
|
183
|
+
result = result or []
|
|
184
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
185
|
+
if output == "json":
|
|
186
|
+
print_json(items)
|
|
187
|
+
else:
|
|
188
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@app.command("show-subscriptions")
|
|
193
|
+
def show_subscriptions(
|
|
194
|
+
subscription_id: str = typer.Argument(help="subscriptionId"),
|
|
195
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
196
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
197
|
+
):
|
|
198
|
+
"""Fetch a Subscription."""
|
|
199
|
+
api = get_api(debug=debug)
|
|
200
|
+
org_id = resolve_org_id(api.session)
|
|
201
|
+
url = f"https://webexapis.com/v1/partner/tags/organizations/{org_id}/subscriptions/{subscription_id}"
|
|
202
|
+
try:
|
|
203
|
+
result = api.session.rest_get(url)
|
|
204
|
+
except WebexError as e:
|
|
205
|
+
handle_rest_error(e)
|
|
206
|
+
if output == "json":
|
|
207
|
+
print_json(result)
|
|
208
|
+
else:
|
|
209
|
+
if isinstance(result, dict):
|
|
210
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
211
|
+
elif isinstance(result, list):
|
|
212
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
213
|
+
else:
|
|
214
|
+
print_json(result)
|
|
215
|
+
|
|
216
|
+
|
wxcli/commands/people.py
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
from wxcli.config import get_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling people.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
email: str = typer.Option(None, "--email", help="List people with this email address. For non-admin requests,"),
|
|
15
|
+
display_name: str = typer.Option(None, "--display-name", help="List people whose name starts with this string. For non-admi"),
|
|
16
|
+
id_param: str = typer.Option(None, "--id", help="List people by ID. Accepts up to 85 person IDs separated by"),
|
|
17
|
+
roles: str = typer.Option(None, "--roles", help="List of roleIds separated by commas."),
|
|
18
|
+
calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
|
|
19
|
+
location_id: str = typer.Option(None, "--location-id", help="List people present in this location."),
|
|
20
|
+
exclude_status: str = typer.Option(None, "--exclude-status", help="Omit people status/availability to enhance query performance"),
|
|
21
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
22
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
23
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
24
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
25
|
+
):
|
|
26
|
+
"""List People."""
|
|
27
|
+
api = get_api(debug=debug)
|
|
28
|
+
url = f"https://webexapis.com/v1/people"
|
|
29
|
+
params = {}
|
|
30
|
+
if email is not None:
|
|
31
|
+
params["email"] = email
|
|
32
|
+
if display_name is not None:
|
|
33
|
+
params["displayName"] = display_name
|
|
34
|
+
if id_param is not None:
|
|
35
|
+
params["id"] = id_param
|
|
36
|
+
if roles is not None:
|
|
37
|
+
params["roles"] = roles
|
|
38
|
+
if calling_data is not None:
|
|
39
|
+
params["callingData"] = calling_data
|
|
40
|
+
if location_id is not None:
|
|
41
|
+
params["locationId"] = location_id
|
|
42
|
+
if exclude_status is not None:
|
|
43
|
+
params["excludeStatus"] = exclude_status
|
|
44
|
+
if limit > 0:
|
|
45
|
+
params["max"] = limit
|
|
46
|
+
if offset > 0:
|
|
47
|
+
params["start"] = offset
|
|
48
|
+
org_id = get_org_id()
|
|
49
|
+
if org_id is not None:
|
|
50
|
+
params["orgId"] = org_id
|
|
51
|
+
try:
|
|
52
|
+
if limit > 0:
|
|
53
|
+
result = api.session.rest_get(url, params=params)
|
|
54
|
+
result = result or {}
|
|
55
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
56
|
+
else:
|
|
57
|
+
items = list(api.session.follow_pagination(url=url, params=params, item_key="items"))
|
|
58
|
+
except WebexError as e:
|
|
59
|
+
handle_rest_error(e)
|
|
60
|
+
if output == "json":
|
|
61
|
+
print_json(items)
|
|
62
|
+
else:
|
|
63
|
+
print_table(items, columns=[('ID', 'id'), ('Display Name', 'displayName'), ('Email', 'emails[0]')], limit=limit)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@app.command("create")
|
|
68
|
+
def create(
|
|
69
|
+
calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
|
|
70
|
+
min_response: str = typer.Option(None, "--min-response", help="Set to `true` to improve performance by omitting person deta"),
|
|
71
|
+
extension: str = typer.Option(None, "--extension", help="Webex Calling extension of the person. This is only settable"),
|
|
72
|
+
location_id: str = typer.Option(None, "--location-id", help="The ID of the location for this person."),
|
|
73
|
+
display_name: str = typer.Option(None, "--display-name", help="The full name of the person."),
|
|
74
|
+
first_name: str = typer.Option(None, "--first-name", help="The first name of the person."),
|
|
75
|
+
last_name: str = typer.Option(None, "--last-name", help="The last name of the person."),
|
|
76
|
+
avatar: str = typer.Option(None, "--avatar", help="The URL to the person's avatar in PNG format."),
|
|
77
|
+
org_id: str = typer.Option(None, "--org-id", help="The ID of the organization to which this person belongs."),
|
|
78
|
+
department: str = typer.Option(None, "--department", help="The business department the user belongs to."),
|
|
79
|
+
manager: str = typer.Option(None, "--manager", help="A manager identifier."),
|
|
80
|
+
manager_id: str = typer.Option(None, "--manager-id", help="Person ID of the manager."),
|
|
81
|
+
title: str = typer.Option(None, "--title", help="The person's title."),
|
|
82
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
83
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
84
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
85
|
+
):
|
|
86
|
+
"""Create a Person\n\nExample --json-body:\n '{"emails":["..."],"phoneNumbers":[{"type":"...","value":"..."}],"extension":"...","locationId":"...","displayName":"...","firstName":"...","lastName":"...","avatar":"..."}'."""
|
|
87
|
+
api = get_api(debug=debug)
|
|
88
|
+
url = f"https://webexapis.com/v1/people"
|
|
89
|
+
params = {}
|
|
90
|
+
if calling_data is not None:
|
|
91
|
+
params["callingData"] = calling_data
|
|
92
|
+
if min_response is not None:
|
|
93
|
+
params["minResponse"] = min_response
|
|
94
|
+
if json_body:
|
|
95
|
+
body = json.loads(json_body)
|
|
96
|
+
else:
|
|
97
|
+
body = {}
|
|
98
|
+
if extension is not None:
|
|
99
|
+
body["extension"] = extension
|
|
100
|
+
if location_id is not None:
|
|
101
|
+
body["locationId"] = location_id
|
|
102
|
+
if display_name is not None:
|
|
103
|
+
body["displayName"] = display_name
|
|
104
|
+
if first_name is not None:
|
|
105
|
+
body["firstName"] = first_name
|
|
106
|
+
if last_name is not None:
|
|
107
|
+
body["lastName"] = last_name
|
|
108
|
+
if avatar is not None:
|
|
109
|
+
body["avatar"] = avatar
|
|
110
|
+
if org_id is not None:
|
|
111
|
+
body["orgId"] = org_id
|
|
112
|
+
if department is not None:
|
|
113
|
+
body["department"] = department
|
|
114
|
+
if manager is not None:
|
|
115
|
+
body["manager"] = manager
|
|
116
|
+
if manager_id is not None:
|
|
117
|
+
body["managerId"] = manager_id
|
|
118
|
+
if title is not None:
|
|
119
|
+
body["title"] = title
|
|
120
|
+
try:
|
|
121
|
+
result = api.session.rest_post(url, json=body, params=params)
|
|
122
|
+
except WebexError as e:
|
|
123
|
+
handle_rest_error(e)
|
|
124
|
+
if output == "json":
|
|
125
|
+
print_json(result)
|
|
126
|
+
elif isinstance(result, dict) and "id" in result:
|
|
127
|
+
typer.echo(f"Created: {result['id']}")
|
|
128
|
+
elif not result or result == {}:
|
|
129
|
+
typer.echo("Created.")
|
|
130
|
+
else:
|
|
131
|
+
print_json(result)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@app.command("show")
|
|
136
|
+
def show(
|
|
137
|
+
person_id: str = typer.Argument(help="personId"),
|
|
138
|
+
calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
|
|
139
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
140
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
141
|
+
):
|
|
142
|
+
"""Get Person Details."""
|
|
143
|
+
api = get_api(debug=debug)
|
|
144
|
+
url = f"https://webexapis.com/v1/people/{person_id}"
|
|
145
|
+
params = {}
|
|
146
|
+
if calling_data is not None:
|
|
147
|
+
params["callingData"] = calling_data
|
|
148
|
+
try:
|
|
149
|
+
result = api.session.rest_get(url, params=params)
|
|
150
|
+
except WebexError as e:
|
|
151
|
+
handle_rest_error(e)
|
|
152
|
+
if output == "json":
|
|
153
|
+
print_json(result)
|
|
154
|
+
else:
|
|
155
|
+
if isinstance(result, dict):
|
|
156
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
157
|
+
elif isinstance(result, list):
|
|
158
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
159
|
+
else:
|
|
160
|
+
print_json(result)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@app.command("update")
|
|
165
|
+
def update(
|
|
166
|
+
person_id: str = typer.Argument(help="personId"),
|
|
167
|
+
calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
|
|
168
|
+
show_all_types: str = typer.Option(None, "--show-all-types", help="Include additional user data like `#attendee` role."),
|
|
169
|
+
min_response: str = typer.Option(None, "--min-response", help="Set to `true` to improve performance by omitting person deta"),
|
|
170
|
+
extension: str = typer.Option(None, "--extension", help="Webex Calling extension of the person. This is only settable"),
|
|
171
|
+
location_id: str = typer.Option(None, "--location-id", help="The ID of the location for this person."),
|
|
172
|
+
display_name: str = typer.Option(None, "--display-name", help="The full name of the person."),
|
|
173
|
+
first_name: str = typer.Option(None, "--first-name", help="The first name of the person."),
|
|
174
|
+
last_name: str = typer.Option(None, "--last-name", help="The last name of the person."),
|
|
175
|
+
nick_name: str = typer.Option(None, "--nick-name", help="The nickname of the person if configured. This cannot be ove"),
|
|
176
|
+
avatar: str = typer.Option(None, "--avatar", help="The URL to the person's avatar in PNG format."),
|
|
177
|
+
org_id: str = typer.Option(None, "--org-id", help="The ID of the organization to which this person belongs."),
|
|
178
|
+
department: str = typer.Option(None, "--department", help="The business department the user belongs to."),
|
|
179
|
+
manager: str = typer.Option(None, "--manager", help="A manager identifier."),
|
|
180
|
+
manager_id: str = typer.Option(None, "--manager-id", help="Person ID of the manager."),
|
|
181
|
+
title: str = typer.Option(None, "--title", help="The person's title."),
|
|
182
|
+
login_enabled: bool = typer.Option(None, "--login-enabled/--no-login-enabled", help="Whether or not the user is allowed to use Webex. This proper"),
|
|
183
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
184
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
185
|
+
):
|
|
186
|
+
"""Update a Person\n\nExample --json-body:\n '{"displayName":"...","emails":["..."],"phoneNumbers":[{"type":"...","value":"..."}],"extension":"...","locationId":"...","firstName":"...","lastName":"...","nickName":"..."}'."""
|
|
187
|
+
api = get_api(debug=debug)
|
|
188
|
+
url = f"https://webexapis.com/v1/people/{person_id}"
|
|
189
|
+
params = {}
|
|
190
|
+
if calling_data is not None:
|
|
191
|
+
params["callingData"] = calling_data
|
|
192
|
+
if show_all_types is not None:
|
|
193
|
+
params["showAllTypes"] = show_all_types
|
|
194
|
+
if min_response is not None:
|
|
195
|
+
params["minResponse"] = min_response
|
|
196
|
+
if json_body:
|
|
197
|
+
body = json.loads(json_body)
|
|
198
|
+
else:
|
|
199
|
+
body = {}
|
|
200
|
+
if extension is not None:
|
|
201
|
+
body["extension"] = extension
|
|
202
|
+
if location_id is not None:
|
|
203
|
+
body["locationId"] = location_id
|
|
204
|
+
if display_name is not None:
|
|
205
|
+
body["displayName"] = display_name
|
|
206
|
+
if first_name is not None:
|
|
207
|
+
body["firstName"] = first_name
|
|
208
|
+
if last_name is not None:
|
|
209
|
+
body["lastName"] = last_name
|
|
210
|
+
if nick_name is not None:
|
|
211
|
+
body["nickName"] = nick_name
|
|
212
|
+
if avatar is not None:
|
|
213
|
+
body["avatar"] = avatar
|
|
214
|
+
if org_id is not None:
|
|
215
|
+
body["orgId"] = org_id
|
|
216
|
+
if department is not None:
|
|
217
|
+
body["department"] = department
|
|
218
|
+
if manager is not None:
|
|
219
|
+
body["manager"] = manager
|
|
220
|
+
if manager_id is not None:
|
|
221
|
+
body["managerId"] = manager_id
|
|
222
|
+
if title is not None:
|
|
223
|
+
body["title"] = title
|
|
224
|
+
if login_enabled is not None:
|
|
225
|
+
body["loginEnabled"] = login_enabled
|
|
226
|
+
try:
|
|
227
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
228
|
+
except WebexError as e:
|
|
229
|
+
handle_rest_error(e)
|
|
230
|
+
typer.echo(f"Updated.")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
@app.command("delete")
|
|
235
|
+
def delete(
|
|
236
|
+
person_id: str = typer.Argument(help="personId"),
|
|
237
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
238
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
239
|
+
):
|
|
240
|
+
"""Delete a Person."""
|
|
241
|
+
if not force:
|
|
242
|
+
typer.confirm(f"Delete {person_id}?", abort=True)
|
|
243
|
+
api = get_api(debug=debug)
|
|
244
|
+
url = f"https://webexapis.com/v1/people/{person_id}"
|
|
245
|
+
try:
|
|
246
|
+
api.session.rest_delete(url)
|
|
247
|
+
except WebexError as e:
|
|
248
|
+
handle_rest_error(e)
|
|
249
|
+
typer.echo(f"Deleted: {person_id}")
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@app.command("show-me")
|
|
254
|
+
def show_me(
|
|
255
|
+
calling_data: str = typer.Option(None, "--calling-data", help="Include Webex Calling user details in the response."),
|
|
256
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
257
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
258
|
+
):
|
|
259
|
+
"""Get My Own Details."""
|
|
260
|
+
api = get_api(debug=debug)
|
|
261
|
+
url = f"https://webexapis.com/v1/people/me"
|
|
262
|
+
params = {}
|
|
263
|
+
if calling_data is not None:
|
|
264
|
+
params["callingData"] = calling_data
|
|
265
|
+
try:
|
|
266
|
+
result = api.session.rest_get(url, params=params)
|
|
267
|
+
except WebexError as e:
|
|
268
|
+
handle_rest_error(e)
|
|
269
|
+
if output == "json":
|
|
270
|
+
print_json(result)
|
|
271
|
+
else:
|
|
272
|
+
if isinstance(result, dict):
|
|
273
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
274
|
+
elif isinstance(result, list):
|
|
275
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
276
|
+
else:
|
|
277
|
+
print_json(result)
|
|
278
|
+
|
|
279
|
+
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
from wxcli.config import get_org_id
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
app = typer.Typer(help="Manage Webex Calling person-call-settings.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@app.command("list")
|
|
13
|
+
def cmd_list(
|
|
14
|
+
person_id: str = typer.Argument(help="personId"),
|
|
15
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
16
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
17
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
18
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
19
|
+
):
|
|
20
|
+
"""Retrieve a Person's Monitoring Settings."""
|
|
21
|
+
api = get_api(debug=debug)
|
|
22
|
+
url = f"https://webexapis.com/v1/people/{person_id}/features/monitoring"
|
|
23
|
+
params = {}
|
|
24
|
+
if limit > 0:
|
|
25
|
+
params["max"] = limit
|
|
26
|
+
if offset > 0:
|
|
27
|
+
params["start"] = offset
|
|
28
|
+
org_id = get_org_id()
|
|
29
|
+
if org_id is not None:
|
|
30
|
+
params["orgId"] = org_id
|
|
31
|
+
result = None
|
|
32
|
+
try:
|
|
33
|
+
result = api.session.rest_get(url, params=params)
|
|
34
|
+
except WebexError as e:
|
|
35
|
+
handle_rest_error(e)
|
|
36
|
+
result = result or []
|
|
37
|
+
items = result.get("monitoredElements", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
38
|
+
if output == "json":
|
|
39
|
+
print_json(items)
|
|
40
|
+
else:
|
|
41
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@app.command("update")
|
|
46
|
+
def update(
|
|
47
|
+
person_id: str = typer.Argument(help="personId"),
|
|
48
|
+
enable_call_park_notification: bool = typer.Option(None, "--enable-call-park-notification/--no-enable-call-park-notification", help="Call park notification is enabled or disabled."),
|
|
49
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
50
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
51
|
+
):
|
|
52
|
+
"""Modify Monitoring Settings for a Person\n\nExample --json-body:\n '{"enableCallParkNotification":true,"monitoredElements":["..."]}'."""
|
|
53
|
+
api = get_api(debug=debug)
|
|
54
|
+
url = f"https://webexapis.com/v1/people/{person_id}/features/monitoring"
|
|
55
|
+
params = {}
|
|
56
|
+
org_id = get_org_id()
|
|
57
|
+
if org_id is not None:
|
|
58
|
+
params["orgId"] = org_id
|
|
59
|
+
if json_body:
|
|
60
|
+
body = json.loads(json_body)
|
|
61
|
+
else:
|
|
62
|
+
body = {}
|
|
63
|
+
if enable_call_park_notification is not None:
|
|
64
|
+
body["enableCallParkNotification"] = enable_call_park_notification
|
|
65
|
+
try:
|
|
66
|
+
result = api.session.rest_put(url, json=body, params=params)
|
|
67
|
+
except WebexError as e:
|
|
68
|
+
handle_rest_error(e)
|
|
69
|
+
typer.echo(f"Updated.")
|
|
70
|
+
|
|
71
|
+
|