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,126 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
app = typer.Typer(help="Manage Webex Calling broadworks-billing-reports.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
before: str = typer.Option(None, "--before", help="Only include billing reports created before this date."),
|
|
14
|
+
after: str = typer.Option(None, "--after", help="Only include billing reports created after this date."),
|
|
15
|
+
sort_by: str = typer.Option(None, "--sort-by", help="Sort the reports. + Members: + id + status + bi"),
|
|
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 BroadWorks Billing Reports."""
|
|
22
|
+
api = get_api(debug=debug)
|
|
23
|
+
url = f"https://webexapis.com/v1/broadworks/billing/reports"
|
|
24
|
+
params = {}
|
|
25
|
+
if before is not None:
|
|
26
|
+
params["before"] = before
|
|
27
|
+
if after is not None:
|
|
28
|
+
params["after"] = after
|
|
29
|
+
if sort_by is not None:
|
|
30
|
+
params["sortBy"] = sort_by
|
|
31
|
+
if limit > 0:
|
|
32
|
+
params["max"] = limit
|
|
33
|
+
if offset > 0:
|
|
34
|
+
params["start"] = offset
|
|
35
|
+
result = None
|
|
36
|
+
try:
|
|
37
|
+
result = api.session.rest_get(url, params=params)
|
|
38
|
+
except WebexError as e:
|
|
39
|
+
handle_rest_error(e)
|
|
40
|
+
result = result or []
|
|
41
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
42
|
+
if output == "json":
|
|
43
|
+
print_json(items)
|
|
44
|
+
else:
|
|
45
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@app.command("create")
|
|
50
|
+
def create(
|
|
51
|
+
billing_period: str = typer.Option(None, "--billing-period", help="(required) The year and month (`YYYY-MM`) for which the billing report"),
|
|
52
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
53
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
54
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
55
|
+
):
|
|
56
|
+
"""Create a BroadWorks Billing Report."""
|
|
57
|
+
api = get_api(debug=debug)
|
|
58
|
+
url = f"https://webexapis.com/v1/broadworks/billing/reports"
|
|
59
|
+
if json_body:
|
|
60
|
+
body = json.loads(json_body)
|
|
61
|
+
else:
|
|
62
|
+
body = {}
|
|
63
|
+
if billing_period is not None:
|
|
64
|
+
body["billingPeriod"] = billing_period
|
|
65
|
+
_missing = [f for f in ['billingPeriod'] if f not in body or body[f] is None]
|
|
66
|
+
if _missing:
|
|
67
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
68
|
+
raise typer.Exit(1)
|
|
69
|
+
try:
|
|
70
|
+
result = api.session.rest_post(url, json=body)
|
|
71
|
+
except WebexError as e:
|
|
72
|
+
handle_rest_error(e)
|
|
73
|
+
if output == "json":
|
|
74
|
+
print_json(result)
|
|
75
|
+
elif isinstance(result, dict) and "id" in result:
|
|
76
|
+
typer.echo(f"Created: {result['id']}")
|
|
77
|
+
elif not result or result == {}:
|
|
78
|
+
typer.echo("Created.")
|
|
79
|
+
else:
|
|
80
|
+
print_json(result)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@app.command("show")
|
|
85
|
+
def show(
|
|
86
|
+
id: str = typer.Argument(help="id"),
|
|
87
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
88
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
89
|
+
):
|
|
90
|
+
"""Get a BroadWorks Billing Report."""
|
|
91
|
+
api = get_api(debug=debug)
|
|
92
|
+
url = f"https://webexapis.com/v1/broadworks/billing/reports/{id}"
|
|
93
|
+
try:
|
|
94
|
+
result = api.session.rest_get(url)
|
|
95
|
+
except WebexError as e:
|
|
96
|
+
handle_rest_error(e)
|
|
97
|
+
if output == "json":
|
|
98
|
+
print_json(result)
|
|
99
|
+
else:
|
|
100
|
+
if isinstance(result, dict):
|
|
101
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
102
|
+
elif isinstance(result, list):
|
|
103
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
104
|
+
else:
|
|
105
|
+
print_json(result)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@app.command("delete")
|
|
110
|
+
def delete(
|
|
111
|
+
id: str = typer.Argument(help="id"),
|
|
112
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
113
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
114
|
+
):
|
|
115
|
+
"""Delete a BroadWorks Billing Report."""
|
|
116
|
+
if not force:
|
|
117
|
+
typer.confirm(f"Delete {id}?", abort=True)
|
|
118
|
+
api = get_api(debug=debug)
|
|
119
|
+
url = f"https://webexapis.com/v1/broadworks/billing/reports/{id}"
|
|
120
|
+
try:
|
|
121
|
+
api.session.rest_delete(url)
|
|
122
|
+
except WebexError as e:
|
|
123
|
+
handle_rest_error(e)
|
|
124
|
+
typer.echo(f"Deleted: {id}")
|
|
125
|
+
|
|
126
|
+
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
app = typer.Typer(help="Manage Webex Calling broadworks-enterprises.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("show")
|
|
12
|
+
def show(
|
|
13
|
+
sp_enterprise_id: str = typer.Option(None, "--sp-enterprise-id", help="The Service Provider supplied unique identifier for the subs"),
|
|
14
|
+
starts_with: str = typer.Option(None, "--starts-with", help="The starting string of the enterprise identifiers to match a"),
|
|
15
|
+
max: str = typer.Option(None, "--max", help="Limit the number of enterprises returned in the search, up t"),
|
|
16
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
17
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
18
|
+
):
|
|
19
|
+
"""List BroadWorks Enterprises."""
|
|
20
|
+
api = get_api(debug=debug)
|
|
21
|
+
url = f"https://webexapis.com/v1/broadworks/enterprises"
|
|
22
|
+
params = {}
|
|
23
|
+
if sp_enterprise_id is not None:
|
|
24
|
+
params["spEnterpriseId"] = sp_enterprise_id
|
|
25
|
+
if starts_with is not None:
|
|
26
|
+
params["startsWith"] = starts_with
|
|
27
|
+
if max is not None:
|
|
28
|
+
params["max"] = max
|
|
29
|
+
try:
|
|
30
|
+
result = api.session.rest_get(url, params=params)
|
|
31
|
+
except WebexError as e:
|
|
32
|
+
handle_rest_error(e)
|
|
33
|
+
if output == "json":
|
|
34
|
+
print_json(result)
|
|
35
|
+
else:
|
|
36
|
+
if isinstance(result, dict):
|
|
37
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
38
|
+
elif isinstance(result, list):
|
|
39
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
40
|
+
else:
|
|
41
|
+
print_json(result)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@app.command("show-broadworks-directory-sync")
|
|
46
|
+
def show_broadworks_directory_sync(
|
|
47
|
+
id: str = typer.Argument(help="id"),
|
|
48
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
49
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
50
|
+
):
|
|
51
|
+
"""Get Directory Sync Status for an Enterprise."""
|
|
52
|
+
api = get_api(debug=debug)
|
|
53
|
+
url = f"https://webexapis.com/v1/broadworks/enterprises/{id}/broadworksDirectorySync"
|
|
54
|
+
try:
|
|
55
|
+
result = api.session.rest_get(url)
|
|
56
|
+
except WebexError as e:
|
|
57
|
+
handle_rest_error(e)
|
|
58
|
+
if output == "json":
|
|
59
|
+
print_json(result)
|
|
60
|
+
else:
|
|
61
|
+
if isinstance(result, dict):
|
|
62
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
63
|
+
elif isinstance(result, list):
|
|
64
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
65
|
+
else:
|
|
66
|
+
print_json(result)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@app.command("create")
|
|
71
|
+
def create(
|
|
72
|
+
id: str = typer.Argument(help="id"),
|
|
73
|
+
sync_status: str = typer.Option(None, "--sync-status", help="(required) At this time, the only value allowed for this attribute is `"),
|
|
74
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
75
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
76
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
77
|
+
):
|
|
78
|
+
"""Trigger Directory Sync for an Enterprise."""
|
|
79
|
+
api = get_api(debug=debug)
|
|
80
|
+
url = f"https://webexapis.com/v1/broadworks/enterprises/{id}/broadworksDirectorySync"
|
|
81
|
+
if json_body:
|
|
82
|
+
body = json.loads(json_body)
|
|
83
|
+
else:
|
|
84
|
+
body = {}
|
|
85
|
+
if sync_status is not None:
|
|
86
|
+
body["syncStatus"] = sync_status
|
|
87
|
+
_missing = [f for f in ['syncStatus'] if f not in body or body[f] is None]
|
|
88
|
+
if _missing:
|
|
89
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
90
|
+
raise typer.Exit(1)
|
|
91
|
+
try:
|
|
92
|
+
result = api.session.rest_post(url, json=body)
|
|
93
|
+
except WebexError as e:
|
|
94
|
+
handle_rest_error(e)
|
|
95
|
+
if output == "json":
|
|
96
|
+
print_json(result)
|
|
97
|
+
elif isinstance(result, dict) and "id" in result:
|
|
98
|
+
typer.echo(f"Created: {result['id']}")
|
|
99
|
+
elif not result or result == {}:
|
|
100
|
+
typer.echo("Created.")
|
|
101
|
+
else:
|
|
102
|
+
print_json(result)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@app.command("update")
|
|
107
|
+
def update(
|
|
108
|
+
id: str = typer.Argument(help="id"),
|
|
109
|
+
enable_dir_sync: bool = typer.Option(None, "--enable-dir-sync/--no-enable-dir-sync", help="The toggle to enable/disable directory sync."),
|
|
110
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
111
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
112
|
+
):
|
|
113
|
+
"""Update Directory Sync for a BroadWorks Enterprise."""
|
|
114
|
+
api = get_api(debug=debug)
|
|
115
|
+
url = f"https://webexapis.com/v1/broadworks/enterprises/{id}/broadworksDirectorySync"
|
|
116
|
+
if json_body:
|
|
117
|
+
body = json.loads(json_body)
|
|
118
|
+
else:
|
|
119
|
+
body = {}
|
|
120
|
+
if enable_dir_sync is not None:
|
|
121
|
+
body["enableDirSync"] = enable_dir_sync
|
|
122
|
+
try:
|
|
123
|
+
result = api.session.rest_put(url, json=body)
|
|
124
|
+
except WebexError as e:
|
|
125
|
+
handle_rest_error(e)
|
|
126
|
+
typer.echo(f"Updated.")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@app.command("create-external-user")
|
|
131
|
+
def create_external_user(
|
|
132
|
+
id: str = typer.Argument(help="id"),
|
|
133
|
+
user_id: str = typer.Option(None, "--user-id", help="The user ID of the Broadworks user to be synced (A non-webex"),
|
|
134
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
135
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
136
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
137
|
+
):
|
|
138
|
+
"""Trigger Directory Sync for a User."""
|
|
139
|
+
api = get_api(debug=debug)
|
|
140
|
+
url = f"https://webexapis.com/v1/broadworks/enterprises/{id}/broadworksDirectorySync/externalUser"
|
|
141
|
+
if json_body:
|
|
142
|
+
body = json.loads(json_body)
|
|
143
|
+
else:
|
|
144
|
+
body = {}
|
|
145
|
+
if user_id is not None:
|
|
146
|
+
body["userId"] = user_id
|
|
147
|
+
try:
|
|
148
|
+
result = api.session.rest_post(url, json=body)
|
|
149
|
+
except WebexError as e:
|
|
150
|
+
handle_rest_error(e)
|
|
151
|
+
if output == "json":
|
|
152
|
+
print_json(result)
|
|
153
|
+
elif isinstance(result, dict) and "id" in result:
|
|
154
|
+
typer.echo(f"Created: {result['id']}")
|
|
155
|
+
elif not result or result == {}:
|
|
156
|
+
typer.echo("Created.")
|
|
157
|
+
else:
|
|
158
|
+
print_json(result)
|
|
159
|
+
|
|
160
|
+
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import typer
|
|
3
|
+
from wxcli.auth import get_api
|
|
4
|
+
from wxcli.errors import WebexError, handle_rest_error
|
|
5
|
+
from wxcli.output import print_table, print_json
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
app = typer.Typer(help="Manage Webex Calling broadworks-subscribers.")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.command("list")
|
|
12
|
+
def cmd_list(
|
|
13
|
+
user_id: str = typer.Option(None, "--user-id", help="The user ID of the subscriber on BroadWorks."),
|
|
14
|
+
person_id: str = typer.Option(None, "--person-id", help="The Person ID of the Webex subscriber."),
|
|
15
|
+
email: str = typer.Option(None, "--email", help="The email address of the subscriber."),
|
|
16
|
+
provisioning_id: str = typer.Option(None, "--provisioning-id", help="The Provisioning ID associated with this subscriber."),
|
|
17
|
+
sp_enterprise_id: str = typer.Option(None, "--sp-enterprise-id", help="The Service Provider supplied unique identifier for the subs"),
|
|
18
|
+
last_status_change: str = typer.Option(None, "--last-status-change", help="Only include subscribers with a provisioning status change a"),
|
|
19
|
+
status: str = typer.Option(None, "--status", help="Choices: pending_email_input, pending_email_validation, pending_user_migration, provisioning, provisioned, updating, error"),
|
|
20
|
+
after: str = typer.Option(None, "--after", help="Only include subscribers created after this date and time. E"),
|
|
21
|
+
self_activated: str = typer.Option(None, "--self-activated", help="Indicates if the subscriber was self activated, rather than"),
|
|
22
|
+
output: str = typer.Option("table", "--output", "-o", help="Output format: table|json"),
|
|
23
|
+
limit: int = typer.Option(0, "--limit", help="Max results (0=all for paginated endpoints, API default for non-paginated)"),
|
|
24
|
+
offset: int = typer.Option(0, "--offset", help="Start offset"),
|
|
25
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
26
|
+
):
|
|
27
|
+
"""List BroadWorks Subscribers."""
|
|
28
|
+
api = get_api(debug=debug)
|
|
29
|
+
url = f"https://webexapis.com/v1/broadworks/subscribers"
|
|
30
|
+
params = {}
|
|
31
|
+
if user_id is not None:
|
|
32
|
+
params["userId"] = user_id
|
|
33
|
+
if person_id is not None:
|
|
34
|
+
params["personId"] = person_id
|
|
35
|
+
if email is not None:
|
|
36
|
+
params["email"] = email
|
|
37
|
+
if provisioning_id is not None:
|
|
38
|
+
params["provisioningId"] = provisioning_id
|
|
39
|
+
if sp_enterprise_id is not None:
|
|
40
|
+
params["spEnterpriseId"] = sp_enterprise_id
|
|
41
|
+
if last_status_change is not None:
|
|
42
|
+
params["lastStatusChange"] = last_status_change
|
|
43
|
+
if status is not None:
|
|
44
|
+
params["status"] = status
|
|
45
|
+
if after is not None:
|
|
46
|
+
params["after"] = after
|
|
47
|
+
if self_activated is not None:
|
|
48
|
+
params["selfActivated"] = self_activated
|
|
49
|
+
if limit > 0:
|
|
50
|
+
params["max"] = limit
|
|
51
|
+
if offset > 0:
|
|
52
|
+
params["start"] = offset
|
|
53
|
+
result = None
|
|
54
|
+
try:
|
|
55
|
+
result = api.session.rest_get(url, params=params)
|
|
56
|
+
except WebexError as e:
|
|
57
|
+
handle_rest_error(e)
|
|
58
|
+
result = result or []
|
|
59
|
+
items = result.get("items", result.get("data", result if isinstance(result, list) else [])) if isinstance(result, dict) else (result if isinstance(result, list) else [])
|
|
60
|
+
if output == "json":
|
|
61
|
+
print_json(items)
|
|
62
|
+
else:
|
|
63
|
+
print_table(items, columns=[("ID", "id"), ("Name", "name")], limit=limit)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@app.command("create")
|
|
68
|
+
def create(
|
|
69
|
+
provisioning_id: str = typer.Option(None, "--provisioning-id", help="(required) This Provisioning ID defines how this subscriber is to be pr"),
|
|
70
|
+
user_id: str = typer.Option(None, "--user-id", help="(required) The user ID of the subscriber on BroadWorks."),
|
|
71
|
+
sp_enterprise_id: str = typer.Option(None, "--sp-enterprise-id", help="(required) The Service Provider supplied unique identifier for the subs"),
|
|
72
|
+
first_name: str = typer.Option(None, "--first-name", help="(required) The first name of the subscriber."),
|
|
73
|
+
last_name: str = typer.Option(None, "--last-name", help="(required) The last name of the subscriber."),
|
|
74
|
+
package: str = typer.Option(None, "--package", help="(required) Choices: softphone, basic, standard, premium"),
|
|
75
|
+
primary_phone_number: str = typer.Option(None, "--primary-phone-number", help="The primary phone number configured against the subscriber o"),
|
|
76
|
+
mobile_phone_number: str = typer.Option(None, "--mobile-phone-number", help="The mobile phone number configured against the subscriber on"),
|
|
77
|
+
extension: str = typer.Option(None, "--extension", help="The extension number configured against the subscriber on Br"),
|
|
78
|
+
email: str = typer.Option(None, "--email", help="The email address of the subscriber (mandatory for the trust"),
|
|
79
|
+
language: str = typer.Option(None, "--language", help="The {ISO-639-1}_{ISO-3166} or {ISO-639-1} locale or language"),
|
|
80
|
+
timezone: str = typer.Option(None, "--timezone", help="The time zone associated with the subscriber. Refer to the ["),
|
|
81
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
82
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
83
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
84
|
+
):
|
|
85
|
+
"""Provision a BroadWorks Subscriber."""
|
|
86
|
+
api = get_api(debug=debug)
|
|
87
|
+
url = f"https://webexapis.com/v1/broadworks/subscribers"
|
|
88
|
+
if json_body:
|
|
89
|
+
body = json.loads(json_body)
|
|
90
|
+
else:
|
|
91
|
+
body = {}
|
|
92
|
+
if provisioning_id is not None:
|
|
93
|
+
body["provisioningId"] = provisioning_id
|
|
94
|
+
if user_id is not None:
|
|
95
|
+
body["userId"] = user_id
|
|
96
|
+
if sp_enterprise_id is not None:
|
|
97
|
+
body["spEnterpriseId"] = sp_enterprise_id
|
|
98
|
+
if first_name is not None:
|
|
99
|
+
body["firstName"] = first_name
|
|
100
|
+
if last_name is not None:
|
|
101
|
+
body["lastName"] = last_name
|
|
102
|
+
if package is not None:
|
|
103
|
+
body["package"] = package
|
|
104
|
+
if primary_phone_number is not None:
|
|
105
|
+
body["primaryPhoneNumber"] = primary_phone_number
|
|
106
|
+
if mobile_phone_number is not None:
|
|
107
|
+
body["mobilePhoneNumber"] = mobile_phone_number
|
|
108
|
+
if extension is not None:
|
|
109
|
+
body["extension"] = extension
|
|
110
|
+
if email is not None:
|
|
111
|
+
body["email"] = email
|
|
112
|
+
if language is not None:
|
|
113
|
+
body["language"] = language
|
|
114
|
+
if timezone is not None:
|
|
115
|
+
body["timezone"] = timezone
|
|
116
|
+
_missing = [f for f in ['provisioningId', 'userId', 'spEnterpriseId', 'firstName', 'lastName', 'package'] if f not in body or body[f] is None]
|
|
117
|
+
if _missing:
|
|
118
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
119
|
+
raise typer.Exit(1)
|
|
120
|
+
try:
|
|
121
|
+
result = api.session.rest_post(url, json=body)
|
|
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
|
+
subscriber_id: str = typer.Argument(help="subscriberId"),
|
|
138
|
+
output: str = typer.Option("json", "--output", "-o", help="Output format: table|json"),
|
|
139
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
140
|
+
):
|
|
141
|
+
"""Get a BroadWorks Subscriber."""
|
|
142
|
+
api = get_api(debug=debug)
|
|
143
|
+
url = f"https://webexapis.com/v1/broadworks/subscribers/{subscriber_id}"
|
|
144
|
+
try:
|
|
145
|
+
result = api.session.rest_get(url)
|
|
146
|
+
except WebexError as e:
|
|
147
|
+
handle_rest_error(e)
|
|
148
|
+
if output == "json":
|
|
149
|
+
print_json(result)
|
|
150
|
+
else:
|
|
151
|
+
if isinstance(result, dict):
|
|
152
|
+
print_table([result], columns=[("Key", ""), ("Value", "")], limit=0)
|
|
153
|
+
elif isinstance(result, list):
|
|
154
|
+
print_table(result, columns=[("ID", "id"), ("Name", "name")], limit=0)
|
|
155
|
+
else:
|
|
156
|
+
print_json(result)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@app.command("update")
|
|
161
|
+
def update(
|
|
162
|
+
subscriber_id: str = typer.Argument(help="subscriberId"),
|
|
163
|
+
user_id: str = typer.Option(None, "--user-id", help="The user ID of the subscriber on BroadWorks."),
|
|
164
|
+
first_name: str = typer.Option(None, "--first-name", help="The first name of the subscriber."),
|
|
165
|
+
last_name: str = typer.Option(None, "--last-name", help="The last name of the subscriber."),
|
|
166
|
+
primary_phone_number: str = typer.Option(None, "--primary-phone-number", help="The primary phone number configured against the subscriber o"),
|
|
167
|
+
mobile_phone_number: str = typer.Option(None, "--mobile-phone-number", help="The mobile phone number configured against the subscriber on"),
|
|
168
|
+
extension: str = typer.Option(None, "--extension", help="The extension number configured against the subscriber on Br"),
|
|
169
|
+
timezone: str = typer.Option(None, "--timezone", help="The time zone associated with the subscriber. Refer to the ["),
|
|
170
|
+
package: str = typer.Option(None, "--package", help="The Webex for BroadWorks Package to be assigned to the subsc"),
|
|
171
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
172
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
173
|
+
):
|
|
174
|
+
"""Update a BroadWorks Subscriber."""
|
|
175
|
+
api = get_api(debug=debug)
|
|
176
|
+
url = f"https://webexapis.com/v1/broadworks/subscribers/{subscriber_id}"
|
|
177
|
+
if json_body:
|
|
178
|
+
body = json.loads(json_body)
|
|
179
|
+
else:
|
|
180
|
+
body = {}
|
|
181
|
+
if user_id is not None:
|
|
182
|
+
body["userId"] = user_id
|
|
183
|
+
if first_name is not None:
|
|
184
|
+
body["firstName"] = first_name
|
|
185
|
+
if last_name is not None:
|
|
186
|
+
body["lastName"] = last_name
|
|
187
|
+
if primary_phone_number is not None:
|
|
188
|
+
body["primaryPhoneNumber"] = primary_phone_number
|
|
189
|
+
if mobile_phone_number is not None:
|
|
190
|
+
body["mobilePhoneNumber"] = mobile_phone_number
|
|
191
|
+
if extension is not None:
|
|
192
|
+
body["extension"] = extension
|
|
193
|
+
if timezone is not None:
|
|
194
|
+
body["timezone"] = timezone
|
|
195
|
+
if package is not None:
|
|
196
|
+
body["package"] = package
|
|
197
|
+
try:
|
|
198
|
+
result = api.session.rest_put(url, json=body)
|
|
199
|
+
except WebexError as e:
|
|
200
|
+
handle_rest_error(e)
|
|
201
|
+
typer.echo(f"Updated.")
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@app.command("delete")
|
|
206
|
+
def delete(
|
|
207
|
+
subscriber_id: str = typer.Argument(help="subscriberId"),
|
|
208
|
+
force: bool = typer.Option(False, "--force", help="Skip confirmation"),
|
|
209
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
210
|
+
):
|
|
211
|
+
"""Remove a BroadWorks Subscriber."""
|
|
212
|
+
if not force:
|
|
213
|
+
typer.confirm(f"Delete {subscriber_id}?", abort=True)
|
|
214
|
+
api = get_api(debug=debug)
|
|
215
|
+
url = f"https://webexapis.com/v1/broadworks/subscribers/{subscriber_id}"
|
|
216
|
+
try:
|
|
217
|
+
api.session.rest_delete(url)
|
|
218
|
+
except WebexError as e:
|
|
219
|
+
handle_rest_error(e)
|
|
220
|
+
typer.echo(f"Deleted: {subscriber_id}")
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@app.command("create-validate")
|
|
225
|
+
def create_validate(
|
|
226
|
+
provisioning_id: str = typer.Option(None, "--provisioning-id", help="Provisioning ID that defines how this subscriber is to be pr"),
|
|
227
|
+
user_id: str = typer.Option(None, "--user-id", help="The user ID of the Broadworks subscriber."),
|
|
228
|
+
sp_enterprise_id: str = typer.Option(None, "--sp-enterprise-id", help="The Service Provider supplied unique identifier for the subs"),
|
|
229
|
+
first_name: str = typer.Option(None, "--first-name", help="The first name of the subscriber."),
|
|
230
|
+
last_name: str = typer.Option(None, "--last-name", help="The last name of the subscriber."),
|
|
231
|
+
package: str = typer.Option(None, "--package", help="Choices: softphone, basic, standard, premium"),
|
|
232
|
+
primary_phone_number: str = typer.Option(None, "--primary-phone-number", help="The primary phone number configured for the subscriber on Br"),
|
|
233
|
+
mobile_phone_number: str = typer.Option(None, "--mobile-phone-number", help="The mobile phone number configured against the subscriber on"),
|
|
234
|
+
extension: str = typer.Option(None, "--extension", help="The extension number configured against the subscriber on Br"),
|
|
235
|
+
email: str = typer.Option(None, "--email", help="(required) The email address of the subscriber."),
|
|
236
|
+
language: str = typer.Option(None, "--language", help="The ISO 639-1 language code associated with the subscriber."),
|
|
237
|
+
timezone: str = typer.Option(None, "--timezone", help="The time zone associated with the subscriber. Refer to the ["),
|
|
238
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
239
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
240
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
241
|
+
):
|
|
242
|
+
"""Precheck a Broadworks Subscriber Provisioning\n\nExample --json-body:\n '{"email":"...","provisioningId":"...","userId":"...","spEnterpriseId":"...","firstName":"...","lastName":"...","package":"softphone","primaryPhoneNumber":"..."}'."""
|
|
243
|
+
api = get_api(debug=debug)
|
|
244
|
+
url = f"https://webexapis.com/v1/broadworks/subscribers/validate"
|
|
245
|
+
if json_body:
|
|
246
|
+
body = json.loads(json_body)
|
|
247
|
+
else:
|
|
248
|
+
body = {}
|
|
249
|
+
if provisioning_id is not None:
|
|
250
|
+
body["provisioningId"] = provisioning_id
|
|
251
|
+
if user_id is not None:
|
|
252
|
+
body["userId"] = user_id
|
|
253
|
+
if sp_enterprise_id is not None:
|
|
254
|
+
body["spEnterpriseId"] = sp_enterprise_id
|
|
255
|
+
if first_name is not None:
|
|
256
|
+
body["firstName"] = first_name
|
|
257
|
+
if last_name is not None:
|
|
258
|
+
body["lastName"] = last_name
|
|
259
|
+
if package is not None:
|
|
260
|
+
body["package"] = package
|
|
261
|
+
if primary_phone_number is not None:
|
|
262
|
+
body["primaryPhoneNumber"] = primary_phone_number
|
|
263
|
+
if mobile_phone_number is not None:
|
|
264
|
+
body["mobilePhoneNumber"] = mobile_phone_number
|
|
265
|
+
if extension is not None:
|
|
266
|
+
body["extension"] = extension
|
|
267
|
+
if email is not None:
|
|
268
|
+
body["email"] = email
|
|
269
|
+
if language is not None:
|
|
270
|
+
body["language"] = language
|
|
271
|
+
if timezone is not None:
|
|
272
|
+
body["timezone"] = timezone
|
|
273
|
+
_missing = [f for f in ['email'] if f not in body or body[f] is None]
|
|
274
|
+
if _missing:
|
|
275
|
+
typer.echo("Error: Missing required fields: " + ", ".join(_missing), err=True)
|
|
276
|
+
raise typer.Exit(1)
|
|
277
|
+
try:
|
|
278
|
+
result = api.session.rest_post(url, json=body)
|
|
279
|
+
except WebexError as e:
|
|
280
|
+
handle_rest_error(e)
|
|
281
|
+
if output == "json":
|
|
282
|
+
print_json(result)
|
|
283
|
+
elif isinstance(result, dict) and "id" in result:
|
|
284
|
+
typer.echo(f"Created: {result['id']}")
|
|
285
|
+
elif not result or result == {}:
|
|
286
|
+
typer.echo("Created.")
|
|
287
|
+
else:
|
|
288
|
+
print_json(result)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@app.command("create-consent-move")
|
|
293
|
+
def create_consent_move(
|
|
294
|
+
subscriber_id: str = typer.Argument(help="subscriberId"),
|
|
295
|
+
json_body: str = typer.Option(None, "--json-body", help="Full JSON body (overrides other options)"),
|
|
296
|
+
output: str = typer.Option("id", "--output", "-o", help="Output format: id|json"),
|
|
297
|
+
debug: bool = typer.Option(False, "--debug"),
|
|
298
|
+
):
|
|
299
|
+
"""Send Consent User Move Email to Pending Broadworks Subscribers."""
|
|
300
|
+
api = get_api(debug=debug)
|
|
301
|
+
url = f"https://webexapis.com/v1/subscribers/{subscriber_id}/emails/consentMove"
|
|
302
|
+
if json_body:
|
|
303
|
+
body = json.loads(json_body)
|
|
304
|
+
else:
|
|
305
|
+
body = {}
|
|
306
|
+
try:
|
|
307
|
+
result = api.session.rest_post(url, json=body)
|
|
308
|
+
except WebexError as e:
|
|
309
|
+
handle_rest_error(e)
|
|
310
|
+
if output == "json":
|
|
311
|
+
print_json(result)
|
|
312
|
+
elif isinstance(result, dict) and "id" in result:
|
|
313
|
+
typer.echo(f"Created: {result['id']}")
|
|
314
|
+
elif not result or result == {}:
|
|
315
|
+
typer.echo("Created.")
|
|
316
|
+
else:
|
|
317
|
+
print_json(result)
|
|
318
|
+
|
|
319
|
+
|